文章系列
[质量提升之道]-Code Review
上一篇介绍了 Code Review,本篇将介绍 UT&Coverage,两者都是代码入库前做的质量工作,从流程上细分,UT&Coverage 在 Code Review 之前。从 Coding 开始,Bug 就开始蠢蠢欲动了,UT&Coverage 的最大价值,就是把缺陷扼杀在摇篮之中,此时的修复成本是最低的,修复风险也是最小的,做的好能很大程度的提高版本质量。
什么是 UT?
单元测试是最小颗粒度的测试,测试对象往往是某个方法、SQL,相对于静态分析,它是种基于白盒的动态测试。
为什么要 UT&Coverage?
单元测试要和代码覆盖率配合使用,UT 的目的就是要测试代码覆盖到业务代码中的方法、方法内的分支路径,执行者需要知道 UT 的执行情况,比如覆盖率是多少,是否达到预期。
每种语言都有各自的工具,如果用 Java,常见的组合是 Junit/JaCoCo。
工具的安装不是本文重点,想了解的自行谷歌度娘。
单元测试不是无的放矢,应该是有目标、有策略的进行:
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 {
}
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 属于白盒测试的范畴,需要人工介入,是整个团队打赢质量攻坚战最重要的战役,研发和测试都要高度重视。以本人多年的工作经验,如果该环节不做或做的不好就进行提测,对黑盒测试的测试人员,肯定是个灾难,靠时间和人力去堆砌,也不见得有好的结果。