测试引论

黑盒测试&白盒测试

黑盒测试

黑盒测试又称功能测试,在测试过程中不对程序的内部进行分析,而只对程序的输入和输出进行测试

image-20200531202329881

这种测试不需要我们中间参与编写任何代码,传入参数值后查看程序是否正常达到预期值即可

白盒测试

白盒测试又称为结构测试,程序对测试者是可见的,我们清楚代码的结构,在使用白盒测试时,测试人员必须检查程序的内部结构,从测试程序的逻辑开始,一步一步地检查传入参数并且查看程序的运行过输出结果,最终得出测试数据

image-20200531202615957

这也就是白盒测试叫穷举路径测试的原因

单元测试

单元测试是指对软件中最小的可测试单元进行检查和验证,至于单元的大小或者范围,并没有一个明确的标准,单元可以是一个函数、方法、类、功能模块或者子系统

单元测试通常和白盒测试联系到一起,如果单从概念上来讲两者是有区别的,不过我们通常说的单元测试和白盒测试都认为是和代码有关系的,所以某些语境下也认为这两者是同一个东西;还有一种理解方式:单元测试和白盒测试就是对开发人员所编写的代码进行测试

Junit单元测试编码规范

  • 类名:定义测试类,类名由被测试类名Test构成,例如CalculatorTest
  • 包名:定义的测试类需要被放在xxx.xxx.xxx.test包中,例如package com.mylifes1110.test
  • 方法名:测试方法的方法名有两种定义方式test测试方法测试方法,例如testAddadd
  • 返回值:由于我们的方法只是在类中进行测试,可以独立运行,所以不需要处理任何返回值,返回值被设定为void
  • 参数列表:由于我们的方法是用来测试的,所以参数列表也为空
  • @Test注解:测试是需要运行来完成的,如果我们只有一个main方法,显然我们还是需要繁琐地去不断“运行”-“注释”,所以我们在测试方法上加上@Test注解,只要是加过该注解的方法,都是可以单独运行的
    • @Test注解需要我们导入jar包才能使用的
    • @Test(expected=XX.class),表示某个异常即使发生,也是可以被通过测试的
    • @Test(timeout=毫秒)表示如果测试方法在指定的时间内没有完成,就会强制停止

Assert断言

断言方法 描述
assertNull(Object) 检查对象是否为空
assertNotNull(Object) 检查对象是否不为空
assertEqual(long,long) 检查long的值是否相等
assertEqual(double,double,double) 检查double的值在精度范围内是否相等
assertFalse(boolean) 检查条件是否为假
assertTrue(boolean) 检查条件是否为真
assertSame(Object,Object) 检查两个对象引用是否引用同一对象
assertNotSame(Object,Object) 检查两个对象引用是否没引用同一对象

方法调用时机

img

可以使用@BeforeClass@Before@After@AfterClass来为测试类的方法,设定对应的调用时机

测试套件

测试嵌套,即将测试类封装起来,只要运行测试套件,就能运行所有的测试类了

@RunWith(Suite.class)
@Suite.SuiteClasses({Test1.class, Test2.class,...})
public class SuiteTest {
    // 这是一个不包含任何方法的空类
}

参数化设置

以测试加法为例,测试1+1 expect 2是简单的,但如果要测试多组数据,提前配置好参数可能是一个更好的方法

@RunWith(Parameterized.class)
public class ParameterTest {
    int expected, input1, input2;
    @Parameters
    public static Collection<Object[]> t() {
        return Arrays.asList(new Object[][]{
            {3, 1, 2},
            {4, 2, 2}
        });
    }
    public ParameterTest(int expect, int input1, int input2) {
        this.expect = expect;
        this.input1 = input1;
        this.input2 = input2;
    }
    @Test
    public void testAdd() {
        assertEquals(expected, new Calculate().add(input1, input2));
    }
}

googletest单元测试

Assert断言

googletest中,是通过断言来判断代码实现的功能是否符合预期,断言的结果分为成功success,非致命错误non-fatal failure和致命错误fatal failure

  • 成功:断言成功,程序的行为符合预期,程序允许继续向下运行,可以在代码中调用SUCCEED()来表示这个结果
  • 非致命错误:断言失败,但程序没有直接中止,而是继续向下运行,可以在代码中调用FAIL()来表示这个结果
  • 致命错误:中止当前函数或者程序崩溃,可以在代码中调用ADD_FAILURE()来表示这个结果

这些断言都是宏,行为表现得像函数调用,当断言失败时googletest会打印断言的源文件和行号位置以及失败消息,还可以提供自定义失败消息

EXPECT

EXPECT_*在失败时会产生非致命错误

ASSERT

ASSERT_*在失败时会产生致命错误

TEST

TEST是一个没有返回值的宏函数

我们可以在该函数中使用断言来检测代码是否有效,测试的结果由断言决定

TEST(TestSuiteName, TestName) {
    ... test body ...
}