Android測試技術

測試

本文Github Demo地址

相比於服務器測試的高度自動化,Android app的測試因其交互性複雜,運行需要Android環境,並且測試用例編寫比較瑣碎等原因,在大部分公司通常單純由測試人員手工完成,自動化程度比較低。每次版本迭代需要把所有的路徑都要覆蓋一遍,費時費力,如果能將一部分重複單調的流程通過測試用例進行覆蓋,就可以較大程度的減少測試人員的重複工作,從而將更多時間花在新功能的測試上。本文將j簡要介紹Android測試技術。

Android的測試分爲Local Unit Test和Instrumented Test,Local Unit Test運行在JVM上,包括所有不需要Android環境的測試用例。Instrumented Test運行在Android真機或Android模擬器上,包括需要Android環境的測試用例。Instrumented Test又分爲Instrumented Unit Test和UI Test,Instrumented Unit Test包括所有跟UI無關的測試用例,UI Test包括所有含UI交互的測試用例。下面將分類介紹各種測試用例。

Local Unit test

運行在java虛擬機上,Android環境無關的代碼測試,不需要Android設備,簡單高效。測試代碼放在 module-name/src/test/java/目錄下。

首先在gradle中添加如下配置:

dependencies {    
    // Required -- JUnit 4 framework    
    testCompile 'junit:junit:4.12'    

    // Optional -- Mockito framework    
    testCompile 'org.mockito:mockito-core:1.10.19'
}

JUnit是單元測試使用的框架,Mockito工具可以mock簡單的Android環境。

@RunWith(MockitoJUnitRunner.class)
public class MainActivityTest {    
    private static final String FAKE_STRING = "Hello world!";    
    @Mock    
    Context mMockContext;   
 
    @Test    
    public void testAdd_Without_Mock() throws Exception {        
        assertEquals(MainActivity.add(1, 3), 4);    
    }    

    @Test    
    public void testCombineString_With_Mock() {                
        when(mMockContext.getString(R.string.hello_word)).thenReturn(FAKE_STRING);        
        ClassUnderTest classUnderTest = new ClassUnderTest(mMockContext);        
        String result = classUnderTest.combineString("Jack!");        
        assertEquals(result, "Hello world! Jack!");    
    }
}

上面的代碼中包含兩個測試用例,第一個是不需要Mock Android環境的測試用例,第二個需要Mock。在testCombineString_With_Mock中,首先通過when指定Mock的Context調用getString函數時的返回值,相當於構造了一個“假的”Context。這樣當ClassUnderTest的實例執行combineString函數時,通過context.getString(R.string.hello_word)返回的就是我們指定的值,從而避免了真正去構造一個Context。在測試文件上右鍵,Run,就可以看到測試結果。

Instrumented tests

運行在Dalvik虛擬機上,Android環境相關,需要運行在Android設備上或模擬器上。測試代碼放在module-name/src/androidTest/java/目錄下。
首先配置gradle:

dependencies {    
    ... 
    androidTestCompile 'com.android.support:support-annotations:23.4.0'    
    androidTestCompile 'com.android.support.test:runner:0.5'    
    androidTestCompile 'com.android.support.test:rules:0.5'    
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'    
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'    
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'    
}

Instrumented Unit Test

@RunWith(AndroidJUnit4.class)
public class ApplicationTest {    
    @Rule    
    public ActivityTestRule<MainActivity> mMainActivity = new ActivityTestRule<>(MainActivity.class);    

    @Test    
    public void combineString() {        
        ClassUnderTest classUnderTest = new ClassUnderTest(mMainActivity.getActivity());        
        String result = classUnderTest.combineString("Jack!");        
        assertEquals(result, "Hello world! Jack!");    
    }
    ...
}

由於這個測試用例運行在Android環境下,所以相比於Local Unit Test,它不需要Mock Context,直接將生成的Activity傳入即可。

UI Test

UI Test分爲app內UI測試和不同app間UI測試,前者使用Espresso庫,後者使用UI Automator庫。

  • app內UI測試
@RunWith(AndroidJUnit4.class)
public class ApplicationTest {    
    @Rule    
    public ActivityTestRule<MainActivity> mMainActivity = new ActivityTestRule<>(MainActivity.class);    

    @Test
    public void onTextViewClickedTest() {    
        onView(withId(R.id.input_et)).perform(typeText("hello world"), closeSoftKeyboard());    
        onView(withId(R.id.clickme_tv)).perform(click()).check(matches(withText("Submit success!")));
    }
    ...
}

利用Espresso進行UI交互模擬使用下面的代碼,詳細用法可參考這裏
onView(ViewMatcher) //1.匹配View
.perform(ViewAction) //2.執行View行爲
.check(ViewAssertion); //3.驗證View

  • 不同app間UI測試
    較少使用,這裏不做介紹。

本文Github Demo地址

參考:
https://developer.android.com/training/testing/index.html
https://segmentfault.com/a/1190000006031195

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章