ut-maven-plugin简介
这是一个用来生成Unit Test模板的maven插件。使用这个插件不能彻底解决单元测试的问题,她还没有这么智能,只能按照自己的理解帮助你生成一个方法的单元测试方法框架。通过这些自动生成的代码,来提高写单元测试的生产率。
《程序员修炼之道》里的提示29说:“Write Code That Writes Code”。这也是ut-maven-plugin所做的,帮助程序员生成需要重复的工作以及共性的工作。
也许,现在她还小,还不足够智能,智能到足以测试你的方法的所有业务逻辑。但是在将来,她将会越来越智能。帮你解决更多的单元测试问题,或者解决更多共性的问题。
实现原理
如何解析源码,这是首先需要解决的问题。在计算机科学中,有**抽象语法树(Abstract Syntax Tree)**这一概念,它是源代码的抽象语法结构的树状表现形式。树上的每个节点都表示源代码中的一种结构。利用抽象语法树就可以对源码进行一个全方位的解析,从而知道如何生成特定的测试代码。
Eclipse(以及其它IDE)中就提供了AST的解析功能,比如Eclipse里的outline(大纲)视图。
同时,Eclipse也提供的有抽象语法树视图,即ASTView。
本插件选用JavaParser来分析源码,提取并生成测试代码。
如何使用这个工具?
这个插件一个被我放到了Maven Central上,因此,你可以直接在pom.xml里添加上这个插件就可以了。同时建议你使用最新的版本。
比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <plugin> <groupId>cn.shenyanchao.ut</groupId> <artifactId>ut-maven-plugin</artifactId> <version>0.2.9</version> <executions> <execution> <id>source2test</id> <phase>process-test-sources</phase> <goals> <goal>source2test</goal> </goals> </execution> </executions> </plugin>
|
解决了什么问题?
以spring-petclinic中的代码为例。
下面的Service代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package org.springframework.samples.petclinic.service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.samples.petclinic.model.Pet; import org.springframework.samples.petclinic.model.PetType; import org.springframework.samples.petclinic.repository.PetRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
@Service public class ClinicServiceImpl implements ClinicService {
@Autowired private PetRepository petRepository; ......
@Override @Transactional(readOnly = true) public Pet findPetById(int id) throws DataAccessException { return petRepository.findById(id); } ......
}
|
那么,我们自己手工写的单元测试代码有可能是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package org.springframework.samples.petclinic.service.test;
import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.samples.petclinic.model.Pet; import org.springframework.samples.petclinic.repository.PetRepository; import org.springframework.samples.petclinic.service.ClinicServiceImpl;
import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.when;
public class ClinicServiceImplTest {
@InjectMocks private ClinicServiceImpl clinicService = new ClinicServiceImpl();
@Mock private PetRepository petRepository;
@Before public void initMocks() { MockitoAnnotations.initMocks(this); }
@Test public void findPetByIdTest() { when(petRepository.findById(anyInt())).thenReturn(new Pet()); Pet pet = clinicService.findPetById(1); Assert.assertNotNull(pet); }
|
如果,有很多个类需要写单元测试,那么我们会发现有很多代码是具有共性的,或者是有一定规律的。但从这个类来说,我们认为大部分代码都是可以通过对源代码进行分析得到的,除了以下的业务逻辑部分:
1 2
| when(petRepository.findById(anyInt())).thenReturn(new Pet()); Pet pet = clinicService.findPetById(1);
|
因此余下的代码都可以由插件来完成,使得程序员直接关注于业务逻辑部分的编写。大大的提高了程序员单元测试的编写效率,甚至使程序员们爱上单测。
当然,这里只是一个例子,如果能抽象出更多的共性,本插件就可以进行不断的扩展。简单的来说,有共性有规律就可以自动生成出来。随着不断的扩展,ut-maven-plugin将越来越智能化。