前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android终端单测杂烩

Android终端单测杂烩

作者头像
腾讯移动品质中心TMQ
发布2019-07-11 09:40:12
1.8K0
发布2019-07-11 09:40:12
举报
  • 给测试同学-关于语言补习

 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)?

后期我们会根据每个维度陆续写相关的测试文章,如果你有兴趣,请关注我们哦。

长按指纹识别图中的二维码,获取更多测试干货分享!

 将我们公众号置顶 

 不会漏掉我们的原创干货哦!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯移动品质中心TMQ 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •  Kotlin
  •  Java
  •  以上两种,先看Java再跟进Kotlin的话,体感大概一~二周差不多可以读懂开发代码+写一些单测用例。有相关经验会更快一些。
  • Mocking nothing
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档