Wie zu verwenden Espresso Leerlauf Ressource für Netzwerk-Aufrufe
Ich versuche zu verwenden, Espresso zum testen meiner UI. Wenn ich das login in meine Anwendung, ich mache einen Aufruf von Parse-API (network call) zu überprüfen, ob der Benutzername und das Passwort. Wenn alles gut geht bekommt der Nutzer weitergeleitet auf eine neue Tätigkeit. Ich möchte, um dies zu testen, aber ich kann nicht scheinen zu arbeiten mit der idle-Ressource-Sache.
Code:
public class ApplicationTest extends ActivityInstrumentationTestCase2<LoginActivity> {
private CountingIdlingResource fooServerIdlingResource;
public ApplicationTest() {
super(LoginActivity.class);
}
@Before
public void setUp() throws Exception {
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
getActivity();
CountingIdlingResource countingResource = new CountingIdlingResource("FooServerCalls");
this.fooServerIdlingResource = countingResource;
Espresso.registerIdlingResources(countingResource);
}
public void testChangeText_sameActivity() {
//Type text and then press the button.
onView(withId(R.id.username))
.perform(typeText("[email protected]"), closeSoftKeyboard());
onView(withId(R.id.password))
.perform(typeText("s"), closeSoftKeyboard());
if(performClick())
onView(withId(R.id.main_relative_layout))
.check(matches(isDisplayed()));
//Check that the text was changed.
}
public boolean performClick(){
fooServerIdlingResource.increment();
try {
onView(withId(R.id.login)).perform(click());
return true;
} finally {
fooServerIdlingResource.decrement();
}
}
@SuppressWarnings("javadoc")
public final class CountingIdlingResource implements IdlingResource {
private static final String TAG = "CountingIdlingResource";
private final String resourceName;
private final AtomicInteger counter = new AtomicInteger(0);
private final boolean debugCounting;
//written from main thread, read from any thread.
private volatile ResourceCallback resourceCallback;
//read/written from any thread - used for debugging messages.
private volatile long becameBusyAt = 0;
private volatile long becameIdleAt = 0;
/**
* Creates a CountingIdlingResource without debug tracing.
*
* @param resourceName the resource name this resource should report to Espresso.
*/
public CountingIdlingResource(String resourceName) {
this(resourceName, false);
}
/**
* Creates a CountingIdlingResource.
*
* @param resourceName the resource name this resource should report to Espresso.
* @param debugCounting if true increment & decrement calls will print trace information to logs.
*/
public CountingIdlingResource(String resourceName, boolean debugCounting) {
this.resourceName = checkNotNull(resourceName);
this.debugCounting = debugCounting;
}
@Override
public String getName() {
return resourceName;
}
@Override
public boolean isIdleNow() {
return counter.get() == 0;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
/**
* Increments the count of in-flight transactions to the resource being monitored.
* <p/>
* This method can be called from any thread.
*/
public void increment() {
int counterVal = counter.getAndIncrement();
if (0 == counterVal) {
becameBusyAt = SystemClock.uptimeMillis();
}
if (debugCounting) {
Log.i(TAG, "Resource: " + resourceName + " in-use-count incremented to: " + (counterVal + 1));
}
}
/**
* Decrements the count of in-flight transactions to the resource being monitored.
* <p/>
* If this operation results in the counter falling below 0 - an exception is raised.
*
* @throws IllegalStateException if the counter is below 0.
*/
public void decrement() {
int counterVal = counter.decrementAndGet();
if (counterVal == 0) {
//we've gone from non-zero to zero. That means we're idle now! Tell espresso.
if (null != resourceCallback) {
resourceCallback.onTransitionToIdle();
}
becameIdleAt = SystemClock.uptimeMillis();
}
if (debugCounting) {
if (counterVal == 0) {
Log.i(TAG, "Resource: " + resourceName + " went idle! (Time spent not idle: " +
(becameIdleAt - becameBusyAt) + ")");
} else {
Log.i(TAG, "Resource: " + resourceName + " in-use-count decremented to: " + counterVal);
}
}
checkState(counterVal > -1, "Counter has been corrupted!");
}
/**
* Prints the current state of this resource to the logcat at info level.
*/
public void dumpStateToLogs() {
StringBuilder message = new StringBuilder("Resource: ")
.append(resourceName)
.append(" inflight transaction count: ")
.append(counter.get());
if (0 == becameBusyAt) {
Log.i(TAG, message.append(" and has never been busy!").toString());
} else {
message.append(" and was last busy at: ")
.append(becameBusyAt);
if (0 == becameIdleAt) {
Log.w(TAG, message.append(" AND NEVER WENT IDLE!").toString());
} else {
message.append(" and last went idle at: ")
.append(becameIdleAt);
Log.i(TAG, message.toString());
}
}
}
}
}
Ausnahme, die ich jetzt bekommen, ist die folgende:
ndroid.support.test.espresso.IdlingResourceTimeoutException: Wait for [FooServerCalls] to become idle timed out
Wenn ich den test ausführen, der Benutzername und das Passwort sind immer gefüllt, aber das ausführen klicken, wird nie aufgerufen und ich erhalte die exception nach ein paar Sekunden. Wie soll ich das implementieren, die im Leerlauf Ressource richtig?
BEARBEITEN --
Ich würde empfehlen, mit Kalebasse für Android. Kalebasse arbeitet ähnlich, muss aber nicht, Sie zu ändern Sie Ihre app-code für die Prüfung.
InformationsquelleAutor Dennis Anderson | 2015-06-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wie die andere Antwort schon andeutet, ist der countingIdlingResource nicht wirklich für Ihren Fall.
Was ich immer mache, ist eine Schnittstelle hinzufügen, nennen wir dies eine
ProgressListener
- als Feld der Tätigkeit /fragment, eine Ressource zu warten (asynchron im hintergrund arbeiten, mehr networking sessions, etc.) und eine Methode, teilt Sie dies jedesmal, wenn der Fortschritt angezeigt wird, oder entlassen.Ich nehme an, Sie haben Ihre Anmeldeinformationen überprüfung der Logik und der Aufruf der Parse-API in der
LoginActivity
, die dann eine Absicht, dieMainActivity
wenn erfolgreich.Dann, einfach zu implementieren die IdlingResource - Klasse und überschreiben Sie die Methoden, um zu kommunizieren, wenn die Ressource von beschäftigt auf idle durch seine ResourceCallBack
Letzten Schritt ist die Registrierung Ihrer benutzerdefinierten Leerlauf Ressource im test
setUp()
Methode:Und das ist es! Jetzt espresso wartet auf Ihre login-Vorgang abgeschlossen ist und dann weiter mit all den anderen tests.
Bitte lassen Sie mich wissen, wenn ich mich nicht klar genug ist oder wenn das ist genau das, was man benötigt.
Viel Glück, kann Es scheinen, wie ein bisschen mehr Arbeit, aber die Anmeldung war sehr hilfreich für mich
Ich versuchte es und es funktionierte !! ich war Weg mit meinem code ! nicht aspected zu implementieren code in meine "app" - code. Seine ein Nachteil zu ändern, meine app-code, um meine tests arbeiten. Ich bekam eine Menge von Parse-API-Aufrufe. Ich glaube, mein code ist ein Durcheinander mit all diesen ! Aber das war nicht die Frage, die Sie beantwortet haben meine eigentliche Frage. Also vielen Dank dafür !
Ich bin froh, dass es geholfen hat 🙂 Vielleicht ist es nicht die einzige Weise, aber hey, nicht jeder schreibt ui-tests UND sichert die Vernetzung zur gleichen Zeit. Daher gehe ich davon aus, es ist es Wert. Alle die besten!!!
Sie können tun, etwas ähnliches suchen, die für den Fortschritt anzeigen/fragment Sichtbarkeit anstelle der Zugabe der
isInProgress()
ausschließlich für die Nutzung der test-code.InformationsquelleAutor appoll
Espresso abfragt, die im Leerlauf Ressource nur, bevor Sie die Taste (oder einer beliebigen Ansicht Aktion). Aber Sie wissen nicht, verringern Sie Ihren counter bis nach das klicken Sie auf. Es ist ein deadlock.
Sehe ich keine schnelle Lösung hier; Ihr Ansatz nicht wirklich Sinn für mich. Ein paar mögliche Alternative Herangehensweisen in den Sinn kommen:
InformationsquelleAutor Daniel Lubarov
Ein weiterer Ansatz ist, um eine benutzerdefinierte Leerlauf Ressource, überprüfen Sie Ihre Aktivität. Ich habe eine erstellt hier:
https://gist.github.com/clivejefferies/2c8701ef70dd8b30cc3b62a3762acdb7
Ich bekam die inspiration von hier, die zeigt, wie es verwendet werden könnte, im test:
https://github.com/AzimoLabs/ConditionWatcher/blob/master/sample/src/androidTest/java/com/azimolabs/f1sherkk/conditionwatcherexample/IdlingResourceExampleTests.java
Die gute Sache ist, dass Sie nicht hinzufügen jede test-code zu Ihrer Umsetzung Klasse.
InformationsquelleAutor Clive Jefferies