Android 单元测试初体验
Android 单元测试初体验
- 前言
- 一、单元测试是什么?
- 二、简单使用
- 1.依赖
- 2.单元测试代码简单模版及解释
- 总结
前言
当初在学校学安卓的时候,老师敢教学进度,翻到单元测试这一章节的时候提了两句,没有把单元测试当重点讲,只是说我们工作中几乎不会用到,果真在之前的几年工作当中我真的没有用到,工作中都没有写过单元测试,后来我自己也下意识的忽略了这一块,直到听说现在这家公司后面会要求单元测试用例覆盖率达到百分之七十。我开始慌了,单元测试什么的,国内真的不太重视,这不,抽个周末简单学习下。对于安卓的单元测试的话,现在新建一个项目可以看到都是用的Junit4,ps:涉及Compose的单元测试本文不会过多解释。
这是官网 https://junit.org/junit4/
一、单元测试是什么?
安卓的单元测试是一种针对应用程序中的最小可测试单元——即单个函数、方法或逻辑模块——进行测试的策略。它专注于验证每个独立单元的特定功能和行为,以确保代码的正确性。
单元测试的目的是提高代码质量,减少bug,提高软件可靠性,同时降低维护成本。它是最为基础的测试形式,能够快速反馈问题,定位错误,并且在开发周期中尽早发现并解决问题,从而避免问题随着时间的推移而变得更加复杂。
虽然单元测试可能看起来很麻烦,但它的价值是无可替代的。通过单元测试,开发人员可以:
- 验证每个单元的功能是否符合预期;
- 检测代码中的潜在错误和漏洞;
- 确保代码在各种条件下都能正常运行;
- 提高代码的可读性和可维护性;
- 为代码重构提供安全保障。
在安卓开发中,由于其环境复杂性和多样性,单元测试尤为重要。通过单元测试,开发者可以更加自信地修改和优化代码,同时确保用户在使用应用程序时能够获得稳定、可靠的性能。虽然初始的投入可能会让人们觉得麻烦,但随着时间的推移,你会发现它在提高开发效率和保障应用程序质量方面具有巨大的优势。虽然单元测试可能会增加一些开发的初始工作量,但它能够为提高软件质量、减少后期维护成本提供强有力的支持。对于安卓开发来说,学会如何有效地进行单元测试,将是非常重要的一步。
二、简单使用
1.依赖
代码如下(示例):
dependencies {implementation("androidx.core:core-ktx:1.9.0")implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")implementation("androidx.activity:activity-compose:1.7.0")implementation(platform("androidx.compose:compose-bom:2023.03.00"))implementation("androidx.compose.ui:ui")implementation("androidx.compose.ui:ui-graphics")implementation("androidx.compose.ui:ui-tooling-preview")implementation("androidx.compose.material3:material3")testImplementation("junit:junit:4.13.2")androidTestImplementation("androidx.test.ext:junit:1.1.5")androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))androidTestImplementation("androidx.compose.ui:ui-test-junit4")debugImplementation("androidx.compose.ui:ui-tooling")debugImplementation("androidx.compose.ui:ui-test-manifest")
}
上面的是新建一个Compose项目的依赖,有Compose的物料库,我们的测试相关依赖带主要是下面几个
testImplementation("junit:junit:4.13.2")androidTestImplementation("androidx.test.ext:junit:1.1.5")androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))androidTestImplementation("androidx.compose.ui:ui-test-junit4")debugImplementation("androidx.compose.ui:ui-tooling")debugImplementation("androidx.compose.ui:ui-test-manifest")
我将为你解释每一行的作用:
-
testImplementation("junit:junit:4.13.2")
- 这是用于单元测试的依赖。JUnit是Java中广泛使用的单元测试框架,
4.13.2
是它的版本号。当你写单元测试时(通常在src/test/java
目录下),JUnit为你提供了注解、断言等测试工具。
- 这是用于单元测试的依赖。JUnit是Java中广泛使用的单元测试框架,
-
androidTestImplementation("androidx.test.ext:junit:1.1.5")
- 这是Android测试专用的JUnit扩展库。它提供了Android特定的功能,例如运行测试前的设备初始化等。
-
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
- Espresso是Android的测试框架,用于编写UI测试。它允许你模拟用户交互行为,如点击、滑动等,并验证应用的状态。
espresso-core
是Espresso的核心库。
- Espresso是Android的测试框架,用于编写UI测试。它允许你模拟用户交互行为,如点击、滑动等,并验证应用的状态。
-
androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
- 这是关于Android Jetpack Compose的依赖。Compose是Android的现代UI工具包,用于构建原生的UI。这一行导入了一个Bill of Materials (BOM)平台,它可以帮助管理和解析Compose相关的库版本。通过使用BOM,开发者可以确保他们使用的所有Compose库版本都是相互兼容的。
-
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
- 这是为Jetpack Compose UI测试提供的JUnit4支持库。如果你使用Compose构建UI并希望进行UI测试,这个库会很有用。
-
debugImplementation("androidx.compose.ui:ui-tooling")
- 这是Compose的工具库,通常在debug版本中使用。它为开发者提供了检查、诊断和与Compose UI交互的功能。例如,当你在模拟器或连接的设备上运行应用时,这个库可以帮助你在开发工具中预览和检查Compose UI。
-
debugImplementation("androidx.compose.ui:ui-test-manifest")
- 这个库提供了为Compose UI测试所需的AndroidManifest.xml中的配置和权限。当你在debug模式下运行应用时,这些配置和权限可以确保测试的顺利运行。
这些依赖确保我们的Android项目拥有进行单元测试和Android设备测试所需的所有工具和框架。
2.单元测试代码简单模版及解释
有了上面的依赖,我们就可以开始写一些简单的单元测试代码了。我们先看下项目结构
上面的androidTest包下是涉及一些页面测试的,我们本文先从单元测试开始,所以就在test包下的ExampleUnitTest.kt下编写代码就好。
代码如下(示例):
package com.example.mytestimport org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test/*** Example local unit test, which will execute on the development machine (host).** See [testing documentation](http://d.android.com/tools/testing).*/
class ExampleUnitTest {private var emptyList: List<*>? = null/*** Sets up the test fixture.* (Called before every test case method.)*/@Beforefun setUp() {emptyList = ArrayList<Any?>()}/*** Tears down the test fixture.* (Called after every test case method.)*/@Afterfun tearDown() {emptyList = null}@Testfun testSomeBehavior() {assertEquals("Empty list should have 0 elements", 0, emptyList!!.size)}@Test(expected = IndexOutOfBoundsException::class)fun testForException() {val o = emptyList!![0]!!}}
先讲注解
- @Test注解:告诉 Junit4 他是一个测试方法。
- @Before 注解:在每执行一个带有@Test注解的方法之前带有@Before 注解的方法都会执行。
- @After 注解:在每执行一个带有@Test注解的方法之后带有@After注解的方法都会执行。
…注解有很多哟,这里只是简单介绍几个
再讲方法
- assertEquals (描述,需要对比的值1,需要对比的值2) 如果需要对比的值1和需要对比的值2不相等则抛出异常
@Test(expected = IndexOutOfBoundsException::class)
expected 表示如果不抛出 IndexOutOfBoundsException这个异常,则方法执行失败
总结
最后我们运行一下,测试通过本文完结!
相关文章:

