2016-05-18 7 views
1

エスプレッソは、AndroidのUIスレッドがアイドル状態になるのを常に待っているので、タイミングを気にする必要はありません問題。しかし、私は例外を見つけたようです: -/エスプレッソはViewPagerのスワイプアクションが完了するのを待つことはありません

設定はで、各フラグメントにEditTextです。

@MediumTest 
public void testSwipe() throws InterruptedException { 
    onView(withIdInActiveFragment(EXTERN_HOURS_INPUT)) 
      .perform(typeText("8.0")); 
    onView(withIdInActiveFragment(DAY_PAGER)) 
      .perform(swipeLeft()); 
    //Thread.sleep(2000); // <--- uncomment this and the test runs fine 
    onView(withIdInActiveFragment(EXTERN_HOURS_INPUT)) 
      .perform(typeText("8.0")); 
    onView(withIdInActiveFragment(DAY_PAGER)) 
      .perform(swipeLeft()); 
    //Thread.sleep(2000); 
    onView(withIdInActiveFragment(EXTERN_HOURS_INPUT)) 
      .perform(typeText("8.0")); 
    onView(withIdInActiveFragment(DAY_PAGER)) 
      .perform(swipeLeft()); 
} 

public static Matcher<View> withIdInActiveFragment(int id) { 
    return Matchers.allOf(withParent(isDisplayed()), withId(id)); 
} 

しかし、最初の実行中に、私はこのエラーを取得する:私はエスプレッソは、最初のフラグメントに EditTextにテキストを入力する第2のフラグメントにスワイプし、その断片(3回)で EditTextと同じことをやってみたいですスワイプ:

android.support.test.espresso.AmbiguousViewMatcherException: '(has parent matching: is displayed on the screen to the user and with id: de.cp.cp_app_android:id/extern_hours_input)' matches multiple views in the hierarchy. 
Problem views are marked with '****MATCHES****' below. 

View Hierarchy: 
... 

+-------->AppCompatEditText{id=2131558508, res-name=extern_hours_input, visibility=VISIBLE, width=110, height=91, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=true, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=true, editor-info=[inputType=0x2002 imeOptions=0x6 privateImeOptions=null actionLabel=null actionId=0 initialSelStart=3 initialSelEnd=3 initialCapsMode=0x0 hintText=null label=null packageName=null fieldId=0 fieldName=null extras=null ], x=165.0, y=172.0, text=8.0, input-type=8194, ime-target=true, has-links=false} ****MATCHES**** 

... 


+-------->AppCompatEditText{id=2131558508, res-name=extern_hours_input, visibility=VISIBLE, width=110, height=91, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=true, editor-info=[inputType=0x2002 imeOptions=0x6 privateImeOptions=null actionLabel=null actionId=0 initialSelStart=0 initialSelEnd=0 initialCapsMode=0x2000 hintText=null label=null packageName=null fieldId=0 fieldName=null extras=null ], x=165.0, y=172.0, text=, input-type=8194, ime-target=false, has-links=false} ****MATCHES**** 

エスプレッソが表示されているID EXTERN_HOURS_INPUTEditTextに書きたいです。スワイプアクションはまだ完了していないため、最初のフラグメントと第2フラグメントのEditTextsの両方が表示されます。なぜなら、一致するonView(withIdInActiveFragment(EXTERN_HOURS_INPUT))が2つの一致で失敗するからです。

スワイプアクションの後に手動で改行を追加してThread.sleep(2000);とすると、すべて問題ありません。

誰でもスワイプアクションが完了するまでエスプレッソを待つ方法を知っていますか?それとも、誰が少なくとも知っているのですか?スワイプアクションが実行されているときにUIスレッドがアイドル状態にならないため、できますか?ここで

activity_day_time_record.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:bind="http://schemas.android.com/apk/res-auto"> 

<data> 
    <variable 
     name="timerecord" 
     type="de.cp.cp_app_android.model.TimerecordDatabindingWrapper" /> 
</data> 

<ScrollView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:tools="http://schemas.android.com/tools" 
     style="@style/cp_relative_layout" 
     android:descendantFocusability="afterDescendants" 
     tools:context=".activities.DayRecordActivity"> 

     <include 
      android:id="@+id/toolbar" 
      layout="@layout/cp_toolbar"></include> 


     <!-- Arbeitsstunden --> 
     <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/section_title_workhours" 
      style="?android:attr/listSeparatorTextViewStyle" 
      android:layout_width="match_parent" 
      android:layout_height="25dip" 
      android:layout_below="@id/toolbar" 
      android:text="@string/dayrecord_section_workhours" /> 

     <TextView 
      android:id="@+id/extern_hours" 
      style="@style/dayrecord_label" 
      android:layout_below="@id/section_title_workhours" 
      android:text="@string/dayrecord_label_extern_hours" /> 

     <EditText 
      android:id="@+id/extern_hours_input" 
      style="@style/dayrecord_decimal_input" 
      android:layout_alignBaseline="@id/extern_hours" 
      android:layout_toEndOf="@id/extern_hours" 
      android:layout_toRightOf="@id/extern_hours" 
      bind:addTextChangedListener="@{timerecord.changed}" 
      bind:binding="@{timerecord.hoursExtern}" 
      bind:setOnFocusChangeListener="@{timerecord.hoursExternChanged}" /> 
     <!-- android:text='@{timerecord.hoursExtern != null ? String.format("%.1f", timerecord.hoursExtern) : ""}' --> 


    </RelativeLayout> 
</ScrollView> 

そしてactivity_swipe_day.xml次のとおりです。

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/day_pager" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 

+0

私はViewPagerが唯一つのフラグメント 'active'を作るかわかりません。それは隣接するフラグメントも保持します。 –

+0

これは隣接するフラグメント(私の場合は前と後のフラグメント)を保持しますが、それらは見えません。したがって、エスプレッソがスワイプアクションが完了するのを待っている場合は、「EditText」が1つだけ表示され、マッチングが成功するでしょう。 – Ruik

+0

私は 'withIdInActiveFragment'と思っています。これはあなたのカスタム 'Matcher'実装ですか?すべてのマッチャーが視認性だけでフィルタリングするわけではありません。 –

答えて

3

私はエスプレッソは、この機能で構築されたものを持っているとは思わない、彼らは012を使って欲しい。 私が思いついたベストは、まだスリープを使用していますが、100ミリ秒ごとにポーリングするため、ビューが表示されてから最悪の場合は100ミリ秒が戻ってきます。

private final int TIMEOUT_MILLISECONDS = 5000; 
private final int SLEEP_MILLISECONDS = 100; 
private int time = 0; 
private boolean wasDisplayed = false; 

public Boolean isVisible(ViewInteraction interaction) throws InterruptedException { 
    interaction.withFailureHandler((error, viewMatcher) -> wasDisplayed = false); 
    if (wasDisplayed) { 
     return true; 
    } 
    if (time >= TIMEOUT_MILLISECONDS) { 
     return false; 
    } 

    //set it to true if failing handle should set it to false again. 
    wasDisplayed = true; 
    Thread.sleep(SLEEP_MILLISECONDS); 
    time += SLEEP_MILLISECONDS; 

    interaction.check(matches(isDisplayed())); 
    Log.i("ViewChecker","sleeping"); 
    return isVisible(interaction); 
} 

あなたは、このようにそれを呼び出すことができます。

ViewInteraction interaction = onView(
     allOf(withId(R.id.someId), withText(someText), isDisplayed())); 
boolean objectIsVisible = isVisible(interaction); 
assertThat(objectIsVisible, is(true)); 
関連する問題