Android 谈谈自动化测试
Android自动化测试原来可以这么简单
几款Android 应用自动化测试工具
Android自动化测试探索(一)adb详细介绍 - 周希 - 博客园
移动测试基础 Android:自动化兼容性测试
Android 上一次编写,随处测试
androidStudio版本BumbleBee2021.1.1Patch3
文章日期20220421
android官网测试指南(可能需要梯子)
android 官方测试演示程序
github地址: https://github.com/android/testing-samples/tree/masterhttps://github.com/android/testing-samples/tree/master
测试入门
android测试个人理解分为本地测试和设备模拟测试
本地测试就是不依赖设备或者模拟器,只需要jvm虚拟机在pc上就可以完成的测试.特点是不依赖android框架,可以快速测试
设备模拟测试,指依赖android框架API或者设备服务设备其他应用.测试速度较慢,但是可以完成比本地测试更强大的功能
本地测试的实现多是指Junit测试框架
设备模拟测试,这里使用的是内置的AndroidJunitRunner测试框架
本地测试
参考官方示例
本地测试依赖项
dependencies {// Required -- JUnit 4 frameworktestImplementation 'junit:junit:4.12'// Optional -- Mockito frameworktestImplementation 'org.mockito:mockito-core:1.10.19'}
本地测试代码基础结构
public class CalculatorTest {private Calculator mCalculator;/*** Before注解,测试前的准备工作* 测试框架会优先运行before注解的方法* 该注解方法限制为public*/@Beforepublic void setUp() {mCalculator = new Calculator();}/*** After注解,测试后释放资源工作* 测试框架在运行完test注解方法后最后运行的方法* 同After,限制方法public*/@Afterpublic void tearDown(){mCalculator=null;}/*** Test注解,真正测试的方法* 运行在Before和After之间* 一般运行结果要有断言来设置期望的结果或者异常* assertThat()来设置期望结果* 还有许多更方便的断言库可以选择,配合Junit框架*/@Testpublic void addTwoNumbers() {double resultAdd = mCalculator.add(1d, 1d);assertThat(resultAdd, is(equalTo(2d)));}/*** Test注解,真正测试的方法* 运行在Before和After之间* 一般运行结果要有断言来设置期望的结果或者异常* Test注解内变量expected设置期望的异常*/@Test(expected = IllegalArgumentException.class)public void divDivideByZeroThrows() {mCalculator.div(32d,0d);}}
Mock模拟框架
如果需要依赖其他复杂的组件,但是只是依赖比较简单的功能,可以用Mock模拟框架,来提供一个虚假的对象,定制依赖的功能,从而起到隔离作用
//定义一个依赖context的类
class StringUtil{private Context mContext;public StringUtil(Context context) {mContext = context;}/*** 依赖context返回商店名* @return*/public String getShopId(){return mContext.getString(R.string.settings_merchant_item_merchant_id);}
}//测试StringUtil.getShopId()方法
//runWith加载MockitoJUnitRunner框架入口类
@RunWith(MockitoJUnitRunner.class)
public class MockStringTest {//mock注解标记需要模拟的对象@MockContext mContext;@Testpublic void testGetString(){//mock的方法定义一个模拟规则when(mContext.getString(R.string.settings_merchant_item_merchant_id)).thenReturn("Hello World");//加载模拟类并断言测试StringUtil stringUtil=new StringUtil(mContext);Assert.assertEquals("Hello World",stringUtil.getShopId());}
}
设备模拟测试
参考官方演示程序中AndroidJunitRunnerSample示例
设备模拟测试需要结合Junit测试框架一起使用
依赖项
build.gralde文件android {defaultConfig {...testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}}dependencies{//runner本体androidTestImplementation 'androidx.test:runner:1.1.0'//配合runner使用的Junit库,以及获取context的相关库androidTestImplementation 'androidx.test.ext:junit:1.1.3'// Optional -- rule可用可不用androidTestImplementation 'androidx.test:rules:1.1.0'// Optional -- Hamcrest library 更人性化的断言库androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'// Optional -- UI testing with Espresso UI测试库androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'}
查看一个测试类的代码结构
/*** JUnit4 unit tests for the calculator logic.* RunWith注解,测试框架入口,不同的框架有不同的入口类,这里是android扩展的Junit4* SmallTest注解,标记测试的大小,按照时间分类,有小测试(<200ms),中等测试(<1000ms),大测试(>1000ms),大测试(>),分片测试(支持测试分片)*/
@RunWith(AndroidJUnit4.class)
@SmallTest
public class CalculatorTest {private Calculator mCalculator;/*** Before注解,测试前的准备工作* 测试框架会优先运行before注解的方法* 该注解方法限制为public*/@Beforepublic void setUp() {mCalculator = new Calculator();}/*** After注解,测试后释放资源工作* 测试框架在运行完test注解方法后最后运行的方法* 同After,限制方法public*/@Afterpublic void tearDown(){mCalculator=null;}/*** Test注解,真正测试的方法* 运行在Before和After之间* 一般运行结果要有断言来设置期望的结果或者异常* assertThat()来设置期望结果* 还有许多更方便的断言库可以选择,配合Junit框架*/@Testpublic void addTwoNumbers() {double resultAdd = mCalculator.add(1d, 1d);assertThat(resultAdd, is(equalTo(2d)));}/*** Test注解,真正测试的方法* 运行在Before和After之间* 一般运行结果要有断言来设置期望的结果或者异常* Test注解内变量expected设置期望的异常*/@Test(expected = IllegalArgumentException.class)public void divDivideByZeroThrows() {mCalculator.div(32d,0d);}}
获取androidApi
插装测试的特点就是可以获取android的Api参数
可以结合UI测试框架,进行UI测试
获取Context参数
//来自androidx.test:monitor库
Context appContext = InstrumentationRegistry.getInstrumentation().getContext();
//来自androidx.test:core库
Context appContext2=ApplicationProvider.getApplicationContext();build.gradle{...
dependencies{//引入android的junit扩展库即可获得上述两个库.此外也是替换runner库中的AndroidJunit4来源androidTestImplementation "androidx.test.ext:junit:1.1.3"
}
}
结合Espresso框架测试UI
@RunWith(AndroidJUnit4.class)
@LargeTest
public class CalculatorInstrumentationTest {/*** Use {@link ActivityScenario} to create and launch of the activity.*/@Beforepublic void launchActivity() {//加载activity界面,launch方法可以添加Bundle参数来控制activity初始化ActivityScenario.launch(CalculatorActivity.class);}@Testpublic void noOperandShowsComputationError() {final String expectedResult = getApplicationContext().getString(R.string.computationError);//Epresso框架模拟触发控件onView(withId(R.id.operation_add_btn)).perform(click());onView(withId(R.id.operation_result_text_view)).check(matches(withText(expectedResult)));}}
套件测试
假设已经有了很多插桩测试文件,现在希望能够一起有顺序的运行测试文件,Junit框架支持把若干测试类组合起来作为一个套件运行测试
/*** 定义一个套件测试类* 效果是按照添加SuiteClasses中的顺序执行测试类* 1.RunWith中添加入口Suite.class* 2.Suite.SuiteClasses注解中顺序添加要执行的测试类* 3.直接运行该套件测试类* 4.会依次执行每个测试类的before-test-after*/
@RunWith(Suite.class)
@Suite.SuiteClasses({TestSuiteFirst.class,TestSuiteSecond.class,TestSuiteThird.class
})
public class TestSuite {
}