执行测试_单元测试
在执行测试为主线,中间穿插质量特性,学会自动化工具的使用。
软件测试的过程
- 测试范围:逐渐增大:先使用白盒测试,然后黑盒测试的比例逐步增加。
- 测试视角:从代码到使用
具体来说就是:
- 单元测试—模块/白盒技术
可以并行进行
- 集成测试—模块接口/黑盒+白盒技术
- 系统测试—满足需求/黑盒
兼容性问题等等
- 验收测试—突出客户作用/黑盒
单元测试
定义
单元测试是对软件最小可测试元素进行正确性检验的测试工作
-
单元选择依据:功能独立、可测、可观测、有明确的可定义的边界或接口
因此单元的备选有:类/方法/idea的model -
验证模块中是否存在差错,是否能正确实现功能,满足性能、接口要求
-
“单元”是软件中最小的、可以单独执行编码的单位
-
确定单元的最基本原则:高内聚、低耦合
-
测试对象:重要模块的重要控制路径
-
每个程序模块可并行的、独立的进行测试工作
注意:一个模块的编写完成,就要进行测试。而不是集成前集中进行
单元测试的重要性
- 时间方面
- 测试效果方面( ①测试基础 ②深层次问题 ③关注代码控制流程 )
- 测试成本方面
- 产品质量方面
单元测试原则
- 单元测试越早进行越好
- 单元测试应该依据《软件详细设计规格说明》进行
- 对于修改过的代码应该重做单元测试
- 测试人员应如实记录实际的测试结果
- 应注意选择好被测软件单元的大小
- 应该包含正面测试和负面测试
- 注意使用单元测试工具
单元测试的目标和任务
目标: 单元模块被正确编码
具体有以下几个方面:
- 数据或信息能否正确的流入和流出单元
- 在单元工作过程中,其内部数据能否保持其完整性,包括内部数据的形式、内容及相互关系不发生错误,也包括全局变量在单元中的处理和影响
- 在数据处理的边界处能否正确工作
- 单元的运行能否做到满足特定的逻辑覆盖
- 单元中发生错误,其中的出错处理措施是否有效
- 指针是否被错误引用、内存是否及时释放
性能
- 有没有安全隐患
安全
主要任务
单元测试的主要任务是测试功能方面的问题,主要有以下五个方面:
模块接口
检查模块接口是否正确,checklist:
模块接收输入的实际参数与形式参数的个数、类型、单位是否一致
调用其他模块的实际参数与被调模块的形参是否一致
全程变量的定义在各模块是否一致
外部输入、输出
文件、缓冲区、错误处理
只能使用静态测试,无法使用动态测试
局部数据结构
检查局部数据结构完整性,Checklist:
不正确或不一致的类型说明
变量初始化或默认值有错
不正确的变量名或从来未被使用过
不相容的数据类型
出现上溢或下溢和地址异常
全局数据结构对模块的影响
建议使用静态测试,动态测试效果不好
独立执行路径
检查每一条独立执行路径的测试。保证每条语句被至少执行一次。
Checklist:
- 误解或不正确使用算术优先级
- 混合类型运算
- 变量初值错
- 运算精度不够
- 算法错误
- 表达式符号错
针对判定和条件覆盖。Checklist:
- 不同数据类型对象之间进行比较
- 错误的使用逻辑操作和优先级
- 由于计算机表示的局限性,期望理论上相等而实际上不相等
- 不正确的判定或不正确的变量
- 不正常或不存在的循环终止
- 错误的修改了循环控制变量
使用以基本路径测试为基础的动态白盒测试
错误处理
预见、预设的各种出错处理是否正确有效。
Checklist:
- 输出的出错信息难以理解
- 报告的错误与实际不相符
- 程序定义的出错处理前系统已介入
- 异常处理不当
- 未提供足够的定位出错的信息
也就是能够用自然语言 清楚的告诉用户错在哪,怎么改。
动态黑盒测试
边界条件
检查临界数据处理的正确性。Checklist:
普通合法数据的处理。
普通非法数据的处理。
边界值内合法边界数据的处理。
边界值外非法边界数据的处理
动态黑盒测试
单元测试环境的建立
单元测试环境=被测模块 + 驱动模块 + 桩模块
-
驱动模块(drive): 对底层或子层模块进行测试所编写的调用这些模块的程序
接收测试数据,把相关的数据传送给被测模块,启动被测模块,并打印出相应的结果 -
桩模块(stub): 对顶层或上层模块进行测试时所编写的替代下层模块的程序
进行很少的数据处理,如打印入口和返回
注:
-
自动和手工测试都要搭建驱动模块 + 桩模块
-
驱动模块 + 桩模块 的设计越简单越好,消耗的资源越少越好
-
驱动模块好写,桩模块难写
单元测试主要技术
主要采用白盒测试技术,辅之以黑盒测试技术
单元测试主要技术:
- 人工静态测试
- 动态执行测试(白盒+黑盒)
- 状态转换测试
1. 静态测试
不运行程序,单独检查单元代码并进行代码的评审和检查
外部接口和程序代码的关键部分要进行桌面检查和代码审查
目的:保证代码算法的逻辑正确性、清晰性、规范性、一致性、算法高效性
- 静态测试
适用于新开发和重用的代码
通常在代码完成并无错误的通过编译或汇编后,采用自动化工具扫描分析、代码评审等方法
由软件开发人员及开发小组成员共同完成
常用方法:
桌面检查(Desk Checking)
代码走查(Walk Through)
代码审查(Program Inspection)
2. 动态执行测试
动态白盒测试:逻辑覆盖和基本路径测试
测试基本原则:
保证单元中每一个独立路径至少执行一次
保证所有判断的每一分支至少执行一次
保证每一循环在边界条件和一般条件下至少执行一次
验证所有单元内部数据结构的有效性
2. 动态执行测试
动态白盒测试:逻辑覆盖和基本路径测试
测试基本原则:
保证单元中每一个独立路径至少执行一次
保证所有判断的每一分支至少执行一次
保证每一循环在边界条件和一般条件下至少执行一次
验证所有单元内部数据结构的有效性
3. 状态转换测试
当单元可能处于不同状态转换时,应根据单元可能进入的状态、这些状态之间的转换、引起转换可能导致的状态等进行测试
单元测试的评估
通过单元测试的一般准则:
- 软件单元功能与设计需求一致
- 软件单元接口与设计需求一致
- 能够正确处理输入和运行中的错误
- 在单元测试中发现的错误已经得到修改并且通过了测试
- 达到了相关的覆盖率的要求
- 完成软件单元测试报告
4.7 单元测试的管理
- 单元测试过程
在详细设计阶段完成单元测试计划。
建立单元测试环境,完成测试设计和开发。
执行单元测试用例,并且详细记录测试结果。
评估测试用例是否通过。
提交《单元测试报告》。
- 单元测试文档
《软件需求规格说明书》、《软件详细设计说明书》 《单元测试计划》
《单元测试计划》、《软件详细设计说明书》 《单元测试用例》
《单元测试用例》文档及《软件需求规格说明书》、《软件详细设计说明书》 《缺陷跟踪报告》/《缺陷检查表》
《单元测试用例》、《缺陷跟踪报告》/《缺陷检查表》 《单元测试检查表》
评估 《单元测试报告》
单元测试工具
单元测试工具简介
自动化单元测试工具的工作原理是借助于驱动模块与桩模块工作的,运行被测软件单元以检查输入的测试用例是否按软件详细设计规格说明的规定执行相关操作。
常见分类:静态分析工具;代码规范审核工具;内存和资源检查工具;测试数据生成工具;测试框架工具;测试结果比较工具;测试度量工具;测试文档生成和管理工具
JUnit⭐
JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试。
- 它是单元测试框架体系xUnit的一个实例
(xUnit系列框架,常用的根据语言不同分为JUnit(java),CppUnit(C++),DUnit (Delphi),NUnit(.net),PhpUnit(Php)等)
⭐JUnit特性
- 可以使测试代码与产品代码分开
- 针对某一个类的测试代码通过较少的改动便可以应用于另一个类的测试
- 易于集成到测试人员的构建过程中,JUnit和Ant的结合可以实施增量开发
- JUnit是公开源代码的,可以进行二次开发
- 可以方便地对JUnit进行扩展
JUnit框架组成
-
对测试目标进行测试的方法与过程集合,可称为测试用例(TestCase)。
-
测试用例的集合,可容纳多个测试用例(TestCase),将其称作测试包(TestSuite)。
-
测试结果的描述与记录(TestResult) 。
-
测试过程中的事件监听者(TestListener)。
-
每一个测试方法所发生的与预期不一致状况的描述,称其测试失败元素(TestFailure)
-
JUnit Framework中的出错异常(AssertionFailedError)
JUnit注解(Annotation)
- @Test:测试方法,表明这是一个测试方法。在Junit中将会自动被执行
- @Before:初始化方法,在任何一个测试执行之前必须执行的代码
- @After:释放资源,在任何测试执行之后需要进行的收尾工作
- @Ignore:忽略的测试方法,该方法尚未完成,暂不参与此次测试
- @BeforeClass:针对所有测试,只执行一次
- @AfterClass:针对所有测试,将会在所有测试方法执行结束后执行一次
@BeforeClass –> @Before –> @Test –> @After –> @AfterClass
JUnit断言
-
assertTrue|False(boolean condition)
:判定结果是否为真|假
如果断言成立,继续运行后续测试;
如果不成立,抛出AssertionFailedError异常 -
assertEquals([String message, ] expected,actual[,tolerance])
:判定表达式是否相等
public void assertTrue(boolean condition){
if(!conditon) abort();
}
assertEquals(“两数不等”,3.33,10.0/3.0,0.01)
assertSame([String message, ] expected,actual)
:判定引用是否指向同一对象assertNull|NotNull([String message], java.lang.object object)
:判定一个对象是否为空|非空fail([String message])
:立即终止测试代码的执行assertEquals([String message,] Object[] expected, Object[] actual)
判定数组长度及每个对应的元素是否相等
注意:遇到第一个断言失败的情况,该测试方法立即结束执行
总结
目标:确保模块被正确的编码
依据:详细设计说明书
过程:设计、脚本开发、执行、调试和分析结果
测试方法:白盒+黑盒
评估方法:通过所有测试用例,代码无严重缺陷
执行者:程序开发人员+测试人员