如何为android检测测试设置环境并进行示例Activity UI测试?

时间:2016-05-06 18:10:18

标签: android unit-testing android-studio testing

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

  

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

1 个答案:

答案 0 :(得分:0)

有更好的答案吗?

尽管谷歌在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 - 它提供了对Application类的测试。它可用于测试应用程序的生命周期;

  •   
  • InstrumentationTestRunner - 运行Android测试用例的运行者。我刚刚发现了这个......希望这对其他人有帮助......如果你想要的话   有关何时以及如何使用的更多详细信息,请参阅APIDemos测试   应用程序在android SDK中的samples目录中。

  •   
     

对于这个答案的肯定,用户Bharat Pawar   Using Android Test Framework;

01 - 设置Gradle模块

在您的app 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测试。在Web中的示例中,将有人使用JUnit3。最后一个不会使用注释,而是使用标准方法名称(以“test”开头),但是,目前,Google告诉您在测试中使用JUnit4

  

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

     
      
  • @Before :使用此批注指定包含测试设置操作的代码块。测试类调用此代码块   在每次测试之前。您可以使用多个@Before方法但订单   其中测试类调用这些方法的方法无法保证;

  •   
  • @After :此批注指定包含测试拆除操作的代码块。测试类之后调用此代码块   每种测试方法。您可以在自己的中定义多个@After操作   测试代码。使用此批注从内存中释放所有资源;

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

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

  •   
  • @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构建期间发生:库冲突时发生; 描述:导入测试特定库时,它可能与Application已存在的库冲突; 解决方案:从冲突的库中排除冲突的模块;

问题02 :检测错误因超时而失败。 时发生:启动检测测试; 描述:入侵测试不支持作为睾丸活动的进度条的存在; 解决方案:在测试活动中,确保在完成加载后将进度条可见性设置为GONE;

更多例子

如果您想查看有关如何使用测试框架的更多示例,请查看this链接;