自动化工具 单元测试自动生成工具 evosuite 尝鲜

陈恒捷 for PPmoney · 2018年12月04日 · 最后由 不过是雨天 回复于 2018年12月06日 · 1549 次阅读

偶尔在群里看到卡斯提到 evosuite 这个工具,随手查了下,竟然可以自动生成单元测试,而且看官方视频还不是太复杂,赶紧尝鲜一下。

介绍

直接摘抄网上的:

EvoSuite是由Sheffield等大学联合开发的一种开源工具,用于自动生成测试用例集,生成的测试用例均符合Junit的标准,可直接在Junit中运行。

通过使用此自动测试工具能够在保证代码覆盖率的前提下极大地提高测试人员的开发效率。但是只能辅助测试,并不能完全取代人工,测试用例的正确与否还需人工判断。

核心功能

  • Generation of JUnit 4 tests for the selected classes
    生成指定类的 Junit 4 测试用例

  • Optimization of different coverage criteria, like lines, branches, outputs and mutation testing
    通过不同的覆盖指标调整生成的用例,如行覆盖率、分支覆盖率、输出及变异测试(mutation testing)

  • Tests are minimized: only the ones contributing to achieve coverage are retained
    测试最小化,只有能贡献覆盖指标的用例才会被保留下来

  • Generation of JUnit asserts to capture the current behavior of the tested classes
    生成 Junit 断言来检验被测试的类的行为

  • Tests run in a sandbox to prevent potentially dangerous operations
    测试被运行在一个沙盒中,避免潜在的危险行为

  • Virtual file system
    虚拟文件系统

  • Virtual network
    虚拟网络

使用

官方提供了包括命令行工具eclipse 插件idea 插件maven 插件 在内的数种运行方式。

其中 eclipse 插件的可以参照 自动化单元测试工具 EvoSuite 的简单使用

四种都大致看了下,其中 maven 插件的方式最为简单,所以选取它来尝鲜。

接下来的流程主要参考官方的 http://www.evosuite.org/documentation/tutorial-part-2/ ,时间关系简略了一些解释说明,有兴趣的同学欢迎阅读官方原文了解。

准备工作

既然是尝鲜,当然不能直接用官方的项目啦,找了个自己以前找到的开源 java 项目:https://github.com/chenhengjie123/JavaSpringMvcBlog

下一步,按照官方指示,调整下 junit 版本

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

生成测试用例

添加 evosuite 插件

<plugins>
<plugin>
<groupId>org.evosuite.plugins</groupId>
<artifactId>evosuite-maven-plugin</artifactId>
<version>1.0.6</version>
</plugin>
...

(可选)官方提到,因为maven中央仓库没有收录这个插件,所以要加上 evosuite 自己的仓库地址。不过经过搜索,中央仓库现在已经有了,所以这步应该可以忽略。如果大家下载不了,可以把下面的配置也加到 pom 里面添加 evosuite 的仓库

<pluginRepositories>
<pluginRepository>
<id>EvoSuite</id>
<name>EvoSuite Repository</name>
<url>http://www.evosuite.org/m2</url>
</pluginRepository>
</pluginRepositories>

为了执行用例,需要加入 evosuite 的运行依赖:

<dependency>
<groupId>org.evosuite</groupId>
<artifactId>evosuite-standalone-runtime</artifactId>
<version>1.0.6</version>
<scope>test</scope>
</dependency>

开始生成,只需要执行这个命令

mvn  evosuite:generate

为了加快速度一步到位,我加了不少参数:

mvn compile -DmemoryInMB=2000 -Dcores=2 -Dcuts=alexp.blog.service.PostServiceImpl -DtargetFolder=src/test/java/evosuite evosuite:generate evosuite:export

