Espresso で アイドリング

espresso

Espresso は以下の非同期処理は考慮してくれるようですが.

- メッセージキューを利用したUIイベント
- デフォルト AsyncTask のスレッドプールを利用したタスク

Square Island: Espresso: Custom Idling Resource

これらに該当しない処理でも, テスト実行を「あるタイミング」まで待たせたいときがありますよね?

カスタムした「IdlingResource」を使ってみましょう.

Espresso Idling Resource

ここで書かれているアプローチとしては2つ.

Counting running jobs: When a job starts, increment a counter. When it finishes, decrement it. The app is idle if the counter is zero. This approach is very simple and accounts for most situations. CountingIdlingResource does exactly this.

Querying state: It might be more reliable to ask a work queue or an HTTP client (or whatever is doing the background work) if it is busy. If the state is exposed, implementing an Idling Resource is trivial.

これらのうち, 汎用的に使えるジョブカウンターを利用した方法を, Googleサンプルを眺めつつ手順整理しておきます.

Android Testing Codelab

1. IdlingResource ユーティリティの作成

アイドリング向けのユーテリティを作成します.
そのまま2つのクラスを利用してもいいかもしれません.

EspressoIdlingResource.java at master · googlecodelabs/android-testing

SimpleCountingIdlingResource.java at master · googlecodelabs/android-testing

2. テスト対象の Activity に記述

テスト対象となる Activity にテスト時に利用するメソッドを記述しておきます.
テスト時にはこのメソッドを利用して, 先ほどのユーティリティを利用登録します.


    @VisibleForTesting
    public IdlingResource getCountingIdlingResource() {
        return EspressoIdlingResource.getIdlingResource();
    }

AddNoteActivity.java at master · googlecodelabs/android-testing

NotesActivity.java at master · googlecodelabs/android-testing

3. 「待たせる」処理の記述

Presenter や View などのテスト対象クラス内にアイドリングの利用タイミングを記述しておきます.


EspressoIdlingResource.increment(); 


EspressoIdlingResource.decrement(); 

カウンターを増減しながらアイドリングを操作します.
カウンターが0になると処理が再開されます.


    @Override
    public void loadNotes(boolean forceUpdate) {
        mNotesView.setProgressIndicator(true);
        if (forceUpdate) {
            mNotesRepository.refreshData();
        }

        // The network request might be handled in a different thread so make sure Espresso knows
        // that the app is busy until the response is handled.
        EspressoIdlingResource.increment(); // App is busy until further notice

        mNotesRepository.getNotes(new NotesRepository.LoadNotesCallback() {
            @Override
            public void onNotesLoaded(List<Note> notes) {
                EspressoIdlingResource.decrement(); // Set app as idle.
                mNotesView.setProgressIndicator(false);
                mNotesView.showNotes(notes);
            }
        });
    }

AddNoteFragment.java at master · googlecodelabs/android-testing

NotesPresenter.java at master · googlecodelabs/android-testing

4. テスト内で登録する

テスト対象Activityに記述したメソッドを利用してテストコードへ登録します
アイドリング処理がテスト時に反映されます.


    @Before
    public void registerIdlingResource() {
        Espresso.registerIdlingResources(
                mAddNoteIntentsTestRule.getActivity().getCountingIdlingResource());
    }

    @After
    public void unregisterIdlingResource() {
        Espresso.unregisterIdlingResources(
                mAddNoteIntentsTestRule.getActivity().getCountingIdlingResource());
    }

AddNoteScreenTest.java at master · googlecodelabs/android-testing

まとめ

テストにかかるコストがただの自己満足で終わらないようにしたいです.

JakeWharton/okhttp-idling-resource: An Espresso IdlingResource for OkHttp.

PSA: Dont Use Espresso Idling Resources like Google does · Philosophical Hacker


LINE Notify をつかってターミナルから送信する

使ってみる.

line-notify

コマンドラインから LINE にメッセージを送れる LINE Notify « LINE Engineers' Blog

とりあえず.


#!/bin/sh -x                                                                                                                                   

token=zbOIf0lthC34fLGsXuilN2WBIkbomhtKj18M1MP0B1g

while true
do
  read message
  curl https://notify-api.line.me/api/notify \
  -H "Authorization: Bearer ${token}" \
  -F "message=${message} https://goo.gl/lU0Kx6" \
  -F "imageThumbnail=https://pbs.twimg.com/profile_images/745806811597406210/HO0KCGf2_400x400.jpg" \
  -F "imageFullsize=http://developers.linecorp.com/blog/wp-content/uploads/2016/10/moon.png"
  echo
done

これはグループ向けのメッセージ通知用になるのかな.


AGPBI 関連の多量のエラーを排除する

意味不明な Gradle の Warning や Error を消して激ビルド時間短縮

解決法がなく, 待っていたがビルド時間が長すぎて非効率すぎる.

Issue リストに新しい書き込み.

A temporary workaround I managed was to rollback to 2.1.3 of gradle in my project level build.gradle. No more errors and app builds fine. Going to keep it like this until a fix is pushed out. You will be prompted to upgrade to v2.2.0 when you open AS for the project, but you can ignore it.

classpath 'com.android.tools.build:gradle:2.1.3'

Issue 215748 - android - AGPBI reports errors instead of warnings - Android Open Source Project - Issue Tracker - Google Project Hosting

なので 2.2.0 から 2.1.3 に下げる.


  dependencies {
      //classpath 'com.android.tools.build:gradle:2.2.0'
      classpath 'com.android.tools.build:gradle:2.1.3'

com.android.tools.build.gradle

再度, clean build のあと, re-start や rebuild しても以下でできず.


Error:Cause: org.gradle.api.internal.tasks.DefaultTaskInputs$TaskInputUnionFileCollection cannot be cast to org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection
Possible causes for this unexpected error include:<ul><li>Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
<a href="syncProject">Re-download dependencies and sync project (requires network)</a></li><li>The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem.
<a href="stopGradleDaemons">Stop Gradle build processes (requires restart)</a></li><li>Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.</li></ul>In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

gradle-wrapper.properties で gradle のバージョンを下げる.


#distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

これでいけます. ビルド時間は, 5分の1程度に短縮された感じ.

意味がなかった proguard 記述は 無効化しておく.

proguard-rules_pro

まとめ

AGPBI 関連のエラーを消すには com.android.tools.build:gradle を 2.1.3 にダウングレードする(build.gradle root の書き換え).

com.android.tools.build:gradle:2.1.3 に対応している最新バージョンの gradle は 2.14.1(gradle-wrapper.properties の書き換え).

Gradle Distributions

2016-10-14 追記

修正された模様.

Yesterday (28 hours ago) #8 electros...@gmail.com
it seems to be fixed in Android Studio 2.2.1 with the gradle wrapper 2.2.1

Yesterday (25 hours ago) #9 pzol...@gmail.com
A.S. 2.2.1 fixed it for mee too

Issue 222989 - android - Android Studio 2.2 : Build successful with 1944 errors - Android Open Source Project - Issue Tracker - Google Project Hosting

実際, 試してみたが確かに修正されていた.


  dependencies {
      classpath 'com.android.tools.build:gradle:2.2.1'

gradle 3.1 でも問題はない感じ.