2015-05-29 5 views
7

Ich habe einen einfachen Test heute:Gibt es eine Möglichkeit, den Espresso-Test mit mehreren Testmethoden, aber nur einer Setup-Methode auszuführen?

@RunWith(AndroidJUnit4.class) 
@LargeTest 
public class WhenNavigatingToUsersView { 

    @Rule 
    public ActivityTestRule<MainActivity> mActivityRule = 
     new ActivityTestRule(MainActivity.class); 
    private MainActivity mainActivity; 

    @Before 
    public void setActivity() { 
     mainActivity = mActivityRule.getActivity(); 
     onView(allOf(withId(R.id.icon), hasSibling(withText(R.string.users)))).perform(click()); 
    } 

    @Test 
    public void thenCorrectViewTitleShouldBeShown() { 
     onView(withText("This is the Users Activity.")).check(matches(isDisplayed())); 
    } 

    @Test 
    public void thenCorrectUserShouldBeShown() { 
     onView(withText("Donald Duck (1331)")).check(matches(isDisplayed())); 
    } 
} 

Aber für jede Testmethode der setActivity ausgeführt wird, die, wenn Sie 10-15 Methoden haben, in der Endzeit sein wird raubend (wenn Sie haben eine Menge von Ansichten auch).

@BeforeClass scheint nicht zu funktionieren, da es statisch sein muss und damit die ActivityTestRule auch statisch sein muss.

Gibt es einen anderen Weg, dies zu tun? Anstatt mehrere Behauptungen in der gleichen Testmethode zu haben?

Antwort

3

@Before Annotation sollte nur Methoden vorausgehen, die vorläufige Einstellungen enthalten. Initialisierung der benötigten Objekte, Erhalt der aktuellen Sitzung oder der aktuellen Aktivität, Sie erhalten die Idee.

Es ersetzt die alte setUp()-Methode von der ActivityInstrumentationTestCase2, genauso wie @After die tearDown() ersetzt. Das bedeutet, dass es vor jedem Test in der Klasse ausgeführt werden soll und es sollte so bleiben.

Sie sollten keine ViewInteraction haben, keine DataInteraction, keine Assertions noch View Aktionen in diesem Verfahren, da das nicht ihr Zweck ist.

In Ihrem Fall, entfernen Sie einfach den onView() Anruf von setActivity() und es in den eigentlichen Testmethoden setzen, in jedem Testverfahren erforderlich, wenn, wie so:

@RunWith(AndroidJUnit4.class) 
@LargeTest 
public class WhenNavigatingToUsersView { 

    @Rule 
    public ActivityTestRule<MainActivity> mActivityRule = 
     new ActivityTestRule(MainActivity.class); 
    private MainActivity mainActivity; 

    @Before 
    public void setActivity() { 
     mainActivity = mActivityRule.getActivity(); 
     // other required initializations/definitions 
    } 

    @Test 
    public void thenCorrectViewTitleShouldBeShown() { 
     onView(allOf(withId(R.id.icon), hasSibling(withText(R.string.users)))).perform(click()); 
     onView(withText("This is the Users Activity.")).check(matches(isDisplayed())); 
    } 

    @Test 
    public void thenCorrectUserShouldBeShown() { 
     onView(allOf(withId(R.id.icon), hasSibling(withText(R.string.users)))).perform(click()); 
     onView(withText("Donald Duck (1331)")).check(matches(isDisplayed())); 
    } 
} 
+0

Sie verpassen meinen Punkt irgendwie ... Gibt es eine Möglichkeit, die Interaktion nicht für jede Testmethode definieren zu müssen? Ein guter Komponententest für mich ist, dass eine Testmethode nur eine Assert pro Test haben sollte und der Aufbau in einer anderen Methode erfolgen sollte. Stellen Sie sich vor, diese Ansicht würde voller Felder sein, die ich überprüfen möchte, wenn sie existieren. Es wäre sehr teuer, mit der Ansicht für jeden Test zu interagieren. Wenn ich diese Ansicht nur einmal "öffnen" und mehrere Tests durchführen möchte. – peuhse

+0

Warum sollte ich keine Ansichtsinteraktion und andere Sachen in setActivity haben? Ein besserer Name wäre setupContext oder etwas und fügt dem Test dort alle Voraussetzungen hinzu. Das ist die Absicht des @Before-Schlüsselworts in Junit ... – peuhse

0

Eine weitere Option für Sie diese Tests wird Trennung würde .

Wenn Sie auf das Benutzersymbol klicken, befindet es sich in der HomeActivity-Testklasse, während der Rest der Tests in der UserActivity-Testklasse stattfindet.

Die UserActivity-Testklasse startet UserActivity mit der richtigen Absicht (Sie können dazu den falschen Boolean in den Regelkonstruktor übergeben und manuell launchActivity(intent) aufrufen).

Dadurch entfällt die Notwendigkeit, die Aktivität jedes Mal neu einzurichten. Es wird auch die ständige Abhängigkeit von der Hauptaktivität los. Wenn etwas schief geht, sind Ihre UserActivity-Tests intakt und erzeugen die Ergebnisse, während das Problem durch den Test in der MainActivity abgefangen wird.

Tatsächlich werden Ihre Tests dadurch zu MediumSize, da die Laufzeit drastisch abnimmt.

+0

könnte ich wohl zu sowas machen. Aber UsersActivity ist keine Aktivität, es ist ein Fragment. Ich habe bisher nur eine Aktivität; Hauptaktivität. Und alle Navigation geht zu verschiedenen Fragmenten. – peuhse

0

Sie können dies versuchen:

**** Setting **** 
public void testStory() throws Exception { 

} 

public void testStory2() throws Exception { 

} 

public void testStory3() throws Exception { 

} 

Versuchen Sie, Ihren Test durch diesen Befehl auszuführen:

./gradlew cC 
0

Haben Sie versuchen es zu tun wie folgt oder eine geringfügige Änderung der es an Ihre Bedürfnisse anpassen:

@Rule 
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule(MainActivity.class); 
private MainActivity mainActivity = mActivityRule.getActivity(); 

@BeforeClass 
public static void setActivity() { 
    onView(allOf(withId(R.id.icon), hasSibling(withText(R.string.users)))).perform(click()); 
} 

Auf diese Weise müssen Sie "mainActivity" nicht statisch sein.Außerdem wird die setActivity()-Methode nur einmal aufgerufen.