Comment utiliser Espresso Idling Resource pour les appels réseau
Im essayant d'utiliser Espresso pour tester mon UI. Quand je me connecter à ma demande, je fais un appel pour Analyser API (réseau téléphonique) pour vérifier le nom d'utilisateur et mot de passe. Si tout va bien, l'utilisateur obtient redirigé vers une nouvelle activité. Je veux le tester, mais je ne peux pas semble fonctionner au ralenti ressource chose.
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());
}
}
}
}
}
L'exception je reçois aujourd'hui est la suivante:
ndroid.support.test.espresso.IdlingResourceTimeoutException: Wait for [FooServerCalls] to become idle timed out
Quand je lance le test, le nom d'utilisateur et un mot de passe, se remplir, mais de l'exécuter sur n'est jamais appelé, et j'ai l'exception après quelques secondes. Comment dois-je mettre en œuvre le régime de ralenti de ressources correctement?
EDIT --
Je vous conseille d'utiliser de la Calebasse pour Android. Calebasse fonctionne de manière similaire, mais n'a pas besoin de vous pour changer votre code d'application pour les essais.
source d'informationauteur Dennis Anderson
Vous devez vous connecter pour publier un commentaire.
Comme les autres, de répondre à l'indique, le countingIdlingResource ne s'appliquent pas vraiment à votre cas d'utilisation.
Ce que je fais toujours, c'est d'ajouter une interface - appelons cela un
ProgressListener
- comme un champ de l'activité ou du fragment qui a une ressource qui doit être attendu (asynchrone travail de fond, plus de séances de réseautage, etc.) et une méthode pour informer à chaque fois que la progression est affichée ou rejeté.Je suis en supposant que vous avez vos informations d'identification de la validation de la logique et de l'appel à l'analyse de l'API dans le
LoginActivity
qui sera alors un appel à l'intention desMainActivity
en cas de succès.Ensuite, il suffit de mettre en œuvre les IdlingResource de classe et de redéfinir ses méthodes pour communiquer lorsque la ressource va de l'animation de la veille grâce à son ResourceCallBack
Dernière étape est d'enregistrer votre coutume de la marche au ralenti des ressources dans le test du
setUp()
méthode:Et c'est tout! Maintenant espresso vais attendre pour votre processus de connexion à remplir et ensuite continuer avec tous les autres tests.
S'il vous plaît laissez-moi savoir si je n'ai pas été assez clair ou si c'est exactement ce dont vous avez besoin.
Espresso sondage la marche au ralenti des ressources juste avant d'effectuer le clic (ou de toute action de la vue). Mais vous n'avez pas décrémenter compteur jusqu'à ce que après le clic. C'est une impasse.
Je ne vois pas de solution rapide ici; votre approche n'a pas vraiment de sens pour moi. Quelques autres approches viennent à l'esprit:
Une autre approche est d'avoir une coutume de la marche au Ralenti des ressources qui peuvent examiner votre activité. J'ai créé un ici:
https://gist.github.com/clivejefferies/2c8701ef70dd8b30cc3b62a3762acdb7
J'ai eu l'inspiration d'ici, qui montre comment elle pourrait être utilisée dans un test:
https://github.com/AzimoLabs/ConditionWatcher/blob/master/sample/src/androidTest/java/com/azimolabs/f1sherkk/conditionwatcherexample/IdlingResourceExampleTests.java
La bonne chose est que vous n'avez pas à ajouter un test de code de votre classe d'implémentation.