Android 单元测试初体验
Android 单元测试初体验 前言一、单元测试是什么?二、简单使用1.依赖2.单元测试代码简单模版及解释 总结 前言 当初在学校学安卓的时候,老师敢教学进度,翻到单元测试这一章节的时候提了两句,没有把单元测试当重点讲,只…...
HarmonyOS—ArkTS中@Observed和@ObjectLink装饰器的嵌套类对象属性变化【鸿蒙应用开发】
文章目录 ARKTS中@Observed和@ObjectLink装饰器的嵌套类对象属性变化@Observed 类装饰器说明装饰器参数类装饰器的使用@ObjectLink 变量装饰器说明装饰器参数同步类型允许装饰的变量类型被装饰变量的初始值举例装饰器的限制条件观察变化和行为表现观察的变化框架行为使用场景1.…...

设计问卷调查问题的技巧二:确定问题的结构与顺序
上篇文章中,我们了解到设计问卷调查问卷的技巧有保持问题中立、少用开放式问题、保持全名平衡的答案集、谨慎设置单一回答。在这篇文章中,我们将继续深入探讨设计问卷调查问题的剩余5大技巧! Tip5:注意问题的顺序 虽然您可以任意…...

kubernetes使用nfs创建pvc部署mysql stateful的方法
kubernetes创建的pod默认都是无状态的,换句话说删除以后不会保留任何数据。 所以对于mysql这种有状态的应用,必须使用持久化存储作为支撑,才能部署成有状态的stateful. 最简单的方法就是使用nfs作为网络存储,因为nfs存储很容易被…...

JavaScript WebApi(二) 详解
监听事件 介绍 事件监听是一种用于在特定条件下执行代码的编程技术。在Web开发中,事件监听器可以用于捕获和响应用户与页面交互的各种操作,如点击、滚动、输入等。 事件监听的基本原理是,通过在特定元素上注册事件监听器,当事件…...

