发布于 2017-10-05 00:27:02 | 113 次阅读 | 评论: 0 | 来源: 网友投递

这里有新鲜出炉的Android Studio教程,程序狗速度看过来!

Android Studio Android 开发环境

Android Studio 是一个全新的 Android 开发环境,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试


昨天在完善项目的时候,需要进行单元测试,在Eclipse环境中进行是很简单的,但是在Android Studio环境中进行单元测试,在国内找了很多资料,大都是人云亦云,本文发布出来供大家学习参考。

面对android studio Run 一次项目要等好几分钟的痛点,不得不研究一下android studio 的单元测试。

其实我的目的很简单,在不对视图进行操作的前提下,测试一些activity 的生命周期,或网络拉取数据的一些处理,比如解析 json 数据啊,做网络请求啊等等,也就是对 Model层的测试。这些不需要操作视图,但在没有单元测试环境下,比如我们网络请求一些数据,Log 打印看看是否请求成功,却又要 利用模拟器或真机Run 一次项目,花费好几分钟,这是不能容忍的。

于是乎,强大的 android studio 也考虑到了这一点,给我们提供的简单的单元测试类。

让我们来简单的了解学习一下吧。

首先先来了解一下一些名称,方便下面介绍和使用:

在java中咱们有用过 JUnit 的 单元测试 ,那android 也是基于 java 语言编写的,所以也有个 JUnit的单元测试。在做 android 的单元测试需要导入依赖:

androidTestCompile 'junit:junit:4.12'
testCompile 'junit:junit:4.12'

其中, test目录为在本机执行单元测试代码的目录, androidTest为在Android设备上执行单元测试代码的目录。如下图:

Android 自带的 junit单元测试的一些测试类(androidTest测试 需要运行在模拟机或真机上)

1、InstrumentationTestCase框架:

Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的,我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。

举个例子,利用InstrumentationTestCase 启动一个activity:

在androidTest下新建一个java类,并且继承自InstrumentationTestCase编写一个public void的方法,但是必须要是方法名以test打头,比如testPublishSubject,并不需要@Test注解


public class TestSubject extends InstrumentationTestCase {
  private static final String LOG_TAG = "test";
 
  public void testPublishSubject() {
 
    launchActivity("demo.zts.com.demo",SecondActivity.class,null);
  }
}

2、ApplicationTestCase——测试整个应用程序的类。它允许你注入一个模拟的Context到应用程序中,在应用程序启动之前初始化测试参数,并在应用程序结束之后销毁之前检查应用程序。

使用Context,你可以浏览资源,文件,数据库等等。基类是AndroidTestCase,一般常见的是它的子类,和特定组件关联。

测试代码如下:


public class MyApp extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    String app_name = getResources().getString(R.string.app_name);
    Log.i("MyApp",".........MyApp....app_name.........."+app_name);
  }
}
public class ApplicationTest extends ApplicationTestCase<MyApp> {
  public ApplicationTest() {
    super(MyApp.class);
  }
  public void testStart() {
    String str = null;
    str = mContext.getResources().getString(R.string.app_name);
    Log.i("..",".............ApplicationTest ...........app_name............."+str);
  }

Log 日志:

 07-22 23:27:10.276 32259-32259/demo.zts.com.demo I/MyApp: .........MyApp....app_name..........demo
 07-22 23:27:10.276 32259-32319/demo.zts.com.demo I/TestRunner: started: testStart(demo.zts.com.demo.ApplicationTest)
 07-22 23:27:10.286 32259-32319/demo.zts.com.demo I/..: .............ApplicationTest..........app_name..............demo

3、ActivityUnitTestCase——对单个Activity进行单一测试的类。使用它,你可以注入模拟的Context或Application,或者两者。它用于对Activity进行单元测试。也就是说你可以用于测试单独的activity ,虽然也需要利用模拟机或真机启动,但你启动的只是你需要做测试的activity,于其他activity无关。
测试代码如下:

要测试的 activity


public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    System.out.println("...............MainActivity......onCreate............");
    Log.i("MainActivity","................onCreate............................");

  }
  @Override
  protected void onStart() {
    super.onStart();
    System.out.println("...............MainActivity......onStart............");
    Log.i("MainActivity","................onStart............................");
  }
  @Override
  protected void onStop() {
    super.onStop();
    System.out.println("...............MainActivity......onStop............");
    Log.i("MainActivity","................onStop............................");
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    System.out.println("...............MainActivity......onDestroy............");
    Log.i("MainActivity","................onDestroy............................");
  }
}

测试类


public class TestActivity extends ActivityInstrumentationTestCase2<MainActivity> {

  private Context ctx;

  public TestActivity() {
    super(MainActivity.class);
  }

