So verwenden Sie Espresso Idling Resource für Netzwerkaufrufe

Ich versuche, Espresso zu benutzen, um meine Benutzeroberfläche zu testen. Wenn ich mich in meine Anwendung einlogge, mache ich einen Anruf zu Parse API (Netzwerkaufruf), um den Benutzernamen und das Passwort zu überprüfen. Wenn alles gut ist, wird der Benutzer an eine neue Aktivität gerichtet. Ich möchte das testen, aber ich kann nicht mit der Leerlaufressourcen-Sache arbeiten.

Code:

  • Was ist die Standard-Schriftfamilie in Android?
  • Bessere Möglichkeit, einen Android x86 HAXM beschleunigten Emulator auf Windows 8 mit Hyperv zu verwenden
  • Ernte ein Bild, wenn aus der Galerie in Android ausgewählt
  • MediaRecorder Ausgabe auf Android Lollipop
  • Google map v2 oder v3?
  • So speichern Sie Dateien im externen Speicher Public Directory DOKUMENTE auf Android 4.1.2
  • 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("s@s.nl"), 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()); } } } } 

    }

    Die Ausnahme, die ich jetzt bekomme, ist die folgende:

     ndroid.support.test.espresso.IdlingResourceTimeoutException: Wait for [FooServerCalls] to become idle timed out 

    Wenn ich den Test ausführen, werden der Benutzername und das Passwort eingefüllt, aber der Durchlauf Klick wird nie aufgerufen und ich bekomme die Ausnahme nach ein paar Sekunden. Wie soll ich die Leerlaufressource korrekt implementieren?

    EDIT –

    Ich würde empfehlen, Calabash für Android zu verwenden. Calabash funktioniert ähnlich, aber Sie brauchen nicht, um Ihren App-Code zum Testen zu ändern.

  • Was ist die beste Sprache für Echtzeit-Grafik-Programmierung auf Android?
  • Android Studio kann kein neues Android-Projekt erstellen
  • Fehler beim Aufblasen der Klasse RecyclerView
  • App nicht kompatibel mit Nexus7 mit Marshmallow
  • Wo ist der Speicherort der von Cordova File Plugin erstellten Datei?
  • Verwenden eines Nicht-Android-Namespace-Präfix in untergeordneten Elementen in einem Layout
  • 3 Solutions collect form web for “So verwenden Sie Espresso Idling Resource für Netzwerkaufrufe”

    Wie die andere Antwort darauf hindeutet, gilt die countingIdlingResource nicht wirklich für Ihren Anwendungsfall.

    Was ich immer mache, füge eine Schnittstelle hinzu – nennen wir diese ProgressListener – als ein Feld der Aktivität / Fragment, auf das eine Ressource gewartet werden muss (asynchrone Hintergrundarbeit, längere Networking-Sessions etc.) und eine Methode, um sie jedes Mal zu benachrichtigen Der Fortschritt wird angezeigt oder entlassen.

    Ich gehe davon aus, dass Sie Ihre Anmeldeinformationen-Validierungslogik und den Aufruf der Parse-API in der LoginActivity , die dann eine Absicht zur MainActivity wenn sie erfolgreich ist.

     public class LoginActivity extends AppCompatActivity { private ProgressListener mListener; ... public interface ProgressListener { public void onProgressShown(); public void onProgressDismissed(); } public void setProgressListener(ProgressListener progressListener) { mListener = progressListener; } ... public void onLoginButtonClicked (View view) { String username = mUsername.getText().toString(); String password = mPassword.getText().toString(); // validate credentials for blanks and so on // show progress and call parse login in background method showProgress(); ParseUser.logInInBackground(username,password, new LogInCallback() { @Override public void done(ParseUser parseUser, ParseException e) { dismissProgress(); if (e == null){ // Success!, continue to MainActivity via intent Intent intent = new Intent (LoginActivity.this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); } else { // login failed dialog or similar. } } }); } private void showProgress() { // show the progress and notify the listener ... notifyListener(mListener); } private void dismissProgress() { // hide the progress and notify the listener ... notifyListener(mListener); } public boolean isInProgress() { // return true if progress is visible } private void notifyListener(ProgressListener listener) { if (listener == null){ return; } if (isInProgress()){ listener.onProgressShown(); } else { listener.onProgressDismissed(); } } } 

    Dann implementiere einfach die IdlingResource- Klasse und überschreibe ihre Methoden, um zu kommunizieren, wenn die Ressource von besetzt geht, um durch ihre ResourceCallBack zu leeren

     public class ProgressIdlingResource implements IdlingResource { private ResourceCallback resourceCallback; private LoginActivity loginActivity; private LoginActivity.ProgressListener progressListener; public ProgressIdlingResource(LoginActivity activity){ loginActivity = activity; progressListener = new LoginActivity.ProgressListener() { @Override public void onProgressShown() { } @Override public void onProgressDismissed() { if (resourceCallback == null){ return ; } //Called when the resource goes from busy to idle. resourceCallback.onTransitionToIdle(); } }; loginActivity.setProgressListener (progressListener); } @Override public String getName() { return "My idling resource"; } @Override public boolean isIdleNow() { // the resource becomes idle when the progress has been dismissed return !loginActivity.isInProgress(); } @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { this.resourceCallback = resourceCallback; } } 

    Der letzte Schritt besteht darin, Ihre benutzerdefinierte Leerlaufressource in der setUp() Methode des Tests zu setUp() :

     Espresso.registerIdlingResources(new ProgressIdlingResource((LoginActivity) getActivity())); 

    Und das ist es! Jetzt wird espresso auf Ihren Login-Prozess warten und dann mit allen anderen Tests fortfahren.

    Bitte lassen Sie mich wissen, ob ich nicht klar genug war oder ob das genau das ist, was Sie brauchten.

    Espresso wird die Leerlaufressource kurz vor dem Durchführen des Klicks (oder einer beliebigen Ansichtsaktion) abfragen. Aber du verkürgst deinen Zähler erst nach dem Klick. Es ist ein Deadlock.

    Ich sehe hier keine schnelle Lösung. Ihr Ansatz macht mir nicht wirklich Sinn. Ein paar mögliche alternative Ansätze kommen in den Sinn:

    • Je nachdem, welche Bibliothek Sie für die Vernetzung verwenden, können Sie in der Lage sein, eine Leerlaufressource zu schreiben, die prüft, ob ein Anruf läuft.
    • Wenn Sie während des Anmeldeaufrufs eine Fortschrittsanzeige anzeigen, können Sie eine IdlingResource installieren, die darauf wartet, dass sie verschwindet.
    • Sie könnten warten, bis die nächste Aktivität gestartet wird, oder für eine bestimmte Ansicht zu erscheinen / verschwinden.

    Ein anderer Ansatz ist, eine benutzerdefinierte Leerlaufressource zu haben, die Ihre Aktivität untersuchen kann. Ich habe hier einen geschaffen:

     public class RequestIdlingResource implements IdlingResource { private ResourceCallback resourceCallback; private boolean isIdle; @Override public String getName() { return RequestIdlingResource.class.getName(); } @Override public boolean isIdleNow() { if (isIdle) return true; Activity activity = getCurrentActivity(); if (activity == null) return false; idlingCheck(activity); if (isIdle) { resourceCallback.onTransitionToIdle(); } return isIdle; } private Activity getCurrentActivity() { final Activity[] activity = new Activity[1]; java.util.Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED); activity[0] = Iterables.getOnlyElement(activities); return activity[0]; } @Override public void registerIdleTransitionCallback( ResourceCallback resourceCallback) { this.resourceCallback = resourceCallback; } public void idlingCheck(Activity activity) { /* Look up something (view or method call) on the activity to determine if it is idle or busy */ } } 

    https://gist.github.com/clivejefferies/2c8701ef70dd8b30cc3b62a3762acdb7

    Ich habe die Inspiration von hier, die zeigt, wie es in einem Test verwendet werden könnte:

    https://github.com/AzimoLabs/ConditionWatcher/blob/master/sample/src/androidTest/java/com/azimolabs/f1sherkk/conditionwatcherexample/IdlingResourceExampleTests.java

    Die gute Sache ist, dass Sie keinen Testcode zu Ihrer Implementierungsklasse hinzufügen müssen.

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.