代码测试总结
基本概念
单元测试
一些单元测试中设计的基本概念
- Stub 指的是以可控的方式对对象方法进行模拟,使其按照预期的行为返回结果或抛出异常等的过程。
- Mock Object 整个对象都是模拟对象,所有方法在模拟之前进行调用都是空方法。
- Spy Object 对真实对象的部分方法进行模拟,除了模拟的方法外调用的都是真实的方法。
单元测试的主体对象是方法,目的是测试目标方法的执行是否符合预期的行为,包括执行路径、返回值等。实施单元测试的主要目标是应用的POJOs。测试这些对象应该通过new来进行初始化,而不是通过从容器中获取的对象。目标方法中调用的过程中会调用其他的对象方法,可能基于下面的这些原因
- 真实对象的行为是不确定的(例如,当前的时间或当前的温度);
- 真实对象很难搭建起来;
- 真实对象的行为很难触发(例如,网络错误);
- 真实对象速度很慢(例如,一个完整的数据库,在测试之前可能需要初始化);
- 真实的对象是用户界面,或包括用户界面在内;
- 真实的对象使用了回调机制;
- 真实对象可能还不存在;
- 真实对象可能包含不能用作测试(而不是为实际工作)的信息和方法。
不能够或者不应该使用真实的对象方法。使用Mock对象,可以避免其他方法执行结果对目标方法执行的干扰,同时能够更好的控制方法的执行路径。
实施单元测试的好处不仅仅在于它能保证代码的正确性,更大的好处在于它的高效,因为它是通过new初始化的,调用的对象也可以进行mock,并不依赖于难以控制的外部环境。另外的好处是可以间接地提高代码的品质要求,如果你想实施单元测试,那么你得要求你的类尽可能的是一个POJO,代码应该应有较好的分层结构以及松散的耦合,一段品质很差的代码要实施单元测试是非常苦难的。
如何进行Mock
下面是基本的mock准则
- 不要什么都mock
- 不要mock不是你的类
- 不要mock值对象
针对大多数的mock框架,使用mock对象的步骤大致是一致的
- 创建mock对象
- 录制需要mock的方法行为
- 调用mock对象
- 验证
下面是Mocktio的示例代码
|
|
集成测试
集成测试主要针对是测试多个组件组合在一起工作的情况。 例如Repository接口和Spring Data JPA集成的情况下,生成的查询接口测试;Web框架和Controller集成的情况下,请求参数的绑定、转换、验证是否正常;和消息中间件集成时,消息的收发是否正常等等。
功能测试
功能测试有时候也叫E2E测试,功能测试以系统的功能点为测试对象。以Web应用为例,功能测试的主要应该是测试页面的功能是否正常,例如测试
- 请求是否成功
- 重定向是否正确
- 用户是否成功授权
- 页面的元素是否正常显示
- 页面的表单的验证是否正确,提交后的跳转是否正确
功能测试最常用的工具Selenium。当然有些框架也提供应用内的功能测试,例如Rails的Functional Test,但是这些测试不属于E2E测试的范畴,因为他们是基于容器内的测试,而不是完全独立的端到端的测试。
测试逻辑
|
|
测试方法
Behavior-driven development(BDD)
行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。 BDD是一种开发方式,但是它和测试紧密相关。BDD用它的DSL来描述系统的功能的,测试用例则则相当于对功能描述一个实现。
Cucumber
Cucumber是一个BDD的框架,它支持各种语言的实现。
业务描述
Cucumber使用Gherkin语言来作为DSL来对业务规则进行描述,下面是一个Gherkin的文档
|
|
一个Scenario指的是一个业务规则的演示、描述。其中包括Give、And、When、Then等多个Step。
上面的文档就是非技术人员或商业参与者需要做的,使用DSL语言对系统功能进行描述。
步骤实现
开发人员则需要对上面的文档中的描述进行实现,调用实际的功能代码,以达到测试代码的目的。
例如,针对下面的Step
|
|
进行实现
|
|
实现方法是应该调用实际的业务代码,对于Given来说,应该是类似setUp
来初始化测试上下文环境的。
测试框架
下面主要介绍下各个平台中较为广泛的使用的测试框架
Test Runner
Test Runner是用来启动测试,调用测试代码,反馈测试结果的。它本身可能作为一个测试框架还包括了断言、Mock等其他额外的功能
- Karama 它作为JS的Test Runner,仅负责测试的运行。它是一个Node.js的模块,能够在本地启动浏览器执行测试用例,并将测试结果输出到本地控制台。
- Junit Java平台的测试框架,它是一个完整的测试框架,除了负责运行测试用例,它还包括测试方法定义,断言的书写等功能。
- XCTest 从Xcode5,使用XCtest作为OS X和iOS平台的完整测试框架。
BDD
即便开发团队不使用完整的BDD框架进行开发,使用BDD风格的测试用例描述方式,仍然有诸多的有点,测试用例具有良好的可读性。
下面是一些BDD测试框架,其中一部分虽然是测试框架,但也创建拥有功能描述文档的功能
- Jasmine 基于JS的完整BDD测试框架,包括断言、mock的功能。
- Spock 基于Groovy的BDD测试框架,有用自己特有的断言方式,也支持使用groovy-test的断言。
- Specta 基于Object-C和Cocoa的BDD测试框架,它不提供断言、mock的功能。
- Kiwi iOS平台的完整BDD测试框架,包括了断言、mock的功能。
Mock库
除了针对对象方法的mock库,还有一些实现了类似mock功能的库。
- [OHHTTPStubs] iOS平台的HTTP请求的Stub库。它可以Stub所有通过NSURLConnection接口进行的请求,模拟数据的返回,模拟网速慢的情况的请求等。 除了可以用于更高效的测试外,还可以用于开发阶段,API等尚未完成时的接口模拟等。
断言&匹配库
匹配库本身并不是测试必要的一部分,但是有了匹配库可以让断言的书写更为简洁和高效