Android测试框架介绍

来源:互联网 发布:天刀数据怎么导入 编辑:程序博客网 时间:2024/05/21 17:50

Android测试框架是开发环境的重要组成部分,他提供了一种架构和强大的工具。可以实现对应用程序的各个方面不同水平的测试,从单元测试到框架测试。

1. 测试框架的特性

  •  基于JUnit

          Android测试套件基于JUnit。不用调用Android的API,就可以使用JUnit测试一个类,或者使用Android的Junit扩展测试android的组件。

  • 组件的测试

         Android的junit扩展提供了针对组件的测试用例类。这些类为创建mock对象和方法提供帮助,从而帮助你实现对组件生命周期的控制 。

  • 测试工程同应用工程类似

         测试套件包含在测试包中,与主应用程序包类似。因此,你不需要学习新工具或技术来设计、构建测试 。

  • 自动创建测试工程

         可以使用包含ADT的Eclipse或者和其他IDE(命令行模式)来创建测试工程,编译和执行。这些工具从被测项目的应用中获得信息,之后使用该信息自动创建构建文件、manifest文件、以及测试包的目录结构 。

  • 自动事件流模拟工具

         SDK也提供了 monkeyrunner、UI/Application Exerciser Monkey工具,monkeyrunner是用Python实现的一种API测试策略。UI/Application Exerciser Monkey是一种命令行工具,通过对设备发送随机事件进行UI的压力测试。

    2. 测试框架的结构

  • Android的构建与测试工具设想测试项目被组织成一个标准的测试结构,及测试用例类、测试包、还有测试项目。

    Android的测试是基于JUnit的。JUnit的测试大体上就是一个方法,由方法中的语句对待测试应用的某一部分进行测试。你将这些测试方法组织在一起,放到一个叫做测试用例(或者测试套件)的类中。每个测试在待测试应用的单个模块中都是独立的。每个测试用例类都是相关测试方法的一个容器,尽管它也提供一些帮助方法。

    在JUnit中,一个或多个测试源文件被构建到class文件中;在Android中,你同样使用SDK的构建工具将一个或多个测试源文件构建到Android测试包中的class文件里。在JUnit中,你使用测试运行器来执行测试用例;在Android中,你使用测试工具加载测试包和待测应用,然后由工具来执行特定的Android测试运行器。

     

  • 3. 测试项目

  • MyProject/

            AndroidManifest.xml

            res/

                 ... (resources for main application)

             src/

                 ... (source code for main application) ...

             tests/

                 AndroidManifest.xml

                 res/

                    ... (resources for tests) 

                 src/

                   ... (source code for tests)

    4. 测试API

         Android测试API是基于JUnit的API,扩展了instrumentation框架与android-specific测试类

     

    4.1 JUnit

    你可以在普通的Java对象上使用JUnitTestCase类来做单元测试。TestCase类也是AndroidTestCase类的父类,你可以使用AndroidTestCase类来测试依赖Android的对象。AndroidTestCase类除了提供JUnit框架中拥有的功能,也提供了专门在Android上使用的setupteardown和帮助方法。

    你使用JUnit中的Assert类来显示测试结果。assert方法将你在测试中期望的结果与实际的结果作比较,并且在比较失败的时候抛出异常。Android也提供了断言类,它继承了JUnit Assert类中的各种断言类型,还提供了另一类用于测试界面的断言。

    4.2 Instrumentation

    Android系统中,仪器是指一组控制方法或者“钩子”。这些钩子控制着Android组件,使其独立于它正常的生命周期。它们也控制着Android如何加载应用程序。

    正常情况下,Android组件运行在由系统决定的生命周期中。比如,一个Activity对象的生命周期在它被一个Intent激活时开始,它的onCreate()方法被调用,然后是onResume()。当用户启动另一个应用,onPause()方法被调用。如果Activity的代码调用了finish()方法,那么onDestroy()方法会被调用。Android的框架API不提供让你直接调用这些回调方法的方式,但是你可以使用仪器(instrumentation)来做这些。

    同样,系统把一个应用程序中的所有组件运行在同一个进程中。你可以允许一些组件,如content provider,运行在一个独立的进程中,但是你不能强制一个应用程序和一个已经运行的应用程序运行在同一个进程中。

    然而,有了Android仪器,你可以在测试代码中调用那些回调方法。这让你可以一步一步地遍历运行一个组件的生命周期,仿佛你在调试组件。下面的代码片段演示了如何使用仪器来测试一个Activity保存和恢复状态:

  • // Start the main activity of the application under test
        mActivity = getActivity();

        // Get a handle to the Activity object's main UI widget, a Spinner
        mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01);

        // Set the Spinner to a known position
        mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION);

        // Stop the activity - The onDestroy() method should save the state of the Spinner
        mActivity.finish();

        // Re-start the Activity - the onResume() method should restore the state of the Spinner
        mActivity = getActivity();

        // Get the Spinner's current position
        int currentPosition = mActivity.getSpinnerPosition();

        // Assert that the current position is the same as the starting position
        assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition);

  • 4.3 Test case classes

    Android提供了一些测试用例类,它们都继承自TestCase类和Assert类,并带有Android特定的setup,teardown和帮助方法。

      

    4.3.1 AndroidTestCase

    AndroidTestCase类是一个有用的通用类,特别是在你刚开始接触Android测试的时候。它继承了TestCase类和Assert类,提供了JUnit标准的setUp()和tearDown()方法,还有所有的JUnit里的Assert方法。此外,它还提供了测试许可(permission)的方法和通过清除一些类引用来防止内存泄露的方法。

    4.3.2 Component-specific test cases

    Android测试框架的一个关键特性就是它的特定组件测试类。这些类提供了安装(setup)和卸载(teardown)测试所需资源(fixture)的方法和控制组件生命周期的方法,解决了对特定组件进行测试的需求。它们还提供了创建模拟对象的方法。我们在特定组件测试的章节中讨论这些类:

    * Activity测试

    * Content Provider测试

    * Service测试

    Android没有为BroadcastReceiver提供一个独立的测试用例类,取而代之的是通过向注册BroadcastReceiver的组件发送一个intent对象,判断broadcast receiver能否正确响应来进行测试的。

     4.3.3 Application TestCase

    你使用ApplicationTestCase类来测试Application对象的setup和teardown。这些对象维护着一个应用包中的所有组件都使用的全局状态信息。这个测试用例在验证清单文件中<application>元素是否被正确设置(setup)时是很有用的。但是注意该测试用例不允许你进行应用包中组件的测试。

    4.3.4 InstrumentationTestCase

    如果你想在测试用例中用到仪器方法,你必须使用InstrumentationTestCase类或它的一个子类。Activity测试用例继承了该基类并实现了其他功能帮助Activity测试。

    4.4 Assertion classes

    由于Android测试用例类继承自JUnit,你可以使用断言方法来显示测试的结果。断言方法的作用是将测试返回的实际结果同你期望的结果作比较,并在比较失败的时候抛出AssertionException。使用断言比记录日志更便利,能提供更好的测试效果。

    除了JUnit的Assert类方法,测试API还提供了MoreAsserts和ViewAsserts类:

    * MoreAsserts类包含了更强大的断言,比如assertContainsRegex(String, String)方法,它能够匹配正则表达式。

    * ViewAsserts类包含测试视图时有用的断言。例如assertHasScreenCoordinates(View, View, int, int)方法,该方法能测试一个视图在可视屏幕特定的(X,Y)坐标处是否有位置。这些断言方法简化了对界面几何形状和对齐方式的测试。

    4.5 Mock object classes

    为了在测试中方便地使用依赖注入,Android提供了创建模拟系统对象的类,比如Context对象,ContentProvider对象,ContentResolver对象和Service对象。一些测试用例还提供了Intent模拟对象。你使用这些对象既是为了将测试与系统中的其他测试隔离开来,又能很方便的在测试中使用依赖注入。这些类能在Java包android.test和android.test.mock中找到。

    模拟对象通过“屏蔽”(stub out)或重写常规方法将测试同正在运行的系统隔离开。例如,MockContentResolver使用自己的本地框架替代常规的Resolver框架,这与系统的其他部分是隔离的。MockContentResolver也屏蔽了notifyChange(Uri, ContentObserver, boolean)方法,这样测试环境外的观察者对象就不会被不小心触发了。

    模拟对象还通过提供常规对象的子类来方便依赖注入,这些模拟对象并没有实际的功能,除非你重写了父类的方法。例如,MockResources对象是Resources的子类,里面所有的方法在调用时都会抛出异常。使用它的时候,你只需重写必须提供信息的方法。

    下面这些是Android中可用的模拟对象:

    (1)简单模拟对象类(Simple mock object classes)

    MockApplication,MockContext,MockContentProvider,MockCursor,MockDialogInterface,MockPackageManager和MockResources提供了简单有用的模拟策略。他们是系统中相应对象的空实现(stubbed-out)版本,其中所有的方法在被调用的时候会抛出UnsupportedOperationException。使用它们的时候,你重写需要的方法来依赖模拟。

    注意:MockContentProvider和MockCursor是API level 8中新添的。

    (2)Resolver模拟对象(Resolver mock objects)

    MockContentResolver通过屏蔽掉系统的常规resolver框架,提供了对content providers的隔离测试。MockContentResolver使用自己的内部表,而不是提供一个authority string去系统内部查找content provider。你必须显示地使用addProvider(String, ContentProvider)方法为内部表增加provider。

    有了这个功能,你能将一个模拟的content provider与一个authority关联起来。你能创建一个真实provider的实例,但是仅使用其中的测试数据。你甚至可以设置一个authority的provider为null。实际上,一个MockContentResolver对象将你的测试同包含真实数据的provider隔离开来了。你可以控制provider的功能,你可以防止测试影响到真实的数据。

    4.6 上下文测试

    Android提供了两个上下文类用于测试:

    *   IsolatedContext提供了一个隔离的上下文(Context),使用该上下文的文件、目录、数据库操作将发生在测试空间。尽管它的功能受限,该上下文还是有足够的桩代码(stub code)响应系统调用。

    该类允许你测试应用的数据操作,而且不会影响到可能在设备上存在的真实数据。

    *   RenamingDelegatingContext提供了一个上下文,其中大多数的操作都由一个已存在的上下文处理,但是文件和数据库的操作由一个IsolatedContext处理。隔离部分使用测试目录,并创建特殊的文件和目录名。你可以自己控制它们的命名,或者让构造器自动决定。

    该对象提供了一种为数据操作设置隔离区的快速方式,并且保留了对其他上下文操作的常规功能。

    5. 测试的执行

    测试用例是通过测试运行器类运行的,测试运行器先加载测试用例类,然后安装(set up)测试资源,运行测试用例,最后卸载(tear down)每个测试的资源。Android的测试运行器还必须装上测试仪器(instrumentation),以便启动应用的系统工具能控制测试包(test package)如何加载测试用例和待测应用程序。你通过在测试包的清单文件中设置一个值来告诉android平台使用哪个装好仪器的测试运行器。

    InstrumentationTestRunner是主要的测试运行器。它继承了JUnit的测试运行器框架并且装上了测试仪器。它能运行Android提供的所有测试用例类,并支持所有可能的测试种类。

    你在测试包的清单文件的instrumentation元素中指定InstrumentationTestRunner或它的子类作为你的测试运行器。InstrumentationTestRunner的代码在共享库android.test.runner中,该库正常情况下没有被连接到Android代码中。你必须在uses-library元素中指定包含它。你不需要自己手动设置这些元素,Eclipse的ADT工具和android命令行工具会在你的测试包清单文件中自动构建他们。

    注意:如果你要使用别的测试运行器而不是InstrumentationTestRunner,你必须改变<instrumentation>元素,使它指向你要用的类。

    你要使用被Android工具调用的内部系统类来运行InstrumentationTestRunner。当你在装有ADT的Eclipse中运行测试时,这些类会被自动调用。当你从命令行中运行测试时,你通过Android Debug Bridge(adb)工具运行它们。

    这些系统类加载和启动测试包时,先杀死所有正在运行的待测应用的进程,然后加载待测应用的新进程。然后它们将控制交给InstrumentationTestRunner,由它来运行测试包下的每个测试用例。你还可以使用Eclipse ADT插件中的设置选项(settings)和命令行工具的标志位(flag)来控制运行哪些测试用例和方法。

    待测应用既不是由系统类启动,也不是由InstrumentationTestRunner启动,而是由测试用例直接启动的。测试用例既可以调用待测应用的方法,又可以调用自己的方法,这些方法能在待测应用中触发生命周期时间的事件。待测应用在测试用例的完全控制之下,这就允许测试用例在运行测试之前设置(set up)测试环境(测试fixture)。

    6. 查看测试结果

    Android测试框架将测试结果返回到运行测试的工具上。如果你在Eclipse中使用ADT来运行测试,那么测试结果显示在一个新的Junit视图窗格种。如果你从一个命令行中运行测试,那么结果显示在STDOUT中。在两种情况下,你都会看到一个测试总结显示每个测试用例的名字和其中运行的方法。你还能看到所有发生的断言失败,它们包括了出错行的指针。断言失败还列出了期望值和实际值。

     

    7. monkey and monkeyrunner

    SDK针对功能级别的测试提供了两个工具:

    * UI/Application Exerciser Monkey,通常被叫做“monkey”,是一个向设备发送键盘敲击、触摸、手势等伪随机流的命令行工具。你使用Android Debug Bridge(adb)来启动它。你使用它来对你的程序作压力测试并报道遇到的错误。你可以通过每次使用相同的随机数种子启动该工具来重复一个事件流。

    用法示例如下:
    adb shell monkey -p your.package.name -v 500

    * monkeyrunner工具是使用Python来测试程序的一套API和执行环境。这套API包括了连接设备、安装和卸载应用包、截屏、比较两幅图片和运行测试应用测试包的功能。有了monkeyrunner命令行工具提供的这套API,你可以写出大型的、强大的、复杂的测试。

     

    8. 测试类之间的关系

  • 0 0
    原创粉丝点击