TDD中单元测试测试覆盖范围问题

TDD中单元测试测试覆盖范围问题

1、问题

​ TDD要求测试反馈速度非常快,如果不快就没有办法支持小步快走的的三个标准步骤。如果进行重量级单元测试启动本地环境连接内存数据库或者文件IO等,无法达到秒级反馈。

所以只能采用测试替身(mocks或者stub)屏蔽掉被测对象的细节,那么每个单测覆盖的边界在哪里呢?

2、二分法

是做极端重视单元的隔离性的Mock主义者,还是做小型集成测试SUT(System Under Test)主义者?
1)Mock主义者写出的单测:测试范围小;测试准确性依赖于约定;测试支持由外向内的方法;设计风格进化是Mock主义者关键动力。
2)小型集成测试SUT主义者写出的单测:测试范围较大;使用真实对象或者替身作为模拟;将功能点作为测试目标,单测覆盖多个class;运行了第一个测试,对模拟的期望就作为下一步的规范和测试的起点,逐步逐步遍历系统层次,节奏可控。

3、综合

通常对于修改遗留代码、做ATDD,采取小型集成测试比较方便,提测前精神舒爽;

对于完全新增的代码,不妨试试重视隔离的单测。

无论选哪种TDD风格,提测前都需要再运行断言到数据库的重量级单元测试。

4、小型集成测试示例

描述:针对类链式调用场景 AFacade->BDoaminService->CMapper

环境:spring、jmockit

单测:将中间层依赖BDoaminService初始化,而不是直接使用@Injectable的Mock,再通过反射注入到AFacade中,那么测试范围可以覆盖到BDoaminService中。

  @Test
    void should_get_ok( @Tested(fullyInitialized = true)  AFacadeImpl aFacade, @Tested(fullyInitialized = true)  BDoaminServiceImpl bDoaminServiceImplInitialized,@Injectable CMapper cMapper,@Injectable BDoaminServiceImpl bDoaminServiceImpl) {
        //设置期望
        ReflectionTestUtils.setField(aFacade,"bDoaminService", bDoaminServiceImplInitialized);
        new Expectations(){{
            cMapper.update();
            result = "ok";
            times=1;
        }};
        //运行和断言
        assertEquals("ok",aFacade.execute());
    }	
5、参考:

1、Martin Fowler 《Mocks Aren’t Stubs》[https://martinfowler.com/articles/mocksArentStubs.html]

2、肖鹏《Mock 七宗罪》[https://gitbook.cn/m/mazi/article/58eb77690ff0430e0255a8c4?isLogArticle=no&readArticle=yes&sut=23aab950c5ac11ebbd1ca9e03e8acc15]

上一篇:打包vue-admin-template到Django项目记录


下一篇:Django实战搭建mock系统(二)