简单说明下:

  • compile 表示编译。evosuite 是基于编译后的 .class 文件生成用例的,所以需要先编译。
  • -DmemoryInMB=2000 表示使用 2000MB 的内存
  • -Dcores=2 表示用2个 cpu 来并行加快生成速度
  • -Dcuts=alexp.blog.service.PostServiceImpl 表示只针对 alexp.blog.service.PostServiceImpl 这个类生成用例。多个用例可以用英文逗号分隔
  • -DtargetFolder=src/test/java/evosuite 表示生成的用例放到 src/test/java/evosuite
  • evosuite:generate 表示执行生成用例
  • evosuite:export 表示导出用例到 targetFolder 的值所在的目录中

执行完毕后,在 src/test/evosuite 下会增加一个 alexp/blog/service 文件夹,里面存放生成的测试文件:

src/test/java/evosuite
└── alexp
└── blog
└── service
├── PostServiceImpl_ESTest.java
└── PostServiceImpl_ESTest_scaffolding.java

3 directories, 2 files

PostServiceImpl_ESTest.java:测试用例文件
PostServiceImpl_ESTest_scaffolding.java:用例基类,用于在开始测试前初始化 evosuite 的沙盒机制

实际生成的部分代码会有编译错误(mock 的类型和 model 对不上),先通过注释跳过会编译出错的行,然后直接在 idea 执行 PostServiceImpl_ESTest.java ,并统计覆盖率:

看起来覆盖率还挺高。当然,覆盖率并不代表全部,更重要的是测的内容。

摘抄一条生成的单测用例:

对应的被测函数:

可以看到

  • 大量采用了 mockito 来 mock 掉外部对象。
  • 通过 mock 掉 findByHiddenIs 方法固定返回 null ,进而测试 getPostsList 是否也返回 null ,逻辑上没错,结果可以做到很稳定。

但可惜:

  • 没有校验正常逻辑(看了下整个类,2个用例校验 null ,一个校验非法参数,唯独缺少正常场景)

不过总的来说,作为异常场景的补充,确实能省很多力。

完整测试代码和被测代码,可以查看:

被测代码:
https://github.com/chenhengjie123/JavaSpringMvcBlog/blob/master/src/main/java/alexp/blog/service/PostServiceImpl.java
生成的测试代码:
https://github.com/chenhengjie123/JavaSpringMvcBlog/blob/master/src/test/java/evosuite/alexp/blog/service/PostServiceImpl_ESTest.java
作者自己写的测试代码(场景不全,但覆盖了正常场景):
https://github.com/chenhengjie123/JavaSpringMvcBlog/blob/master/src/test/java/alexp/blog/service/PostServiceTest.java

结论

工具使用简单,生成的用例确实有效,推荐试用。

但比较适合用于生成一些异常场景的用例,省不少力(当然还得人工 review 下)。正常场景还是得靠人。

时间有限,体验不是十分深入,不排除是使用姿势不正确导致上述效果。大家如果有建议或者不认可的地方,欢迎提出,一起交流~

参考文档

官方网站:http://www.evosuite.org
csdn 上 《自动化单元测试工具 EvoSuite 的简单使用》:https://www.cnblogs.com/fang888/p/9008280.html

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

不错不错,找时间玩一下,今天刚好还在看邱化峰大佬在某个峰会的分享说了这个Java自动生成单测的topic

不知道生成的 @ TestCase 可用率怎么样?有效性如何?生成后需要人干预的程度高吗?

哎哟,不错哦~刚试了下,挺好玩

大家都说 TDD 好,但执行都不够好,主要原因应该是懒吗?😂 ,也许只有自动化工具能帮 TDD 落地普及。

感谢大佬分享。准备尝鲜下

好像private方法不能生成,是这样的么?,还是操作姿势不对?😄

testly 回复

可用率还可以,80%左右吧。有效性个人感觉还不错,确实是要覆盖的场景
人工干预还是要的,用例还是要 review 下和人工补充一下

Raymond 回复

主要是意识,大家体会到甩代码给测试的爽快感后就不想搞测试了

佳佳 回复

没测试过,不大清楚。不过我理解一般不会对 private 方法做单测?

陈恒捷 回复

貌似APP工程用不了

16年的时候研究过,还提过几个issue,毕竟是学术工具,实践来说,不如Jtest生成的靠谱,可惜Jtest商业版收费。

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