企业做网站的合同,wordpress 恢复备份,织梦网站如何做优化,人们常说的蓝领是从事什么工作的阅读本文之前#xff0c;请投票支持这款 全新设计的脚手架 #xff0c;让 Java 再次伟大#xff01;
单元测试的质量意义
合理编写单元测试#xff0c;可使团队工程师告别牛仔式编程#xff0c;产出易维护的高质量代码。随着单元测试覆盖率的上升#xff0c;项目会更加…阅读本文之前请投票支持这款 全新设计的脚手架 让 Java 再次伟大
单元测试的质量意义
合理编写单元测试可使团队工程师告别牛仔式编程产出易维护的高质量代码。随着单元测试覆盖率的上升项目会更加的健壮团队的信心满满充满斗志。
无论是瀑布团队还是敏捷团队单元测试及自动化单元测试作为重要的质量保证手段的价值已经被大家接纳与认可。
但是对于大多数团队来讲当测试覆盖率提升一定阶段后收益会迎来瓶颈。 单元测试的设计意义
单元测试除了作为质量保证手段以外更应该作为设计手段。TDD 的核心思想之一就是使用单元测试作为设计手段使开发者在编写测试用例时以调用者的思维方式来写代码这种方式的收益会比作为保护手段更高。 利用测试驱动开发可以让你的设计更加优良、编写出可测试的代码、还能避免在不切实际的假设上过度设计系统。
优秀测试的共性
良好的测试代码具备可读性和可维护性。测试代码在项目中有结构化的组织方式。测试具备可靠性和可重复性。合理的使用测试替身。AAA(Arrange, Act Assert)——准备、执行、断言。 编写测试代码时使用被称为三A模型准备、执行、断言。
测试替身test double
为了方便的测试代码以及绕开各种环境限制应该使用替身来代替真实对象。
public class Car {// 对外封闭的引擎对象。你无法知道内在信息。private Engine engine;public Car(Engine engine) {this.engine engine;}// 需要测试的启动功能public void start() {engine.start();}// 需要测试汽车的驾驶功能public void drive(Route route) {// 根据路线状态获取提供给 car 使用的各种方向 (十分复杂的算法初始化时需要涉及 gis 算法。最终获取的对对象与当前的时间有关for (Directions directions : route.getDirections()) {directions.follow();}}}
为了验证一段代码的行为符合你的期望最好的选择是替换其周围的代码使你获得对环境的完整控制。使用了替身能让执行速度变得更快并且可以随意模拟特殊情况。 public class TestRoute extends Route {// 伪造的替身实现了快速返回路线以及返回固定路线的方法使测试具备了可靠与可重复性Overridepublic ListDirections getDirections() {System.out.println(快速的返回固定的路线);return new ArrayListDirections();}}public class TestEngine extends Engine {private boolean engineFlg false;Overridepublic void start() {engineFlg true;}Overridepublic void stop() {engineFlg false;}public boolean isEngineFlg() {return engineFlg;}public void setEngineFlg(boolean engineFlg) {this.engineFlg engineFlg;}}
使用替身替换协作者隔离被测代码意味着将需要测试的代码与其他代码隔离开来。 Testpublic void testCarStart() {TestEngine engine new TestEngine();new Car(engine).start();assertTrue(engine.isEngineFlg());}Testpublic void testCarDrive() {TestRoute testRoute new TestRoute();TestEngine engine new TestEngine();new Car(engine).drive(testRoute);}
测试替身的类型
替身拥有多种类型。不同的测试场景选择合理的测试替身是优秀测试的必要条件之一。测试替身的类型也决定了测试类的命名方法尤其特别注意。
桩stub
用最简单的可能实现来代替真实实现。桩总是短小的。最好的例子就是一个对象的所有方法都只有一行并且返回一个默认值。
public class LoggerStub implements Logger {Overridepublic void log() {// Nope}
}
伪造对象 fake
有时我们至少需要填充一些行为而有时候你需要测试替身根据收到的消息种类来表现出不同的行为。 Fake 就像是真实事物的简单版本他能够伪造真实事物的行为具备简单的业务逻辑同时没有副作用或者使用真实事物的其他后果。 public class TestRoute extends Route {// 伪造的替身实现了快速返回路线以及返回固定路线的方法使测试具备了可靠与可重复性Overridepublic ListDirections getDirections() {System.out.println(快速的返回固定的路线);return new ArrayListDirections();}}
伪造对象与测试桩十分常用你可以在测试时用它们替换掉缓慢的真实事物以及鞭长莫及的依赖。
测试间谍 (spy)
测试间谍用于记录你和某个不对你开放的对象之间的交互。当对象与协作者之间交互时无法获取协作者交互结果的情况下会使用测试间谍。
// 测试间谍public class TestEngine extends Engine {// 对外暴露信息private boolean engineFlg false;// 比真实对象的 start 方法更具有交互性的方法。Overridepublic void start() {engineFlg true;}Overridepublic void stop() {engineFlg false;}// 对外提供用于获取交互结果的接口用于断言。public boolean isEngineFlg() {return engineFlg;}public void setEngineFlg(boolean engineFlg) {this.engineFlg engineFlg;}}
模拟对象 mock
模拟对象是在一个特定情境下可配置行为的对象。模拟对象时一种更加高级与特殊的测试间谍它关注的重点是两个对象之间的交互行为。
public void mockTest(){final Internet internet context.mock(Internet.class);context.checking(new Expectations() {{one(internet).get(with(containsString(langpairen)));will(returnValue(ok))}};Translator t new Translator(internet);String translation t.translate(flower,ENGLISH);assertEquals(ok,translation)}
通过使用模拟对象的预测返回值行为我们可以更加精确的对交互行为进行验证。
如何选择合适的替身类型
如果你测试的重点是交互即两个对象之前的调用你可能需要一个模拟对象 mock。如果你决定使用 Mock 但测试代码最终看起来不像你想象的那么漂亮了则考虑使用 Spy。如果你只关心协作对象向被测对象输送的响应用 stub 解决问题。如果你运行的是一个复杂场景其中它所依赖的服务无法供测试使用但是你又需要这些服务提供的行为哪怕是一个简单的提示那就应该考虑使用 Fake。