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,需要在某个领域具有专业知识和经验。这可以通过阅读相关…...
FireRedASR-AED-L在STM32项目中的应用:离线语音指令识别原型开发
FireRedASR-AED-L在STM32项目中的应用:离线语音指令识别原型开发 最近在做一个智能家居控制的小项目,核心想法挺简单:对着设备说句话,它就能听懂并执行开关灯、调节风扇之类的操作。听起来是不是有点像智能音箱?但我的…...
一键生成九宫格:用yz-bijini-cosplay快速制作社交媒体宣传素材
一键生成九宫格:用yz-bijini-cosplay快速制作社交媒体宣传素材 1. 项目简介:Cosplay内容创作新范式 在社交媒体运营中,视觉内容的重要性不言而喻。对于动漫展会、Cosplay摄影棚等内容创作者而言,如何快速产出高质量的九宫格宣传…...
Qwen3-4B-Instruct-2507保姆级部署教程:3步免费玩转256K长文本AI
Qwen3-4B-Instruct-2507保姆级部署教程:3步免费玩转256K长文本AI 1. 引言:为什么选择Qwen3-4B-Instruct-2507 如果你正在寻找一个能处理超长文本的开源大模型,Qwen3-4B-Instruct-2507绝对值得关注。这个由阿里开源的40亿参数模型࿰…...
DeepSeek-OCR-2开源可部署:完全离线运行的国产OCR大模型方案
DeepSeek-OCR-2开源可部署:完全离线运行的国产OCR大模型方案 1. 项目简介 DeepSeek-OCR-2是DeepSeek团队于2026年1月发布的创新OCR识别模型,采用完全开源的方式提供给开发者使用。这个模型最大的特点是实现了完全离线运行,不需要依赖任何外…...
Wan2.2-I2V-A14B教育落地:K12学校AI课件视频辅助生成工具部署
Wan2.2-I2V-A14B教育落地:K12学校AI课件视频辅助生成工具部署 1. 为什么K12教育需要AI视频生成工具 在K12教育领域,教师每天需要准备大量教学视频素材。传统视频制作需要专业设备和剪辑技能,耗时耗力。Wan2.2-I2V-A14B文生视频模型可以快速…...
STM32duino驱动X-NUCLEO-IKS5A1多传感器融合开发指南
1. STM32duino X-NUCLEO-IKS5A1 扩展板底层驱动技术解析1.1 工业级多传感器融合平台的硬件架构X-NUCLEO-IKS5A1 是意法半导体(ST)面向工业运动感知与环境监测场景推出的高集成度 MEMS 传感器扩展板,专为 STM32 Nucleo 开发平台设计。其核心价…...
如何处理SQL视图的循环依赖_优化架构设计与拆分逻辑
数据库拒绝创建循环依赖视图(如A依赖B、B又依赖A),在CREATE VIEW时即报ORA-04045等错;根本原因是解析依赖图时检测到环,需拆分逻辑、抽离共用子查询为物化视图或表。视图 A 依赖视图 B,B 又依赖 Aÿ…...
微信小程序uView框架下u-picker三级联动实战:从接口加载到视图强制更新
微信小程序uView框架下u-picker三级联动实战:从接口加载到视图强制更新 在微信小程序开发中,省市区三级联动选择器是常见的功能需求。uView作为一款优秀的小程序UI框架,其u-picker组件提供了强大的多级联动支持。本文将深入探讨如何通过接口异…...
智能家居中枢:OpenClaw+千问3.5-35B-A3B-FP8实现多模态家庭控制面板
智能家居中枢:OpenClaw千问3.5-35B-A3B-FP8实现多模态家庭控制面板 1. 为什么需要本地化的智能家居中枢? 去年冬天的一个深夜,我被空调异常启动的噪音惊醒。打开手机APP检查时,发现第三方云服务正在维护,所有设备状态…...
SQL删除视图会删掉原数据吗_DROP VIEW的安全性分析
DROP VIEW仅删除视图定义而非数据,不影响基表;它不校验下游依赖,删后应用调用会报错;真正删数据的是DROP TABLE或DELETE等操作。DELETE、TRUNCATE 和 DROP VIEW 的作用对象完全不同不会删原表数据。DROP VIEW 只是删掉一个「查询的…...
