白盒测试 [质量提升之道]-UT&Coverage

扫地僧 · 2018年03月22日 · 最后由 萝卜 回复于 2019年07月26日 · 2397 次阅读

文章系列
[质量提升之道]-Code Review

前言

上一篇介绍了 Code Review,本篇将介绍 UT&Coverage,两者都是代码入库前做的质量工作,从流程上细分,UT&Coverage 在 Code Review 之前。从 Coding 开始,Bug 就开始蠢蠢欲动了,UT&Coverage 的最大价值,就是把缺陷扼杀在摇篮之中,此时的修复成本是最低的,修复风险也是最小的,做的好能很大程度的提高版本质量。

UT&Coverage 的概念

什么是 UT?
单元测试是最小颗粒度的测试,测试对象往往是某个方法、SQL,相对于静态分析,它是种基于白盒的动态测试。

为什么要 UT&Coverage?
单元测试要和代码覆盖率配合使用,UT 的目的就是要测试代码覆盖到业务代码中的方法、方法内的分支路径,执行者需要知道 UT 的执行情况,比如覆盖率是多少,是否达到预期。

UT&Coverage 的工具组合

每种语言都有各自的工具,如果用 Java,常见的组合是 Junit/JaCoCo。
工具的安装不是本文重点,想了解的自行谷歌度娘。

UT 的策略和测试代码

单元测试不是无的放矢,应该是有目标、有策略的进行:
1.制定目标:class 覆盖率达到多少、method 覆盖率达到多少、line 覆盖率达到多少;
2.制定策略:如果开发进度紧迫,可以优先保证重要的、核心的部分被覆盖到,例如:Controller、Service 的代码、底层公共方法等;
3.测试代码的设计,要尽量覆盖方法内的各条分支路径。

spring boot 的示例

/**
 * Controller业务代码
 */
@RestController
@RequestMapping("/gretting")
@Api("swagger生成的gretting api文档")
@Slf4j
public class Controller {
    @ApiOperation(value = "索引", notes = "index目录")
    @GetMapping(value = "/index")
    public ResponseEntity<?> index() {
        log.info("GreetingController.index.in.");
        log.error("kidding");
        Map<String, Object> map = new HashMap<>();
        map.put("msg", "Hello, SpringBoot");
        return ResponseEntity.ok(map);
    }
}

/**
 * Controller测试代码
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class TestController {
    @Autowired
    MockMvc mvc;

    @Before
    public void setUp() {
    }

    @Test
    public void index() throws Exception {
        mvc.perform(MockMvcRequestBuilders
                .get("/gretting/index"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.content().string("{\"msg\":\"Hello, SpringBoot\"}"));
    }

    @After
    public void tearDown() {
    }
}
/**
 * Service业务代码
 */
@Service
public class ServiceImpl implements Service {

    @Override
    public String getStr(Object obj) {
        return null == obj ? "false" : "true";
    }
}

/**
 * Service测试代码 - 未覆盖分支路径.
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestService {
    private String expect;

    @Autowired
    private ServiceImpl service;

    @Before
    public void setUp() {
        expect = "success";
    }

    @Test
    public void getStr() throws Exception {
        String str = service.getStr("test");
        Assert.assertEquals(expect, str);
    }

    @After
    public void tearDown() {

    }
}
/**
 * Service测试代码 - 覆盖分支路径.
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestService {
    private String expect;

    @Autowired
    private ServiceImpl service;

    @Before
    public void setUp() {
        expect = "success";
    }

    @Test
    public void getStr() throws Exception {
        String str = service.getStr("test");
        Assert.assertEquals(expect, str);
        //  测试覆盖分支路径
        str = service.getStr(null);
        Assert.assertNull(str);
    }

    @After
    public void tearDown() {

    }
}
/**
 * UT入口
 */
@Suite.SuiteClasses({TestService.class, TestController.class})
@RunWith(Suite.class)
public class TestMain {
}

JaCoCo 的 Coverage

1.代码覆盖率可以作为版本提测的硬性指标,例如:method 覆盖率 100%,line 覆盖率不低于 80%;
2.JaCoCo 可以设置统计样本的目标范围,可以是包(com.demo.controller.、com.paic.demo.service.),也可以是某个类(com.paic.demo.service.ClassDemo);
3.UT&Coverage 作为版本的提测指标,在持续集成中执行,建议在本地 IDE 先跑一遍,提高版本提测的通过率。

覆盖率报告

绿色的代表已覆盖到的代码,红色代表未覆盖到的代码

后话

UT&Coverage、Code Review 属于白盒测试的范畴,需要人工介入,是整个团队打赢质量攻坚战最重要的战役,研发和测试都要高度重视。以本人多年的工作经验,如果该环节不做或做的不好就进行提测,对黑盒测试的测试人员,肯定是个灾难,靠时间和人力去堆砌,也不见得有好的结果。

下一次,会介绍测试左移和提测标准。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 6 条回复 时间 点赞

点赞 好评

赞,小小补充一下,BE 的 UT 在于验证逻辑正确性,FE 的 UT 在于验证数据渲染的正确性。

andward_xu 回复

BE 和 FE 是啥?

FelixKang 回复

frontend&backend

andward_xu 回复

感谢回复

扫地僧 [质量提升之道]-Phabricator 的安装 中提及了此贴 04月09日 15:14
扫地僧 [质量提升之道]-接口测试 中提及了此贴 12月06日 00:30

关键是连人力和时间都不给你,甚至连排期计划都没测试时间。这就是所谓的小型瀑布快速发布部署迭代模式(俗称冥捷开发)的终极形态。哈哈哈哈哈哈

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册