简述:
在实际项目开发中,都是需要写成千上万个方法或函数,这些函数的功能可能很强大,也可能是很小一个功能,但在程序中使用时都是需要经过测试的,保证这一部分功能是正确的。所以,每编写完一个函数之后,都应该对这个函数的方方面面进行测试,这样的测试称之为单元测试。JUnit 4 是其中一种的单元测试框架。
JUnit 4 注解 @Before 标注setup方法,每个单元测试用例方法调用之前都会调用 @After 标注teardown方法,每个单元测试用例方法调用之后都会调用 @Test 标注的每个方法都是一个测试用例 @BeforeClass 标注的静态方法,在当前测试类所有用例方法执行之前执行 @AfterClass 标注的静态方法,在当前测试类所有用例方法执行之后执行 @Test(timeout=) 为测试用例指定超时时间
JUnit断言 assertTrue(condition) condition为真pass,否则fail assertFalse(condition) condition为假pass,否则fail fail() 直接fail assertEquals(expected, actual) expected equal actual pass,否则fail assertSame(expected, actual) expected == actual pass,否则fail
测试筛选 @RequiresDevice 指定测试仅在物理设备而不在模拟器上运行 @SdkSupress 禁止在低于给定级别的 Android API 级别上运行测试
例如,@SdkSupress(minSdkVersion=18)@SmallTest、@MediumTest和@LargeTest 指定测试的运行时长以及运行频率
系统:Windows 7 64bit
Android 系统:Android Studio 3.0.0.18
本文将简单介绍本地单元测试以及设备单元测试,且都是没有与界面交互的。
1、本地单元测试Local Unit Tests
测试运行在本地开发环境的Java虚拟机上,无需连接Android设备或模拟器。
因此,无法获得Android相关的API,只能测试只使用Java API的一些功能。
1 > 首先,在AS 3.0中新建一个项目“LocalUnitTest”,创建方法参考Android Studio安装与配置第3项
2 > 项目创建完成后,project面板中默认为Android,将其切换为Project
展开app,查看目录结构。从目录结构中可以看到,除了main文件夹外,还有两个文件夹androidTest和test。这两个都是Android Studio自动生成的,也是用来编写测试代码的。为了学习,先将相关的全部删掉,只保留main文件夹需要的。
3 > 首先在app目录的 build.gradle文件中添加下面的引入,根据提示点击Sync Now。
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' //implementation 'com.android.support.constraint:constraint-layout:1.0.2' //JUnit 4 framework testImplementation 'junit:junit:4.12' //androidTestImplementation 'com.android.support.test:runner:1.0.1' //androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' }
4 > 在项目中新建一个Calculation 类,并添加一些需要的测试的函数,如add,multiply
5 > 添加测试方法,选中add → 鼠标右键 → Go To → Test → Create New Test
6 >Testing library 选择JUnit4 ,同时选中待测试的方法,点击OK
选择目录为...\app\src\test\java...,点击OK。
可以看到,Android Studio已经生成了测试类,完善测试类
package com.hebbe.localunittest; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * Created by Hebbe on 2018/1/13. */ public class CalculationTest { Calculation calculation; @BeforeClass public static void start() throws Exception { System.out.println("类运行时调用一次"); } @AfterClass public static void end() throws Exception { System.out.println("类结束时调用一次"); } @Before public void before() throws Exception{ calculation = new Calculation(); System.out.println("每个test方法前都会调用"); } @After public void after() throws Exception { System.out.println("每个test方法后都会调用"); } @Test public void add() throws Exception { System.out.println("test add"); int r = calculation.add(2,3); Assert.assertEquals(5,r); } @Test public void multiply() throws Exception { System.out.println("test multiply"); int r = calculation.multiply(2,3); Assert.assertEquals(6,r); } }
7 > 测试运行效果直接在测试类上单击鼠标右键 → 选择 Run 'CalculationTest'
运行结果:
如果把add测试方法中expected值改为6,再运行,便可看到错误信息
2、设备单元测试 Instrumented Unit Tests
此测试需要连接Android设备或模拟器。可使用Android API,比如测试需要访问设备信息(如目标应用程序的上下文中)或若需要一个Android 相关的API(如Parcelable或SharedPreferences对象)。该测试类必须以 @RunWith(AndroidJUnit4.class)注解作为前缀。
1 > 首先,在AS 3.0中新建一个项目“InstrumentedUnitTest”,创建方法参考Android Studio安装与配置第3项。
同时删除自动生成的一些文件,最终目录结构如下:
2 > 在app目录的build.gradle文件中添加下面的引入,根据提示点击Sync Now
android { defaultConfig { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } } dependencies { androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' }
3 > 在main文件夹中新建一个Config类,编写待测试的方法。
增加几个方法模拟通过SharedPreferences保存数据
package com.hebbe.instrumentedunittest; import android.content.Context; import android.content.SharedPreferences; /** * Created by Hebbe on 2018/1/15. */ public class Config { private static SharedPreferences sharedPreferences; private static SharedPreferences.Editor editor; private static Config instance; private Config(Context context) { sharedPreferences = context.getSharedPreferences("test",Context.MODE_PRIVATE); editor =sharedPreferences.edit(); } public static Config getInstance(Context context){ if (instance == null) { synchronized (Config.class){ if (instance == null){ instance = new Config(context.getApplicationContext()); } } } return instance; } /** * 模拟待测试方法,通过SharedPreferences保存userId * * @param userId */ public static void setUserId(String userId){ editor.putString("userId",userId); editor.commit(); } /** * 模拟待测试方法,通过SharedPreferences读取userId * * @return */ public static String getUserId(){ return sharedPreferences.getString("userId",""); } }
SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置。
获取SharedPreferences的两种方式:
调用Context对象的getSharedPreferences()方法:
此方法获得的SharedPreferences对象可以被同一应用程序下的其他组件共享。
调用Activity对象的getPreferences()方法:
SharedPreferences的四种操作模式:此方法获得的SharedPreferences对象只能在该Activity中使用。
Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。Context.MODE_WORLD_READABLE:表示当前文件可以被其他应用读取。Context.MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。
4 > 生成测试类,在Config类中单击鼠标右键 →Go To →Test →Create New Test
Testing library选择JUnit4,同时在Generate test methods for中同时选中setUserId和getUserId方法:
选择.../app/src/androidTest/java/...
点击OK,然后可以看到在刚刚选择的目录中生成了测试类ConfigTest
5 > 编写测试类
首先需要在类开始添加注解@RunWith(AndroidJUnit4.class)。与Local Unit Tests相比,多了访问设备信息和测试筛选。
编写测试类:
package com.hebbe.instrumentedunittest; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; /** * Created by Hebbe on 2018/1/15. */ @RunWith(AndroidJUnit4.class) public class ConfigTest { private static String userId; @BeforeClass public static void setUp(){ userId = "1002123"; } @Test public void setUserId() throws Exception { //模拟通过SharedPreferences保存userId Context context = InstrumentationRegistry.getTargetContext(); Config.getInstance(context).setUserId(userId); } @Test public void getUserId() throws Exception { //读取保存的数据,对比是否成功 Context context = InstrumentationRegistry.getTargetContext(); String id = Config.getInstance(context).getUserId(); assertEquals(userId,id); } }
6 > 测试运行效果
直接在测试类上单击鼠标右键 → 选择 Run 'ConfigTest',选择模拟器
从结果上看,测试是通过了的: