Android robolectric 入門

我的更多 Android 博文

robolectric的最大特別是運(yùn)行測試程序時不需要設(shè)備或者模擬器,在電腦中進(jìn)行就可以了,自然測試程序的運(yùn)行效率可以大大提升。

環(huán)境搭建

gradle

gradle 中加入

  dependencies {
    ...
    testCompile 'junit:junit:4.10'
    testCompile 'org.robolectric:robolectric:3.0'
  }

==注意==

  • 若寫成testCompile,則測試代碼放在 test 文件夾中
  • 若寫成androidTest,則測試代碼放在 androidTest 文件夾中

Android studio 配置

切換成 Unit Tests

在Build Variants窗口內(nèi)的Test Artifact中選擇了"Unit Tests"


Linux 和 Mac 用戶需要進(jìn)行這一步設(shè)置、

Run -> Edit Configurations -> Defaults -> Junit

注意Robolectric目前不支持android 5.1 API level 22,編譯時 sdk = 21 或者以下。

在project視圖中,test 文件夾下,有個綠的的java 文件夾,綠色文件夾表示是單元測試工程。這些代碼能夠檢測目標(biāo)代碼的正確性,打包時單元測試的代碼不會被編譯進(jìn)入APK中

Activity

Activity的創(chuàng)建

Activity activity = Robolectric.buildActivity(MyAwesomeActivity.class).create().get();

會創(chuàng)建一個MyAwesomeActivity實(shí)例,然后調(diào)用它的onCreat()方法

如果只想驗(yàn)證其onResume()方法,可以如下

ActivityController controller = Robolectric.buildActivity(MyAwesomeActivity.class).create().start();
Activity activity = controller.get();
// assert that something hasn't happened
activityController.resume();
// assert it happened!

如果想測試整個activity 的生命周期可以

Activity activity = Robolectric.buildActivity(MyAwesomeActivity.class).create().start().resume().visible().get();

等你需要在activity中,對view進(jìn)行一些操作時候,比如Robolectric.clickOn(),這時候你需要在create()后加入visible()

舉例

我在工程中建立了三個Activity分別為 MainActivity,AnotherActivity,ThridActivity
在MainActivity加入按鍵跳轉(zhuǎn)到AnotherActivity中,

   public void startAnotherActivity(View view) {
        startActivity(new Intent(MainActivity.this, AnotherActivity.class));
    }

增加單元測試用例判斷跳轉(zhuǎn)的是否正確

    @Test
    public void clickingLogin_shouldStartLoginActivity() {
        Button button = (Button) activity.findViewById(R.id.button);
        assertTrue(button.isEnabled());
        button.performClick();

        Intent expectedIntent = new Intent(activity, ThridActivity.class);
        assertEquals(expectedIntent,shadowOf(activity).getNextStartedActivity() );

    }

1.通過 activity.findViewById 找到button
2.判斷button是否可以點(diǎn)擊
3.點(diǎn)擊button
4.構(gòu)造一個intent(從MainActivity跳轉(zhuǎn)到ThridActivity)
5.判斷實(shí)際跳轉(zhuǎn)的和構(gòu)造的是否一致

結(jié)構(gòu)不一致報(bào)錯

java.lang.AssertionError: 
Expected :Intent{componentName=ComponentInfo{io.github.xuyushi.robolectric/io.github.xuyushi.robolectric.ThridActivity}, extras=Bundle[{}]}
Actual   :Intent{componentName=ComponentInfo{io.github.xuyushi.robolectric/io.github.xuyushi.robolectric.AnotherActivity}, extras=Bundle[{}]}
 <Click to see difference>
    at org.junit.Assert.fail(Assert.java:91)
    at org.junit.Assert.failNotEquals(Assert.java:645)
    at org.junit.Assert.assertEquals(Assert.java:126)
    at org.junit.Assert.assertEquals(Assert.java:145)

可以很清楚的定位到錯誤

Dialog驗(yàn)證

@Test
public void testDialog(){
     Dialog dialog = ShadowDialog.getLatestDialog();
    assertNotNull(dialog);
 }

Toast驗(yàn)證

@Test
public void testToast(){
    assertEquals(toastContent, ShadowToast.getTextOfLatestToast());
 }

Fragment的測試

如果使用support的Fragment,需添加以下依賴
testCompile "org.robolectric:shadows-support-v4:3.0"

shadow-support包提供了將Fragment主動添加到Activity中的方法:SupportFragmentTestUtil.startFragment(),簡易的測試代碼如下

@Test
public void testFragment(){
 SampleFragment sampleFragment = new SampleFragment();
 //此api可以主動添加Fragment到Activity中,因此會觸發(fā)Fragment的onCreateView()
 SupportFragmentTestUtil.startFragment(sampleFragment);
 assertNotNull(sampleFragment.getView());
}

訪問資源文件@Test

public void testResources() {
     Application application = RuntimeEnvironment.application;
     String appName = application.getString(R.string.app_name);
     String activityTitle = application.getString(R.string.title_activity_simple);
     assertEquals("test", appName);
     assertEquals("testActivity",activityTitle);
 }

Shodaw

Robolectric的本質(zhì)是在Java運(yùn)行環(huán)境下,采用Shadow的方式對Android中的組件進(jìn)行模擬測試,從而實(shí)現(xiàn)Android單元測試。對于一些Robolectirc暫不支持的組件,可以采用自定義Shadow的方式擴(kuò)展Robolectric的功能。

定義原始類

public class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

定義 shardow 類

@Implements(User.class)
public class ShadowUser {


    @Implementation
    public String getUsername() {
        return "from ShadowUser";
    }
}

需要讓系統(tǒng)知道 ShardowUser 的存在

定義自己的 RobolectricGradleTestRunner 類,繼承自RobolectricGradleTestRunner

public class UserShadowTestRunner extends RobolectricGradleTestRunner {
    public UserShadowTestRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    public InstrumentationConfiguration createClassLoaderConfig() {

        InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder();
        /**
         * 添加要進(jìn)行Shadow的對象
         */
        builder.addInstrumentedClass(User.class.getName());
        return builder.build();
    }
}

test 測試中使用

Runwith 使用上面自定義的類
同時指明使用 ShadowUser.class,多個類可以加{},中間使用,分開

@RunWith(UserShadowTestRunner.class)
@Config(constants = BuildConfig.class, shadows = ShadowUser.class)
public class LoginActivityTest {

    @Test
    public void testCase() {

        User user = new User("username", "password");
        assertEquals("from ShadowUser", user.getUsername());

    }
}

網(wǎng)絡(luò)請求 mock

gradle 中加入

    testCompile 'org.robolectric:shadows-httpclient:3.0'
    testCompile 'org.robolectric:robolectric-shadows:3.0'

更多robolectric 包見
http://mvnrepository.com/artifact/org.robolectric

未搞定的

  1. 項(xiàng)目網(wǎng)絡(luò)請求使用的是 volley ,網(wǎng)絡(luò)請求并沒有找到合適辦法模擬
  2. 使用了第三方框架 butterknief,并不能模擬

以上有知道如何解決的 請告訴我一聲~ xmy166@gmil.com

參考

http://hkliya.gitbooks.io/unit-test-android-with-robolectric/content/2-api-explained.html
http://www.lxweimin.com/p/9d988a2f8ff7
http://robolectric.org
http://chriszou.com/android-unit-testing-with-robolectric

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容