Test Apps

2017/09/12

Testing Apps on Android

verify the conrrectness, functional, behavior, and usability.

  1. Get Started
    • Get Started With Tesing
    • Test Your App
    • Video:Android Testing Patterns
  2. Testing Tools and APIs
    • Android Testing Support Library
    • UI/App Exerciser Monkey
    • monkeyrunner
    • Testing from the Command-Line
    • dumpsys
  3. App Testing Techniques
    • Automating User Interface Tests
    • Building Effective Unit Tests
    • Testing UI Performace
  4. Other resources
    • Android Testing Samples
    • Android Testing Templates
    • Android Testing Codelab指引
    • Video:Debugging and Testing in Android Studio

1 Getting Started with Testing

  1. Testing is based on JUnit, 可以在JVM上进行本地单元测试,可也在Android设备上测试。

1.1 Test Types

  1. AS写测试用例时,需加入两个不同code dir(source sets).
  2. Local unit tests : module-name/src/test/java, 这些测试可不访问Android framework APIs在JVM运行。
  3. Instrumented tests : module-name/src/androidTest/java,这些测试必须运行在Android设备或模拟器。
    • 装置测试运行在设备上。
    • 系统在同一进程中运行测试apk和app,所以测试用例会调用app内部作用域的method、fields,使app 自动进行用户交互。
  4. 两种用例的不同 diff
  5. Real testing types :
    • Unit tests: Local Unit Test, Instrumented unit tests.
    • Integration集成 test: Components within your app only, Cross-app Components.
  6. Components within your app only:
  7. Cross-app Components:

1.2 Test APIs

1.2.1 JUnit

  1. JUnit5提供unit和integration test,有共同的setup, teardown, assert 操作。
  2. 一个JUnit5测试类包含一个或多个测试接口。一个测试接口开始于@Test,包含练习和验证单个功能的代码。
  3. @Before——setup;@After——tearDown;@Test——mark a test method……JUnit annotations
  4. JUnit Assert 验证一个对象状态的正确性。

1.2.2 Android Testing Support Library

  1. 快速构建运行的测试用例。
  2. AndroidJUnitRunner
  3. Espresso适用于App UI funcs.
  4. UI Automator适用于Cross-app UI funcs测试。

1.2.3 Assertion classes

  1. 比较实际值和期望值(actual value and expected value),如果比较失败抛出AssertionException.
  2. 可使用Hamcrest Library创建简单灵活的测试用例。

1.2.4 Monkey and monkeyrunner

  1. App功能测试两种工具:
  2. Monkey:Android Debug Bridge(adb) 可做压力测试(stree-test), 报告任何遇到的error,多次使用相同随机数种子多次运行来重复事件流。
  3. monkeyrunner:
    • Python编写的API和执行环境。包括连接设备,安装卸载包,截图,比较图像,在app内运行测试用例。
    • 可编写大量的大型、功能强大且复杂的测试。在命令行运行monkeyrunner.

1.3 Gudies for Building Android Tests

  1. Building Local Unit Tests
  2. Building Instrumented Unit Tests
  3. Automating User Interface Tests
  4. Testing App Component Integrations
  5. Testing Display Performance

2 Building Effective Unit Tests

  1. 单元测试是最基本的测试策略。运行单元测试可很快找到crash,修复由代码更改的软件回归到app中。
  2. 重复执行尽可能小的代码块(class,method,component)。验证特定代码的逻辑时创建测试。
  3. 通常,代码单元是单独测试的;您的测试只会影响和监视该单元的更改。

2.1 Building Local Unit Tests

  1. 可在JVM运行的测试。最小化执行时间在本地JVM(Java Virtual Machine)编译。
  2. 使用一个mocking fragment如Mockito完成所有的依赖关系。

2.1.1 Set Up Your Testing Environment

  1. 在以下目录module-name/scr/test/java创建测试。
  2. 配置依赖

     dependencies{
         testCompile 'junit:junit:4.12'
         testCompile 'org.mockito:mockito-core:1.10.19'
     }
    

2.1.2 Create a Local Unit Test Class

  1. Junit5不用extend junit.framwork.TestCase,也无需带有’Test’前缀的命名。
  2. 以@Test开始写一个测试函数。
  3. 使用junit.Assert函数检测功能。

     public class EmailValidatorTest {
         @Test
         public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
             assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));
         }
         ...
     }
    

2.1.3 Mock Android Dependencies

  1. 添加Mockito对象
    • 在build.gradle中添加 Mockito依赖库
    • 以@RunWith(MockitoJUnitRunner.class)定义测试类
    • 以@Mock为Android 依赖创建一个Mock对象
    • 使用when(),thenReturn()返回测试值
     @RunWith(MockitoJUnitRunner.class)
     public class UnitTestSample {
    	
         private static final String FAKE_STRING = "HELLO WORLD";
    	
         @Mock
         Context mMockContext;
    	
         @Test
         public void readStringFromContext_LocalizedString() {
             // Given a mocked Context injected into the object under test...
             when(mMockContext.getString(R.string.hello_word))
                     .thenReturn(FAKE_STRING);
             ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
    	
             // ...when the string is returned from the object under test...
             String result = myObjectUnderTest.getHelloWorldString();
    	
             // ...then the result should be the expected one.
             assertThat(result, is(FAKE_STRING));
         }
       }
    
  2. Mockito API,也可查看Sample.

