一直都在写代码,却不知道代码怎么测试,后来由于工程需要,测试是必须的一件事情的时候,我就要去研究怎么测试了。eclipse里面用junit很简单方便,不过现在项目都转android studio(以下简称AS)了,就当然要使用新的测试方法了。
在AS里面,当新建一个android工程时,会在src目录下自动产生一个main目录,还有一个androidTest目录,在androidTest目录里面会有一个applicationTest的java文件。我们要做的就是在这个文件夹里面来测试了。
如果纯粹是测试工具类,那和一般的测试没什么区别,就不赘言了。我这里主要说的是怎么测试回调类中的方法是否被回调,且构造函数需要上下文的,也就是必须在activity中初始化的类。首先,创建自己的类,还有对应的activity类。可以在要测试的类名alt+enter,智能提示,选择createTest,然后把需要测试的方法勾上,按照要求下一步就可以了。他会自动在androidTest中新建一个test+刚才需要测试的类名的类。并且自动生成对应的需要测试的类。
接下来,如果需要测试的是activity中界面的功能,还有生命周期的调用等等,这个测试类需要继承ActivityUnitTestCase<acticity(类名)>类。这个类需要一个构造函数,还有一个setUp(),一个tearDown().顾名思义,setUp()函数里面执行的是初始化的内容。tearDown()用来执行测试完成后的内容。
特别注意的是需要写一个空的构造函数,里面super(activity.class),否则会报错。比如以下代码:
public class WebSettingsTest extends ActivityUnitTestCase<WebViewActivity> {
    public WebSettingsTest() {
        super(WebViewActivity.class);
    }

    public void setUp() throws Exception {
        super.setUp();
        Intent intent = new Intent(getInstrumentation().getContext(), WebViewActivity.class);
        startActivity(intent, null, null);
    }
    }
在这里面我创建了一个intent来启动activity,更加详细的可以参考谷歌官方文档。如果打不开官方文档,也可以看看这个链接能不能打开。[谷歌文档](http://android.toolib.net/reference/android/test/ActivityUnitTestCase.html)
大意就是通过getInstrumentation().getContext()来获取上下文,startActivity()中的三个参数,第一个是intent,第二三个分别是saveBundle,还有个Object类,一般都写成空就行了。这样就会启动一个activity,并且调用其中的onCreate方法,然后自动被tearDown方法关闭。测试过程中就看不到机器上又界面出现。他是运行在测试类的进程里面的,并没有产生UIThread。如果需要测试生命周期,就不要在setUp()方法中调用startActivity方法,自己去调用生命周期的函数就可以实现对生命周期的操控了。如果需要使用activity中的方法,可以使用getActivity()方法。这样大多数时候,测试就很容易了。
还有一种情况,要测试activity中的方法,而不是生命周期之类的函数,主要测功能,这个时候就需要新建的测试类继承ActivityInstrumentationTestCase2<activity(类名)>其他方法类似上面的类,需要注意的是getActivity()方法就相当于启动activity了,可以看到测试机器上界面一闪而过。接下来,就在测试方法中测试回调函数了。可以在activity中回调函数里修改一个变量,通过这个变量我们就可以判断此回调函数是否回调了。这里会有一个问题,就是回调函数需要一定的时间,如果回调需要的时间比较长,这个时候回调函数还没来得及调用,就已经随着activity的销毁,一起消失了,就不会执行了。这个时候,就需要再测试方法中开启一个线程来等待一段时间了。比如:
public void testLoading() throws Exception {
        Thread myThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        myThread.start();
        myThread.join();
        assertEquals(11, getActivity().i);
    }
在这个里面就是跑了一个线程,用来等待。join方法是用来等待线程执行完再执行后面的方法的。
还有一种情况就是自己的类需要在UIThread中运行,那么,在第一种父类ActivityUnitTestCase中就需要使用getInstrumentation().runOnMainSync这个方法来运行,但是这个方法会有个问题,他并不是真正的运行在UIThread中的,而是一个模拟的过程,如果需要UIThread传递个什么东西,这样就不行了。而在第二个父类ActivityInstrumentationTestCase2中,就好处理多了,可以直接在测试方法上注释为@UiThreadTest这样就可以了。
其实大部分内容还是来自谷歌的官方文档,多看看官方文档,可以解决很多问题。