美文网首页软件测试TesterHome测试之家
适用于 android/jvm 的单测生成器 randunit

适用于 android/jvm 的单测生成器 randunit

作者: TesterHome | 来源:发表于2022-01-20 10:40 被阅读0次

    背景


    在持续交付越来越流行的今天,单测作为保障 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

            @user3ters(name = "{0}")

            fun data(): Collection {

                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)


    什么时候推荐使用 randunit


    在之前很长一段时间的观察里,无论项目大小,依旧有大量开发中的项目处在没有任何单元测试的状态中。随着 devops 的流行,持续化的自动化测试几乎已经成为整个敏捷流程中最为关键的一环。

    而在这种情况下其实很多业务认知到了这一阶段的重要性,但不知道从何下手

    这个项目的出发点就是,用尽可能少的成本将单元测试跑起来,至少将这里的空缺填补起来

    推荐使用的情况

    你的项目目前还处于裸奔的状态,或单元测试做得不好的状态

    不推荐使用的情况

    你想要一个彻底发现问题并能完整覆盖整个项目的工具


    原型与演进方向


    有一些朋友肯定会拿 evosuite 跟 randoop 出来杠我,而事实上这个工程的灵感就源自他们。感兴趣可以看:原型与演进方向


    链接


    具体介绍与项目主页: https://github.com/williamfzc/randunit

    接入看这: https://github.com/williamfzc/randunit#installation

    相关文章

      网友评论

        本文标题:适用于 android/jvm 的单测生成器 randunit

        本文链接:https://www.haomeiwen.com/subject/lykjhrtx.html