一个适用于 android/jvm 的冒烟单测生成器 randunit
資深大佬 : williamfzc 4
背景
在持续交付越来越流行的今天,单测作为保障 CI 质量的重要一环也开始在国内被重视起来。
不过在单测上大家的态度还是比较矛盾的,担心的事情主要有两个:
- 从 0 到 1 的第一步不知道从何下手
- 万一花大力气做了之后发现没什么用怎么办
但是缺少这一环,在整个 devops 流程中很多编译时严重问题会被延缓到运行时暴露,这对于项目效率阻碍也不小。。
于是就有了灵感来源:
- 自动生成一系列冒烟级别单测用例,并能发现严重问题
- 接入成本低,能无痛与现有流程结合
- 能对 android 生效(我司重移动端
做了什么
RandUnit 取义自 Random UnitTest,他会:
- 根据提供的包名或入口类,搜索所有相关的待测试类与方法
- 根据搜索结果,为每个方法生成一系列 statements 用于测试
- 像常规单测流程一般,在 junit 上运行这些 statements,得到测试结果
而这一切只需要一次简单的复制粘贴:
import com.williamfzc.randunit.env.NormalTestEnv import com.williamfzc.randunit.models.StatementModel import com.williamfzc.randunit.scanner.ScannerConfig import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @RunWith(Parameterized::class) class MinExampleTest(private val statementModel: StatementModel) { companion object { private val testEnv = NormalTestEnv() private const val packageName = "com.your.package" private val cases by lazy { val scannerConfig = ScannerConfig() scannerConfig.includeFilter.add(packageName) RandUnit.collectStatementsWithPackage(packageName, scannerConfig) } @JvmStatic @Parameterized.Parameters(name = "{0}") fun data(): Collection<StatementModel> { return cases } } @Test fun runStatements() { testEnv.runStatementInSandbox(statementModel) } }
由于它是合法的 junit 用例,所以你可以在 ide 里直接运行它。直接 run with coverage 的话:

可以看到,它帮你生成了 500+条用例并执行了。
解决了啥
再回头看看是不是解决了上面的三个问题:
- 自动生成:目前的策略是在每次编译后自动搜索生成一系列 junit 用例并执行,有代码变更也无需改用例
- 接入成本低:一次粘贴即可接入。除此之外,因为他是合法 junit 用例,那自然也可以像正常使用 junit 用例一样用它,例如在 CI 环境里
- 对 android 生效:得益于 robolectric 的支持, randunit 能够很好地被应用到 android 项目中。不过上面的代码需要有微调,感兴趣可以看看项目主页
像这种问题:
override fun getCastOptions(context: Context?): CastOptions? { // oh, you import a non-existed class here! // it should cause a ClassNotFoundException Class.forName("import unknown class here!") ... }
就不会被遗漏到集成之后啦:
WARNING: error happened inside sandbox: java.lang.reflect.InvocationTargetException java.lang.ClassNotFoundException: import unknown class here! at org.robolectric.internal.bytecode.SandboxClassLoader.getByteCode(SandboxClassLoader.java:158)
链接
- 具体介绍与项目主页: https://github.com/williamfzc/randunit
- 接入看这: https://github.com/williamfzc/randunit#installation
大佬有話說 (1)