2.1.4 Run Local Unit Tests

  1. 点击 Sync Project同步Gradle.
  2. 运行测试用例,点击Run.

2.2 Building Instrumented Unit Tests (依赖Android设备)

  1. 使用无法满足模拟的Android 依赖,构建复杂的单元测试。可访问设备信息如app的Context

2.2.1 Set Up Your Testing Environment

  1. moudle-name/src/androidTest/java创建测试。
  2. build.gralde

     dependencies {
         androidTestCompile 'com.android.support:support-annotations:24.0.0'
         androidTestCompile 'com.android.support.test:runner:0.5'
         androidTestCompile 'com.android.support.test:rules:0.5'
         // Optional -- Hamcrest library
         androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
         // Optional -- UI testing with Espresso
         androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
         // Optional -- UI testing with UI Automator
         androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
     }
    

2.2.2 Create an Instrumented Unit Test Class

  1. 以@RunWith(AndroidJUnit4.class)开始创建测试类。其他与Local unit Test相同。
2.2.2.1 Create a test suite
  1. Runs all unit tests。

2.2.3 Run Instrumented Unit Test

  1. 点击 Sync Project同步Gradle.
  2. 运行测试用例,点击Run.
2.2.3.1 Run Your tests with Firebase Test Lab
  1. 需要再去看吧。

3 Automating UI Tests (依赖Android设备)

  1. 为验证一个或多个app 用户交互行为而建的测试。
  2. 自动测试用户操作行为正确性。 避免手工操作UI耗时,乏味和易出错(timecomsuming,tedious,error-prone)。自动化的方法以重复的方式快速、可靠地运行测试。
  3. AS的Automating UI

3.1 Testing UI for a Single App

  1. 确保UI体验。
  2. Espresso运行在Android2.3+(API 10+),可自动测试UI功能

3.1.1 Set up Espresso

  1. build.gradle添加依赖 androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
  2. 关闭所有的动画 Window/Transition/Animator duration scale

3.1.2 Create an Espresso Test Class

  1. 通过调用onView(),or onData()测试Activity中view。
  2. ViewInteraction.perform()测试action。
  3. ViewAssertion检测UI反应与预期作比较。

     onView(withId(R.id.view)) // a ViewMatcher
         .perform(click())	//a ViewAction
         .check(matches(isDisplayed())) // a ViewAssertion
    
3.1.2.1 Using Espresso with ActivityTestRule
  1. 使用ActivityTestRule减少代码量。

     @Rule
     public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
    	
     @Test
     public void changeText_sameActivity() {
         onView(withId(R.id.text)).perform(typeText("XXX"));
     }
    
3.1.2.2 Accessing UI Components
3.1.2.3 Performing Actions
3.1.2.4 Test your activties in isolation with Espresso Intents
3.1.2.5 Testing WebViews with Espresso Web
3.1.2.6 Verifying Results

3.1.3 Run Espresso Tests on a Device or Emulator

3.2 Testing UI for Multiple Apps

3.2.1 Set up Automator

  1. build.gradle添加依赖 androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
  2. Learn when using.

3.2.2 Create an Automator Test Class

3.2.3 Run UI Automator Tests on a Device or Emulator

4 Testing App Component Integrations (依赖Android设备)

  1. 为验证用户不直接交互的组件如Service, Content Provider的测试。
  2. 注意:Android没有为BroadcastReceiver提供测试类,需要通过调用InstrumentationRegistry,getTargetContext()去创建实例,然后测试。

4.1 Testing Your Service

  1. 创建instrumented unit tests验证Service行为的正确性。
  2. Android Testing Support Library提供了单独测试Service的API——ServiceTestRule(但不支持对IntentService的测试)。

4.1.1 Set Up Your Testing Environment

4.1.2 Create an Integration Test for Services

  1. @Rule创建ServiceTestRule实例。@Rule public final ServiceTestRule rule = new ServiceTestRule();
  2. 实现对Service的集成测试。

     @Test
     public void testWithBoundService() throws TimeoutException {
         Intent serviceIntent = new Intent(InstrumentationRegistry.getTargetContext(), LocalService.class);
         serviceIntent.putExtra(LocalService.SEED_KEY, 42L);
         IBinder binder = rule.bindService(serviceIntent);
         LocalService service = ((LocalService.LocalBinder) binder).getService();
    		
         assertThat(service.getRandomInt(), is(any(Integer.class));
     }
    

4.1.3 Run Integration Tests for Services

4.2 Testing Your Content Provider

  1. Content Provider存取数据,提供给别的app访问。

4.2.1 Create Integration Tests for Content Providers

4.2.2 How ProviderTestCase2 works

4.2.3 What to Test

5 Tesing UI Performace

  1. UI性能确保UX始终如一。

5.1 Measuring UI Performance

5.2 Automating UI Performance Test

6 Espresso

7 UI Automator

8 Junit Rules (with Testing Support Library)

  1. ActivityTestRule
  2. ServiceTestRule

9 AndroidJUnitRunner

10 Sample

  1. android-testing

文内导航