- 给测试同学-关于语言补习
Kotlin
*建议Java全熟之后再看,同时看有可能会记错用法;
*语法比较多,需要慢慢消化;
*优先看下官网的Higher-Order Functions and Lambdas还有inline functions有助于尽快看懂开发代码。
Java
*泛型需要优先看下,其它结合开发代码学习。
以上两种,先看Java再跟进Kotlin的话,体感大概一~二周差不多可以读懂开发代码 写一些单测用例。有相关经验会更快一些。
- 给测试同学-Gradle
实际开始投入单测之后发现有不少坑都在Gradle里面,所以需要大致了解Gradle,磨好刀再砍柴。基础资料搜索一下网络还是比较全的。
下面是两个刚开始接触时遇到的问题:
A.默认的项目test文件里面用的都是Android.support.test.....,因为建议用Androidx代替所以用例文件引用的都是Androidx,结果运行用例的时候会这样报错:
这里需要把Gradle里面的testInstrumentationRunner也替换到androidx.test.runner.AndroidJUnitRunner。
B.dependencies结构:
依赖的一些外部的包在这里配置,其中testimplementation和Androidtestimplementation分别作用于工程路径src/test和src/androidTest
如果没用implementation而是compileOnly则表示只编译,不打包。整体编译情况下这么操作是ok的,但是单测场景下测试单个模块时就可能导致找不到实现。为了不影响最后出包,可以添加对应模块的testimplementation和Androidtestimplementation代替。
- 单测中获取context
Instrument test里面经常要获取context,对于单测来说可以直接使用InstrumentationRegistry.getInstrumentation.context获取,需要注意对应的metadata/versioncode等等数据全部与当前模块路径下的Androidtest/test文件夹内的对应文件挂钩,而不是和工程的APP文件夹挂钩,其中:
InstrumentationRegistry.getInstrumentation()
返回当前正在运行的Instrumentation;
InstrumentationRegistry.getContext()
返回此Instrumentation软件包的上下文;
InstrumentationRegistry.getTargetContext()
返回目标应用的应用上下文;
InstrumentationRegistry.getArguments()
返回传递给此Instrumentation的参数Bundle。
- Manifest—runtime permission—rule—@get—api23
API23(Android6.0)之后,申请权限变成了在运行时获取(用户点了某个功能之后APP弹框提示用户是否授权etc),单测时则需要用androidx.test.rule.GrantPermissionRule.grant(Manifest.permission.STRING)获取对应的权限(android.support.test参考开头)。或者先弄出一个Activity然后动态申请权限(情况比较少,而且很麻烦)。
其中,java可以用
@Rule
public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)实现一次性申请权限;但是如果直接写到kotlin里面会报错:
java.lang.Exception: Delegate runner 'androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner' for AndroidJUnit4 could not be loaded. Check your build configuration。所以在kotlin里面需要改写成:@get:Rule val mRuntimePermissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)
- AndroidX、Android.support有什么区别?
在上一节引用GrantPermissionRule时发现Developer上给了两个不同包下的同名东东:
而本地看到的工程里面大多数引用的是Androidx.test,为防止重复引入导致踩坑,查了一下,大概解释如下:
也就是说androidx是android.support的强化升级版。后面一般有要引入的包,优先在androidx里面查找就好。
P.S.:如果遇到兼容旧版本使用了Android.support的程序,可能还是要配合用回android.support。
- Mockk—static method—AndroidP
mockK声称支持静态方法的mock,然后试验了一下在荣耀V9的表现:
所以想mock静态方法的,找找AndroidP的手机吧。
另外mock静态方法的代码(kotlin):
后面的every语句直接用class.method填写即可。
- Mock private method
Mock一个私有方法时,使用以下语句:
Mock[“methodname”]()
而如果想要把私有方法加到verify跟踪内,在mock的时候要加上(recordPrivateCalls=true):
class Car {
fun drive() = accelerate()
private fun accelerate() = "going faster"
}
val mock = spyk<Car>( recordPrivateCalls = true)
every { mock["accelerate"]() } returns "going not so fast"
此外如果想Mock私有属性,建议采用反射替代mock。
- No implementation found—ndk
最初报错出自于申请了io权限之后,然后手机就一直报错找不到implementation of xxx,debug打印的错误提示如下:
然后在全局搜索下找到了这个丢了的文件,在build里面一个很深的文件夹,不过文件夹名称是armeabi-v7a,而运行时候却非要在arm64-v8a里面找,找了一圈也没发现在哪能设置这个搜索路径。最后问了一下,这里的查找方式是优先找v8,如果有这个文件夹就不在其它文件夹找了,而现在这个文件夹里面又没有libqgfilelog-lib.so(因为不支持64位),结果提示找不到。解决方案是在gradle里面添加ndk{abiFilters “armeabi-v7a”},就可以跳过v8文件夹只查找v7a的文件夹了。
至于为什么多出来了个arm64文件夹,最后推测可能是本地之前新建过一个对应的模拟器。不过为什么运行GrantPermissionRule.grant()之后会触发这条路径搜索,暂时还没搞清楚。
- 环境配置
IDE本身没有太多需要配置的,代理配置好就ok
- 如何Mock 无返回值的方法:
暂时没找到和mockito一样的处理(mockito有专门对应void返回类型的几条语句),下面是mockk网站上一个类似的方案
Mocking nothing
Nothing special here. If you have a function returning Nothing:
Then you need to throw some exception as a behaviour:
- 覆盖率工具
a) Local unit test
如果单测用例是本地用例,可以直接使用AS自带的工具。首先进入run/debug配置页面,新增一条JUnit配置,选项分别填写:
Test kind: All in Package
Package:测试代码所在的package
Search for tests:Across Module Dependencies
VM-options:-ea(默认就是这个_)
Working directory:工程路径
Use ClassPath of mod:选择待测模块
配置后保存,然后在工具栏选择debug右侧的“Run xxx with Coverage”(各个版本AS展示的图标不太一样),等待跑完就可以看到coverage窗口给出覆盖率
b) Instrumented test
需要使用jacoco跟踪生成覆盖率报表
首先在需要生成数据的模块Gradle内添加buildTypes{debug{testCoverageEnabled true}}
重新同步后,命令行依次执行:
./gradlew testDebugUnitTest
./gradlew createDebugCoverageReport
批跑结束后在对应模块的build/reports/coverage/debug/index.html内可以看到详细的覆盖率数据:
最后抛一个问题:大家觉得单测中是否有必要控制mock的使用(能mock的地方全部使用mock VS 只有mock才能解决的时候才使用mock)?
后期我们会根据每个维度陆续写相关的测试文章,如果你有兴趣,请关注我们哦。
长按指纹识别图中的二维码,获取更多测试干货分享!
将我们公众号置顶
不会漏掉我们的原创干货哦!