纯新手发布鸿蒙的第一个java应用
第一个java开发鸿蒙应用 1.下载和安装华为自己的app开发软件DevEco Studio HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 2.打开IDE新建工程(当前用的IDEA 3.1.1 Release) 选择第一个,其他的默认只能用(API9)版本,…...

UI自动化(selenium+python)之元素定位的三种等待方式!
前言 在UI自动化过程中,常遇到元素未找到,代码报错的情况。这种情况下,需要用等待wait。 在selenium中可以用到三种等待方式即sleep,implicitly_wait,WebDriverWait 一、固定等待(sleep) 导入time模块,设定固定的等待时间 缺…...

[C++]指针与结构体
标题 一.指针1.指针的定义和使用2.指针所占的内存空间3.空指针与野指针4.const修饰指针5.指针和数组6.指针和函数 二.结构体1.结构体的定义与使用2.结构体数组3.结构体指针4.结构体的嵌套使用5.结构体做函数参数6.结构体中const使用场景7.案例练习 一.指针 作用: 可以通过指针…...
注解原理是什么 Spring MVC常用的注解有哪些?
文章目录 注解原理是什么Spring MVC常用的注解有哪些? 通过这篇文章来和大家一起认识springMVC常用的注解,那么首先需要来了解注解。 注解原理是什么 注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。…...

【数据结构】树与二叉树(廿五):树搜索指定数据域的结点(算法FindTarget)
文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点a. 算法FindTargetb. 算法解析c. 代码实现a. 使用指向指针的指针b. 直接返回找到的节点 4. 代码整合 5.3.1 树的存储结构 5.…...

深度学习图像风格迁移 - opencv python 计算机竞赛
文章目录 0 前言1 VGG网络2 风格迁移3 内容损失4 风格损失5 主代码实现6 迁移模型实现7 效果展示8 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习图像风格迁移 - opencv python 该项目较为新颖,适合作为竞赛课题…...
提高SQL语句执行效率的8个方法
提高SQL语句执行效率的8个方法 在日常的数据库操作中,如何提高SQL语句的执行效率是每个程序员都需要关注的问题,SQL语句的执行效率对系统的性能有着重要影响,本文将介绍8种提高SQL语句执行效率的方法。 合理使用索引 索引介绍 索引是数据…...

C语言,通过数组实现循环队列
实现循环队列最难的地方就在于如何判空和判满,只要解决了这两点循环队列的设计就没有问题。接下来我们将会使用数组来实现循环队列。 接下来,为了模拟实现一个容量为4的循环队列,我们创建一个容量为4 1 的数组。 接下来我们将会对这个数组…...

python+pygame+opencv+gpt实现虚拟数字人直播(一)
AI技术突飞猛进,不断的改变着人们的工作和生活。数字人直播作为新兴形式,必将成为未来趋势,具有巨大的、广阔的、惊人的市场前景。它将不断融合创新技术和跨界合作,提供更具个性化和多样化的互动体验,成为未来的一种趋…...

c语言:模拟实现各种字符串函数(2)
strncpy函数: 功能:拷贝指定长度的字符串a到字符串b中 代码模拟实现: //strncpy char* my_strncpy(char* dest, char* str,size_t num) {char* ret dest;assert(dest && str);//断言,如果其中有一个为空指针ÿ…...

【Proteus仿真】【STM32单片机】感应水龙头设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器,使用LCD1602液晶模块、HCSR04超声波等。 主要功能: 系统运行后,LCD1602显示超声波模块检测的距离,若检测距离小…...

P15 C++ 枚举
The ChenPi 前言 今天我们要讲的是 C 中的枚举。 enum 是 enumeration 的缩写,基本上可以说,它就是一个数值集合。如果你想要给枚举一个更实际的定义,它们是给一个值命名的一种方法。 所以我们不用一堆叫做 A、B、C 的整数。我们可以有一个…...

深入理解路由协议:从概念到实践
路由技术是Internet得以持续运转的关键所在,路由是极其有趣而又复杂的课题,永远的话题。 SO:这是一个解析路由协议的基础文章。 目录 前言路由的概念路由协议的分类数据包在网络中的路由过程理解路由表的结构路由器关键功能解析 前言 在互联…...

Qt 串口编程-从入门到实战
1. Qt 串口通信流程解析 1.1 串行通信和并行通信对比 并行通信适合距离较短的通信,且信号容易受干扰,成本高串口通讯-设备(蓝牙, wifi, gprs, gps) 1.2 Qt 串口通信具体流程 1. 创建 QSerial…...

如何获得微软MVP徽章
要成为微软MVP,需要在特定领域成为专家,并积极参与社区,为其他人提供帮助和支持。以下是一些步骤可以帮助你成为MVP: 在特定领域成为专家:要成为MVP,需要在某个领域具有专业知识和经验。这可以通过阅读相关…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...