我的目的,旨在介绍一个不一样的“单元测试” !
其实对于单元测试这一块,我很早已经开始关注了,也搜罗了好多这方面技术的博客。要么只有文字性的,要么都是代码的逻辑类,笼统、没有什么脉络可循。之后依然半解,放到项目中,用起来还是不方便,就是觉得这样比我直接运行在模拟器(真机)之后的过程打印、调试要慢好多!
因此,就导致后来的放弃。以及今天的再次拾起,并做一个系统点的介绍,希望特别想要使用单元测试的朋友能够用得着。
不一样 、不一样的 、单元测试
上面,我截取了一个项目中module的目录结构图。看完之后,映入眼帘的是红色框中那两个括弧
中的内容
androidTest
test
她们俩是做什么的?我们就从JUit+Mock+Espresso出发,进行详细无死角的介绍
JUnit 测试
一般而言,使用Android Studio
做安卓开发的我们对项目做测试,无论项目搭建的准备工作或是项目开发进行中的功能行测试。都无非用到两种环境下的测试:
test | androidTest |
---|---|
Java环境下的测试 | Android环境下的测试 |
配置上的区别,也是我们熟悉的地方:在一个module下的build.gradle文件中那一行代码。
支持能够Java虚拟机设备环境下进行测试的默认配置;
//build.gradle/dependencies{}中
testCompile 'junit:junit:4.12'
支持能够Android设备环境下进行测试的默认配置;
//build.gradle/dependencies{}中
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
//且android/defaultConfig{}节点要加上
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
除此之外,两个包内也为我们写了简单的测试代码,作为使用说明
在Android设备上执行的范例
(androidTest)包下
/**
* Instrumentation test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.dalimao.mytaxi", appContext.getPackageName());
}
}
在Java虚拟机设备上执行的范例
(test)包下
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
她们之间明眼的区别在代码上就能发现:注解 @RunWith(AndroidJUnit4.class)
好的,我们该如何使用呢?这是个关键问题!接下来看两种使用方式
【1】test对应下的Java环境下的测试
测试目的:针对的是安卓项目。在基于MVP架构的基础上,使用OkHttp
作网络数据请求,并对其做简单封装,以使用见最简单方式来实现与后台的数据交互。
既可以在要测试的代码中右击鼠标自定义式的选择性生成测试类,也可以仿照已有的测试用例,轻敲几行代码完成。
在代码中选择性的生成
右击鼠标进入
你可以看到上面Generate栏目中的setUp/@Before tearDown/@After
的勾选,也能看到Generate test methods for 栏目下的get() sete() 方法(说明该类只有这俩公共方法)
以及生成的测试类的类名,
生成了这样的效果
public class OkHttpClientImplTest {
...
/**
* 功能:在get()/post()方法执行之前优先执行
* @throws Exception
*/
@Before
public void setUp() throws Exception {
..
}
@Test
public void get() throws Exception {
..
}
@Test
public void post() throws Exception {
..
}
/**
* 功能:在加注解@Before的方法setUp()执行之后立即执行
* @throws Exception
*/
@TearDown
public void get() throws Exception {
..
}
}
贴出具体代码
/**
* @Title:OkHttpClientImplTest
* @Package:com.yjxs.happy
* @Description:使用junit书写测试类
* @Auther:YJH
* @Email:[email protected]
* @Date:2018/6/19 12:36
*/
public class OkHttpClientImplTest {
/**
* 功能:使用get方式进行http请求的测试
*
* @return String
*/
@Test
public void get() {
String url = "https://httpbin.org/get";
// String url = "http://gank.io/api/xiandu/categories";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = null;
String result = null;
try {
response = okHttpClient.newCall(request).execute();
result = response.body().string();
System.out.print("输出get方式请求的结果:==>>" + result);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 功能:使用post方式进行http请求的测试
*/
@Test
public void post() {
MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String url = "http://httpbin.org/post";
RequestBody body = RequestBody.create(JSON, "{\"name\":\"dalimao\"}");
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
System.out.print("输出get方式请求的结果:==>>" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 临时增加测试内容
* 功能:测试计算请求时间
*/
@Test
public void interceptTest() {
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
long start = System.currentTimeMillis();
Request request = chain.request();
Response response = chain.proceed(request);
long end = System.currentTimeMillis();
System.out.print("输出请求的时间:==>>" + (end - start));
return response;
}
};
String url = "http://gank.io/api/xiandu/categories";
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Request request = new Request.Builder().url(url).build();
Response response = null;
String result = null;
try {
response = okHttpClient.newCall(request).execute();
result = response.body().string();
// System.out.print("输出get方式请求的结果:==>>" + result);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 临时增加测试内容
* 功能:测试缓存
*/
@Test
public void cacheTest() {
Cache cache = new Cache(new File("cache.cache"), 5 * 1024 * 1024);
String url = "http://gank.io/api/xiandu/categories";
OkHttpClient okHttpClient = new OkHttpClient
.Builder()
.cache(cache)
.build();
Request request = new Request.Builder()
.url(url)
.cacheControl(CacheControl.FORCE_CACHE)
.build();
try {
Response response = okHttpClient.newCall(request).execute();
System.out.print("输出结果cache:==>>" + response.cacheResponse());
System.out.print("----->输出结果net:==>>" + response.networkResponse());
} catch (IOException e) {
e.printStackTrace();
}
}
}
比如对方法post进行测试,右击鼠标,选中执行Run 'post()'
打印结果: