46

ビューが Espresso で表示されるかどうかを確認しようとしています。私が何をしようとしているのかを示す擬似コードを次に示します。

if (!Espresso.onView(withId(R.id.someID)).check(doesNotExist()){
   // then do something
 } else {
   // do nothing, or what have you
 }

しかし、私の問題は.check(doesNotExist())ブール値を返さないことです。それは単なる主張です。UiAutomator を使用すると、次のようなことができました。

 if (UiAutomator.getbyId(SomeId).exists()){
      .....
   }
4

8 に答える 8

102

テストでの条件付きロジックは望ましくありません。そのことを念頭に置いて、Espresso の API は、(テスト アクションとアサーションを明示することによって) テスト作成者をそれから遠ざけるように設計されました。

そうは言っても、独自の ViewAction を実装し、isDisplayed チェック (Perform メソッド内) を AtomicBoolean にキャプチャすることで、上記を実現できます。

もう 1 つの洗練されていないオプション - 失敗したチェックによってスローされる例外をキャッチします。

    try {
        onView(withText("my button")).check(matches(isDisplayed()));
        //view is displayed logic
    } catch (NoMatchingViewException e) {
        //view not displayed logic
    }

拡張機能を備えた Kotlin バージョン:

    fun ViewInteraction.isDisplayed(): Boolean {
        try {
            check(matches(ViewMatchers.isDisplayed()))
            return true
        } catch (e: NoMatchingViewException) {
            return false
        }
    }

    if(onView(withText("my button")).isDisplayed()) {
        //view is displayed logic
    } else {
        //view not displayed logic
    }
于 2013-12-28T05:02:01.140 に答える
11

UIAutomator を模倣するには、これを行うことができると思います:(
ただし、条件を持たないようにアプローチを再考することをお勧めします。 )

ViewInteraction view = onView(withBlah(...)); // supports .inRoot(...) as well
if (exists(view)) {
     view.perform(...);
}

@CheckResult
public static boolean exists(ViewInteraction interaction) {
    try {
        interaction.perform(new ViewAction() {
            @Override public Matcher<View> getConstraints() {
                return any(View.class);
            }
            @Override public String getDescription() {
                return "check for existence";
            }
            @Override public void perform(UiController uiController, View view) {
                // no op, if this is run, then the execution will continue after .perform(...)
            }
        });
        return true;
    } catch (AmbiguousViewMatcherException ex) {
        // if there's any interaction later with the same matcher, that'll fail anyway
        return true; // we found more than one
    } catch (NoMatchingViewException ex) {
        return false;
    } catch (NoMatchingRootException ex) {
        // optional depending on what you think "exists" means
        return false;
    }
}

またexists、分岐なしで非常に簡単に実装できます。

onView(withBlah()).check(exists()); // the opposite of doesNotExist()

public static ViewAssertion exists() {
    return matches(anything());
}

ただし、ほとんどの場合、matches(isDisplayed())とにかくチェックする価値があります。

于 2016-09-11T12:44:57.137 に答える
9

以下のコードでも確認します。ビューが表示されている場合は、それ以外の場合はクリックします。

onView(withText("OK")).withFailureHandler(new FailureHandler() {
        @Override
        public void handle(Throwable error, Matcher<View> viewMatcher){
        }
    }).check(matches(isDisplayed())).perform(customClick());
于 2016-09-01T16:30:28.983 に答える
9

その機能が必要なので、以下に実装しました。

https://github.com/marcosdiez/espresso_clone

if(onView(withText("click OK to Continue")).exists()){ 
    doSomething(); 
} else { 
   doSomethingElse(); 
}

お役に立てば幸いです。

于 2014-03-12T17:09:00.173 に答える
2

この問題が発表されてからしばらく経ちましたが、ビューが存在することを確認する方法を検索するときに Google で最もヒットしたものの 1 つであるため、Espresso でビューに対してアクションを実行する前に、私の非常に基本的なことを共有したいと思います。これの扱い方。

1: 拡張機能を次のように記述することから始めViewInteractionます。

fun ViewInteraction.exists(): Boolean {
val viewExists = AtomicReference<Boolean>()

this.perform(object : ViewAction {
    override fun perform(uiController: UiController?, view: View?) {
        viewExists.set(view != null)
    }

    override fun getConstraints(): Matcher<View>? {
        return Matchers.allOf(ViewMatchers.withEffectiveVisibility(
                ViewMatchers.Visibility.VISIBLE),
                ViewMatchers.isAssignableFrom(View::class.java))
    }

    override fun getDescription(): String {
        return "check if view exists"
    }
})
return viewExists.get()
}

2: 基本クラスに簡単なヘルプ メソッドを作成します (すべてのテスト クラスで使用します)。

fun viewExists(id: Int): Boolean {
    return try {
        onView(withId(id)).exists()
    } catch (e: RuntimeException) {
        false
    }
}

これにより、 gettrueまたはfalsefromonView(withId(id)).exists()を取得するか、RuntimeException を安全にキャッチして return を返しfalseます。

通常は単純なチェック.exists()で十分ですが、場合によっては、ListView アイテムがなくなるまで削除する場合など、最後のアイテムが削除されると、ListView が存在しなくなり、しようとすると例外がスローされます。存在するかどうかを確認します。

RuntimeException3: 上記の実装では、バックグラウンドで適切に処理されるため、ビューが存在するかどうかを確認しても安全です。

if(viewExists(R.id.something)) {
    //do something
}
//do something else
于 2019-01-30T11:11:54.190 に答える