  @Override
  protected void setUp() throws Exception {
    super.setUp();
    ctx = getActivity().getApplicationContext();
  }

  public void testStart() {
    Intent intent = new Intent(ctx, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    ctx.startActivity(intent);
    Log.i("TestActivity","................startActivity............................");

  }

测试 Log 日志:

  * 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 等于几:


public class ExampleUnitTest {
  @Test
  public void testAdd() {

    int i = 0;
    i = 4+4;
    System.out.print(".............. "+i);
    Log.i("TAG","..................."+i);
    // 比较 i 是否 等于 8 ,相等的话通过测试!!!
    Assert.assertEquals(8, i);
  }
}

测试成功:

以上测试类的运行是 -点击测试右键 - 选择 RunXXXXX

/*********************华丽分割线***********************/

看了半天好像也没有解决文章最初提到的一个痛点啊,就是我需要测试android的资源,但又不想运行笨重的模拟机或真机,怎么办呢? 妈蛋,被骗了,还钱 -_-、、、 确实,上面提到的测试方法虽然没有解决拜托模拟机测试的痛点,但基于模拟机单元测试的 androidTest 确实方便我们做一些 单独功能的测试,而且能做 UI 测试,因为需要模拟机或真机嘛,所以 UI 或视图测试是没问题的。 还有test 测试,可以做一些不需要android资源的 java代码测试,也是在android开发当中很方便的,不用在启用eclipse 做测试,直接android studio 既可以了。

忽悠,接着 忽悠 -_-////

其实要想脱离 模拟机或真机,又要做使用android资源的测试,如 使用Context,浏览资源,文件,数据库等等。 也是可以的!!! 那 就只有第三方测试框架了 Robolectric

666,你是来做宣传的吗 -_-、、、不过真的很好用,也能很好的解决咱们的痛点。

接下来利用个需求来讲解 Robolectric 测试,免得我忽悠你们。

拿到 android 目录下的 assets 下的json01.txt文件 是一段json数据,让后进行解析,解析后将数据显示。 分析:这个需求就跟android下的资源有关,而咱们利用 Robolectric 做单元测试,并且不需要模拟机或真机的支持。

其中json数据


{
 "name": "coolxing",
 "age": 24,
 "male": true,
 "address": {
  "street": "huiLongGuan",
  "city": "beijing",
  "country": "china"
 }
}

首先需要 Robolectric 依赖,在你的 app module 下注入依赖:

testCompile 'org.robolectric:robolectric:3.0'
注意是 testCompile 而不是 androidTestCompile ,不然你有需要启动模拟器了。并且测试类也是 在 test 下的

测试类:


@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MainActivityTest2 {

  @Test
  public void testJson(){
    String str = null;
    str = RuntimeEnvironment.application.getResources().getString(R.string.app_name);

    AssetManager am = null;
    am = RuntimeEnvironment.application.getAssets();
    String strData = null;
    try {
      InputStream inputStream = am.open("json01.txt");
      byte buf[] = new byte[1024];
      inputStream.read(buf);
      strData = new String(buf);
      strData =strData.trim();
      strData.trim();
    } catch (IOException e) {

    }
    jsonBean foo = new Gson().fromJson(strData, jsonBean.class);
    System.out.println("...............json.................."+foo.name);
    System.out.println("...............json.................."+foo.address);
    System.out.println("...............json.................."+foo.age);
  }
}

测试结果:

看,咱们利用application 拿到 android 下的资源,但又不像刚才上面的 androidTestCompile 需要模拟机,是不是很6,我电脑配置比较低,本次测试需要40S多,但不真机快多了。

am = RuntimeEnvironment.application.getAssets();

需要注意几点,类头部需要声明  @ 注解:

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)

并且测试方法是以 textxxx() 开头的,如上面的 testJson() ,方法也需要@Test注解!!!
Robolectric 还可以测试 activity ,如:


@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MainActivityTest2 {
  @Test
  public void testMainActivity() {

    MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class);
    mainActivity.findViewById(R.id.main_tv).performClick();


    Intent expectedIntent = new Intent(mainActivity, SecondActivity.class);

    ShadowActivity openActivity = Shadows.shadowOf(mainActivity);
    Intent actualIntent = openActivity .getNextStartedActivity();

    // Assert.assertEquals(expectedIntent, actualIntent);

  }

其中

MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class);

这句代码就是启动了MainActivity 的生命周期

Robolectric 单元测试类 的 启动 也是跟 上面test 测试类一样,选择 -MainActivityTest2 --右键 -- 选择 Run MainActivityTest2

好了,单元测试就介绍到这里,

其实我也只是初步理解,上面那些基本的也是我做项目的需要我才去学习使用的,还有好多强大的功能大家慢慢探索。



最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务