【问题标题】:How to setup the environment for android instrumentation tests and make a sample Activity UI test?如何为 android 仪器测试设置环境并进行示例 Activity UI 测试?
【发布时间】:2017-07-19 20:10:01
【问题描述】:

免责声明 最近我需要开始测试我的Android应用程序,在我成功测试的过程中发现了很多问题。我的烦恼的答案并不容易找到,因此,我决定将我从社区中学到的东西分享给社区。

我可以回答我自己的问题吗? 是的! Stack Exchange 一直明确鼓励用户回答自己的问题。如果您有一个您已经知道的问题 回答,并且您想公开记录该知识,以便 其他人(包括您自己)以后可以找到它,这是完美的 可以在 Stack Exchange 网站上提出并回答您自己的问题。 https://stackoverflow.com/help/self-answer https://meta.stackexchange.com/questions/17845/etiquette-for-answering-your-own-question

【问题讨论】:

    标签: android unit-testing android-studio testing


    【解决方案1】:

    有更好的答案吗?

    尽管 Google 在 Android 文档中提供了规范,但对于那些缺乏 Gradle 和 Android Studio 经验并希望开始开发仪器测试的人来说,可能会出现一些问题。

    理解主题

    在继续本主题之前,请花十分钟阅读this 文章。它将使您了解测试应用程序的基本概念。

    了解 Android 测试中使用的基本超类:

    • TestCase – 普通的旧 JUnit 测试用例。它可以扩展为测试不绑定到 Android 框架的实用程序类;

    • AndroidTestCase – 它扩展了 JUnit 的 TestCase。与 ActivityTestCase 相比,它是一个更轻量级的测试类。它不需要启动 运行它的活动。它的 getContext() 方法允许你得到一个 如果需要,注入上下文。因为你可以从 这个类,你可以膨胀你的 UI 对象来测试它们的行为;

    • ActivityInstrumentationTestCase2 – 这是 ActivityInstrumentationTestCase 的较新版本。 ActivityInstrumentationTestCase 是 在 Android SDK 1.5 中已弃用。相比之下,这是一个更重的测试课程 到 AndroidTestCase。它为单个用户提供 UI 和功能测试 活动。您可以通过以下方式获得您正在测试的注入活动 调用它的 getActivity() 方法。正在测试的活动是 在每次测试之前和之后启动和完成;

    • ActivityUnitTestCase – 它为测试活动提供了一个隔离的环境。当使用它来测试一个活动时,该活动不是 附在系统上。这使您可以更好地控制哪种 您希望在其中测试您的活动的环境;

    • ApplicationTestCase – 它为应用程序类提供测试。可用于测试应用的生命周期;

    • InstrumentationTestRunner – 运行 Android 测试用例的运行器。我刚找到这个..希望这对其他人有帮助...如果你想要 更多详细信息,例如何时以及如何使用,请参阅 APIDemos 测试 android SDK 中的示例目录中的应用程序。

    此答案的功劳,用户 Bharat Pawar Using Android Test Framework;

    01 - 设置 Gradle 模块

    在您的应用 gradle 模块中导入以下库:

    defaultConfig {
       testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    
    dependencies {
       testCompile 'junit:junit:4.12'
       testCompile 'org.mockito:mockito-core:1.10.19'
       androidTestCompile 'junit:junit:4.12'
       androidTestCompile 'com.android.support:support-annotations:23.0.1'
       androidTestCompile 'com.android.support.test:runner:0.4.1'
       androidTestCompile 'com.android.support.test:rules:0.4.1'
       androidTestCompile 'com.android.support:support-annotations:24.0.0-alpha2'
       androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
       androidTestCompile ('com.android.support.test.espresso:espresso-contrib:2.2.1') {
           exclude module: 'support-annotations'
           exclude module: 'support-v4'
           exclude module: 'support-v13'
           exclude module: 'recyclerview-v7'
       }
       androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
     }
    

    02 - 编写您的活动测试

    这是一个使用 JUnit4 的示例 UI 测试。在网上找到的示例中,会有人使用 JUnit3。最后一个不会使用注释,而是使用标准方法名称(以“test”开头),但是,目前,Google 告诉您在测试中使用 JUnit4

    在您的 JUnit 4 测试类中,您可以调用测试中的部分 使用以下注解进行特殊处理的代码:

    • @Before:使用此注解指定包含测试设置操作的代码块。测试类调用此代码块 每次测试前。您可以有多个 @Before 方法,但顺序 不保证测试类调用这些方法的位置;

    • @After:此注解指定包含测试拆卸操作的代码块。测试类在之后调用这个代码块 每种测试方法。您可以在您的 测试代码。使用此注解从内存中释放任何资源;

    • @Test:使用此注解标记测试方法。单个测试类可以包含多个测试方法,每个测试方法都以 this 为前缀 注释;

    • @Rule:规则允许您以可重用的方式灵活地添加或重新定义每个测试方法的行为。在Android测试中,使用这个 注释与 Android 的测试规则类之一 测试支持库提供,如 ActivityTestRule 或 服务测试规则;

    • @BeforeClass:使用此注解指定每个测试类的静态方法只能调用一次。此测试步骤对于 昂贵的操作,例如连接到数据库;

    • @AfterClass:使用此注解指定测试类的静态方法,仅在类中的所有测试都运行后调用。 此测试步骤对于释放分配的任何资源很有用 @BeforeClass 块;

    • @Test(timeout=):一些注释支持传入可以设置值的元素。例如, 您可以指定测试的超时时间。如果测试开始但 在给定的超时期限内未完成,它会自动 失败。您必须以毫秒为单位指定超时时间,对于 示例:@Test(timeout=5000)

    .

    来源https://developer.android.com/tools/testing/testing_android.html

    import android.content.Intent;
    import android.support.test.InstrumentationRegistry;
    import android.support.test.espresso.contrib.RecyclerViewActions;
    import android.support.test.espresso.matcher.ViewMatchers;
    import android.support.test.rule.ActivityTestRule;
    import android.support.test.runner.AndroidJUnit4;
    import android.support.v7.widget.RecyclerView;
    import android.test.ActivityInstrumentationTestCase2;
    
    import org.hamcrest.Matchers;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.FixMethodOrder;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.MethodSorters;
    
    import br.com.hole19.marvel.R;
    import br.com.hole19.marvel.ui.commons.util.ActivityTemplate;
    
    import static android.support.test.espresso.action.ViewActions.click;
    import static android.support.test.espresso.Espresso.*;
    import static android.support.test.espresso.matcher.ViewMatchers.withId;
    
    
    /**
     * Created by Edgar on 04/05/2016.
     */
    @RunWith(AndroidJUnit4.class)
    @FixMethodOrder(MethodSorters.NAME_ASCENDING)
    public class TestActivityHomepage extends ActivityInstrumentationTestC;se2 <ActivityHomepage> {
    
        private static final String TAG = "TestActivityHomepage";
    
    
        private ActivityHomepage mActivity;
        public ActivityTestRule<ActivityHomepage> rule = new ActivityTestRule(ActivityHomepage.class, true, false);
    
        public TestActivityHomepage() {
            super(ActivityHomepage.class);
        }
    
       @Before
        public void setUp() throws Exception {
            super.setUp();
            Intent intent = new Intent();
            mActivity = rule.launchActivity(intent);
        }
    
        @Test
        public void testPreconditions() {
            assertNotNull(mActivity);
        }
    
        @Test
        public void testLoadMoreCharacters () throws InterruptedException {
            RecyclerView characters = (RecyclerView) this.mActivity.findViewById(R.id.characters);
            int previousSize = characters.getAdapter().getItemCount();
            characters.smoothScrollToPosition(previousSize);
            Thread.sleep(2000);
            int newSize = characters.getAdapter().getItemCount();
            onView(withId(R.id.characters)).perform(RecyclerViewActions.scrollToPosition(previousSize));
            assertNotSame(previousSize, newSize);
        }
    
        @Test
        public void openActivityCharacter () {
            onView(withId(R.id.characters))
                    .perform(
                            RecyclerViewActions
                                    .actionOnItemAtPosition(0, click()));
    
            assertFalse(mActivity.isRunning());
        }
      }
    

    03 - 问题调查

    在创建测试的过程中可能会出现一些问题:

    问题 01:gradle 完成错误。 发生时间:gradle build 时库冲突; 说明:导入测试特定库时,可能会与应用程序已存在的库发生冲突; 解决方案:从冲突库中排除冲突模块;


    问题 02:检测错误因超时而失败。 发生时间:启动仪器测试; 说明:仪器测试不支持被测活动中存在进度条; 解决方案:在测试的activity中,确保加载完成后将进度条可见性设置为GONE;

    更多示例

    如果您想进一步了解如何使用测试框架的示例,请查看this 链接;

    【讨论】:

      猜你喜欢
      • 2017-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 2014-05-22
      • 2021-05-26
      相关资源
      最近更新 更多