Espresso實戰:快速的Android UI自動化測試

jopen 9年前發布 | 14K 次閱讀 Espresso 測試工具

在我和很多Android開發者聊天的時候,我注意到他們在開發的過程中并不注重測試這一環節,原因是他們認為Android測試太難實現,或者難以集成到現有的工程中等等。但是實際上寫一個 Espresso并不是一件很難的事情,而且它能夠非常方便地集成到你的工程之中。容易實現

Espresso測試是非常容易實現的,它由三部分組成:

  • ViewMachers:尋找用來測試的View。
  • ViewActions:發送交互事件。
  • ViewAssertions:檢驗測試結果。
  • </ul>

    舉個例子,接下來這部分代碼向id為name_field的EditText輸入”Steve”,并點擊id為greet_button的按鈕,最后檢查屏幕上是否有”Hello Steve!”字樣。

    @Test
    public void testSayHello() {
      onView(withId(R.id.name_field)).perform(typeText("Steve"));
      onView(withId(R.id.greet_button)).perform(click());
      onView(withText("Hello Steve!")).check(matches(isDisplayed()));
    }

    是不是很簡單?我們再來看看在多線程情況下如何進行測試。

    集成測試

    Espresso官方文檔有這樣一段話:

    引用

    Espresso測試有個很強大的地方是它在多個測試操作中是線程安全的。Espresso會等待當前進程的消息隊列中的UI事件,并且在任何一個測試操作中會等待其中的AsyncTask結束才會執行下一個測試。這能夠解決程序中大部分的線程同步問題。

    我一般使用 Retrofit來處理我的Http請求,而不是AsyncTask(雖然大多數人還是使用AsyncTask),在這種情況下也有別的辦法來實現線程安全的測試。Espresso中有個API叫做registerIdlingResource,它可以讓你使用自定義的線程安全邏輯。

    通過IdlingResource,我們可以通過以下這段代碼來實現線程同步的Retrofit接口:

    public class MockApiService implements ApiService, IdlingResource {

    private final ApiService api; private final AtomicInteger counter; private final List<ResourceCallback> callbacks;

    public MockApiService(ApiService api) { this.api = api; this.callbacks = new ArrayList<>(); this.counter = new AtomicInteger(0); }

    @Override public Response doWork() { counter.incrementAndGet(); return decrementAndNotify(api.doWork()); }

    @Override public String getName() { return this.getClass().getName(); }

    @Override public boolean isIdleNow() { return counter.get() == 0; }

    @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { callbacks.add(resourceCallback); }

    private <T> T decrementAndNotify(T data) { counter.decrementAndGet(); notifyIdle(); return data; }

    private void notifyIdle() { if (counter.get() == 0) { for (ResourceCallback cb : callbacks) { cb.onTransitionToIdle(); } } } }</pre>

    這個類告訴了Espresso你的應用將會在(doWork())方法調用后才能夠進入下一個步驟。但是你看完這段代碼應該馬上意識到一件事情:這樣的寫法太過啰嗦了,你需要實現很多方法才能做到這線程同步一個小功能。一定有其他更好的辦法來實現(接下來就是了!)。

    實際上技巧就隱藏在之前的官方文檔中,“Expresso會等待UI事件……并等待AsyncTask的結束才會執行下一個測試”。 實際上我們只要在AsyncTask的ThreadPoolExecutor中執行Retrofit請求就可以了!

    幸運的是Retrofit的BaseAdapter.Builder類提供了這樣一種方法:

    new RestAdapter.Builder()
       .setExecutors(AsyncTask.THREAD_POOL_EXECUTOR, new MainThreadExecutor())
       .build();

    如此簡單,你還有理由不寫Espresso測試嗎?

    本文出自: Michael Evans ,譯文出自: 開發技術前線 ,譯者: desmond1121 ,校對者: Mr.Simple

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!