在Android Studio中,我们经常会遇到一个痛点:运行一次项目需要等待很长时间。为了解决这个问题,我们需要研究一下Android Studio的单元测试。实际上,我的目的很简单:在不操作视图的前提下,测试一些Activity的生命周期,或者网络拉取数据的一些处理,例如解析JSON数据、进行网络请求等,也就是对Model层的测试。这些不需要操作视图,但在没有单元测试环境下,例如我们网络请求一些数据,通过Log打印查看是否请求成功,却又需要利用模拟器或真机运行一次项目,这就导致了耗时较长的问题,这是不能容忍的。
幸运的是,强大的Android Studio也考虑到了这一点,为我们提供了简单的单元测试类。让我们来简单地了解一下如何使用它们吧。
首先,我们需要了解一些名称,以便在后面的介绍和使用中更加得心应手:
1. 在Java中,我们使用过JUnit的单元测试。由于Android是基于Java语言编写的,所以也有JUnit的单元测试。在进行Android的单元测试时,需要导入以下依赖:
```xml
androidTestCompile 'junit:junit:4.12'
testCompile 'junit:junit:4.12'
```
其中,test目录为在本机执行单元测试代码的目录,androidTest为在Android设备上执行单元测试代码的目录。如下图所示:
2. Android自带的JUnit单元测试的一些测试类(androidTest测试需要运行在模拟器或真机上):
- InstrumentationTestCase框架:Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的。我们可以将它理解为一种没有图形界面的、具有启动能力的工具类,用于监控其他类(用Target Package声明)。
举个例子,利用InstrumentationTestCase启动一个activity:
在androidTest目录下新建一个Java类,并继承自InstrumentationTestCase。然后编写一个public void的方法,但是必须要是方法名以test打头,例如testPublishSubject。注意,这个方法不需要@Test注解。
ApplicationTestCase是用于测试整个应用程序的类。它允许你将模拟的Context注入到应用程序中,在应用程序启动之前初始化测试参数,并在应用程序结束之后销毁之前检查应用程序。通过使用Context,你可以浏览资源、文件、数据库等。ApplicationTestCase的基类是AndroidTestCase,通常与特定组件关联的是它的子类。
以下是ApplicationTestCase的测试代码示例:
```java
// 测试代码
Log.d("MyApp", ".........MyApp....app_name..........demo");
Log.d("TestRunner", "started: testStart(demo.zts.com.demo.ApplicationTest)");
Log.d("ApplicationTest", ".............ApplicationTest..........app_name..............demo");
```
ActivityUnitTestCase是用于对单个Activity进行单一测试的类。通过使用它,你可以注入模拟的Context或Application,或者两者。它主要用于对Activity进行单元测试。也就是说,你可以用于测试单独的activity,虽然也需要利用模拟机或真机启动,但你启动的只是你需要做测试的activity,与其他activity无关。
以下是ActivityUnitTestCase的测试代码示例:
要测试的activity:
```java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
```
测试类:
```java
public class ActivityUnitTestCase extends ActivityUnitTestCase
public ActivityUnitTestCase() {
super(MainActivity.class);
}
}
```
测试 Log 日志:
```java
* 07-22 23:39:44.146 3171-3171/demo.zts.com.demo I/System.out: ...............MainActivity......onCreate............
07-22 23:39:44.146 3171-3171/demo.zts.com.demo I/MainActivity: ................onCreate............................
```
以下是重构后的内容:
```
07-22 23:39:44.151 3171-3171/demo.zts.com.demo D/MZPerfObserver: demo.zts.com.demo onCreate consume 153 ms
07-22 23:39:44.151 3171-3171/demo.zts.com.demo I/System.out: ...............MainActivity......onStart............
07-22 23:39:44.151 3171-3171/demo.zts.com.demo I/MainActivity: ................onStart............................
07-22 23:39:44.326 3171-3171/demo.zts.com.demo D/OpenGLRenderer: Enabling debug mode 0
07-22 23:39:44.361 3171-3171/demo.zts.com.demo I/System.out: ...............MainActivity......onStop............
07-22 23:39:44.361 3171-3171/demo.zts.com.demo I/MainActivity: ................onStop............................
07-22 23:39:44.421 3171-3224/demo.zts.com.demo I/TestActivity: ................startActivity............................
还有很多常见的测试,比如ServiceTestCase,ProviderTestCase2等,大家需要慢慢琢磨。
Android 自带的 junit单元测试的一些测试类(test 测试 ,不需要模拟机,电脑直接运行)
```
请根据提供的内容完成内容重构,并保持段落结构:
比如我需要测试一段Java代码,而这段Java代码跟Android没关系,也就是不用到Android的资源,如Context、Activity等,说白了就是简单的Java测试。当然,嘿嘿,Android Studio也是可以做Java代码测试的。
测试代码如下,测试4+4等于几:
```java
public class JsonTest {
public static void main(String[] args) {
int result = 4 + 4;
System.out.println("4 + 4 = " + result);
}
}
```
测试成功:以上测试类的运行是 -点击测试右键 - 选择 RunXXXXXX。
/*********************华丽分割线***********************/
看了半天好像也没有解决文章最初提到的一个痛点啊,就是我需要测试Android的资源,但又不想运行笨重的模拟机或真机,怎么办呢?妈蛋,被骗了,还钱 -_-、、、确实,上面提到的测试方法虽然没有解决拜托模拟机测试的痛点,但基于模拟机单元测试的androidTest确实方便我们做一些单独功能的测试,而且能做UI测试,因为需要模拟机或真机嘛,所以UI或视图测试是没问题的。还有test测试,可以做一些不需要Android资源的Java代码测试,也是在Android开发当中很方便的,不用在启用Eclipse做测试,直接Android Studio既可以了。
忽悠,接着忽悠 -_-////
其实要想脱离模拟机或真机,又要做使用Android资源的测试,如使用Context、浏览资源、文件、数据库等等。也是可以的!!!那就要第三方测试框架了Robolectric。666,你是来做宣传的吗 -_-、、、不过真的很好用,也能很好的解决咱们的痛点。
接下来利用个需求来讲解Robolectric测试,免得我忽悠你们。拿到android目录下的assets下的json01.txt文件是一段json数据,然后进行解析,解析后将数据显示。分析:这个需求就跟android下的资源有关,而咱们利用Robolectric做单元测试,并且不需要模拟机或真机的支持。其中json数据首先需要Robolectric依赖,在你的app module下注入依赖:
```xml
testCompile 'org.robolectric:robolectric:3.0'
```
在进行单元测试时,我们需要注意的是使用`testCompile`而不是`androidTestCompile`,否则你需要启动模拟器。同时,测试类需要放在`test`目录下。下面是一个简单的测试类示例:
```java
import android.content.res.AssetManager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricConfig;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MyUnitTest {
@Test
public void testJson() {
AssetManager am = RuntimeEnvironment.application.getAssets();
// ...其他操作
}
}
```
注意事项:
1. 测试类头部需要声明`@RunWith`和`@Config`注解;
2. 测试方法需要以`testxxx()`开头,并添加`@Test`注解;
3. Robolectric还可以测试Activity,如上面的`MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class);`。这句代码会启动MainActivity的生命周期。
4. 启动Robolectric单元测试类与启动普通单元测试类似,选择`-MyUnitTestTest --右键 -- 选择 Run MyUnitTestTest`。
需要注意的是,这些仅仅是基本的操作,还有很多强大的功能等待你去探索。