web-dev-qa-db-fra.com

android espresso connectez-vous une fois avant d'exécuter les tests

J'ai essayé de couvrir mon Android avec des tests et j'ai commencé à utiliser espresso récemment . J'ai été assez impressionné jusqu'à présent. Cependant, la plupart des fonctionnalités de mon application nécessitent que les utilisateurs sont connectés. Et comme tous les tests sont indépendants, cela nécessite d'enregistrer un nouvel utilisateur pour chaque test. Cela fonctionne bien, mais le temps requis pour chaque test augmente considérablement à cause de cela.

J'essaie de trouver un moyen d'enregistrer un utilisateur une fois dans une classe (de tests), puis d'utiliser ce même compte d'utilisateur pour effectuer tous les tests de cette classe.

Une façon dont j'ai pu le faire est de n'avoir en fait qu'un seul test (@Test) méthode qui exécute tous les autres tests dans l'ordre que je souhaite. Cependant, c'est une approche tout ou rien, puisque le gradle cAT la tâche ne produit les résultats qu'une seule fois à la fin sans fournir d'informations sur les tests intermédiaires qui peuvent avoir réussi/échoué.

J'ai aussi essayé le @BeforeClass approche qui n'a cependant pas fonctionné (pas de sortie gradle de la classe où je l'avais utilisé même avec l'option de débogage et il semblait que cela prenait beaucoup de temps avant de passer à la classe de tests suivante).

Existe-t-il une meilleure approche pour enregistrer un utilisateur une fois au début d'une classe, puis se déconnecter une fois à la fin des tests?

Toute aide appréciée.

30
source.rar

Idéalement, vous testez la fonctionnalité de connexion/déconnexion dans un ensemble de tests qui testent simplement différents scénarios de connexion/déconnexion et laissez les autres tests se concentrer sur d'autres cas d'utilisation. Cependant, comme les autres scénarios dépendent de la connexion de l'utilisateur, il semble qu'une façon de résoudre ce problème serait de fournir une version fictive du composant d'application gérant la connexion. Pour les autres tests dépendants de la connexion, vous injecteriez cette maquette au début et elle renverrait des informations d'identification utilisateur avec lesquelles le reste de l'application peut fonctionner.

Voici un exemple où Dagger, Mockito et Espresso sont utilisés pour accomplir cela: https://engineering.circle.com/instrumentation-testing-with-dagger-mockito-and-espresso/

11
fejd

Je teste une application qui nécessite ce même scénario. Le moyen le plus simple que j'ai trouvé est de diviser la connexion et la déconnexion en leurs propres classes de test. Ensuite, vous ajoutez toutes vos classes de test à une suite, en commençant et en terminant par les suites de connexion et de déconnexion respectivement. Vos suites de tests finissent par ressembler à ceci.

@RunWith(Suite.class)
@Suite.SuiteClasses({
        LoginSetup.class,
        SmokeTests.class,
        LogoutTearDown.class
})

EDIT: Voici un exemple des tests LoginSetup et LogoutTearDown. Cette solution ne devrait vraiment être que pour des tests de bout en bout et représenter une petite partie de vos efforts de test. fejd fournit une solution pour une pile de tests complète qui doit également être prise en compte.

@LargeTest
public class SmokeSetup extends LogInTestFixture {

    @Rule
    public ActivityTestRule<LoginActivity> mLoginActivity = new ActivityTestRule<>(LoginActivity.class);

    @Test
    public void testSetup() throws IOException {

        onView(withId(R.id.username_field)).perform(replaceText("username"));
        onView(withId(R.id.password_field)).perform(replaceText("password"));
        onView(withId(R.id.login_button)).perform(click());

    }

}

@LargeTest
public class LogoutTearDown extends LogInTestFixture {

    @Rule
    public ActivityTestRule<MainActivity> mMainActivity = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void testLogout() throws IOException {

        onView(withId(R.id.toolbar_menu)).perform(click());
        onView(withId(R.id.logout_button)).perform(click());

    }

}
6
James Pullar

L'approche de la connexion avec @Before est agréable mais si votre connexion est lente, votre temps de test combiné sera très lent.

Voici un excellent hack qui fonctionne. La stratégie est simple: exécutez chaque test dans l'ordre et échouez à chaque test avant qu'ils ne puissent s'exécuter si un certain test échoue (dans ce cas, le test de connexion).

@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@LargeTest
public class YourTestsThatDependsOnLogin {

    private static failEverything;

    @Before
    public void beforeTest() {

        // Fail every test before it has a chance to run if login failed
        if (failEverything) {
            Assert.fail("Login failed so every test should fail");
        }

    }    

    @Test
    public void test0_REQUIREDTEST_login() {

        failEverything = true;
        // Your code for login
        // Your login method must fail the test if it fails.
        login();
        failEverything = false; // We are safe to continue.

    }

    // test1 test2 test3 etc...

}

Avantages:

  • Ce que vous avez demandé fonctionne et c'est rapide (si votre connexion est lente)
  • Vous pouvez avoir plusieurs tests qui dépendent de différentes connexions, ce qui signifie que vous pouvez faire un tas de tests pour l'utilisateur 1, puis un tas de tests pour l'utilisateur 2, etc.
  • Rapide à installer.

Inconvénients:

  • Procédure pas standard et quelqu'un pourrait se demander pourquoi tant de tests échouent ...
  • Vous devriez vous moquer des utilisateurs au lieu de vous connecter. Vous devriez tester votre Connectez-vous séparément et les tests ne devraient pas dépendre les uns des autres.
3
Erik Sillén

Ajoutez la fonction suivante dans votre fichier de test, remplacez le code du bloc try par le vôtre qui effectue les actions de connexion.

@Before
fun setUp() {
    // Login if it is on the LoginActivity
    try {
        // Type email and password
        Espresso.onView(ViewMatchers.withId(R.id.et_email))
                .perform(ViewActions.typeText("a_test_account_username"), ViewActions.closeSoftKeyboard())
        Espresso.onView(ViewMatchers.withId(R.id.et_password))
                .perform(ViewActions.typeText("a_test_account_password"), ViewActions.closeSoftKeyboard())

        // Click login button
        Espresso.onView(ViewMatchers.withId(R.id.btn_login)).perform(ViewActions.click())
    } catch (e: NoMatchingViewException) {
        //view not displayed logic
    }
}

Avec cette annotation @Before, cette fonction setUp sera exécutée avant tout autre test que vous avez dans ce fichier de test. Si l'application atterrit sur l'activité de connexion, effectuez la connexion dans cette fonction de configuration. L'exemple ici suppose qu'il existe un EditText pour l'e-mail et le mot de passe, ainsi qu'un bouton de connexion. Il utilise Expresso pour taper l'e-mail et le mot de passe, puis appuyez sur le bouton de connexion. Le bloc try catch est de s'assurer que si vous n'atterrissez pas sur l'activité de connexion, il détectera l'erreur et ne fera rien, et si vous n'avez pas atterri sur l'activité de connexion, alors vous êtes prêt à passer d'autres tests de toute façon.

Remarque: il s'agit du code Kotlin, mais il ressemble beaucoup à Java.

3
s-hunter

Mon application requiert également que l'utilisateur soit connecté tout au long du test. Cependant, je peux me connecter la première fois et l'application se souvient de mon nom d'utilisateur/mot de passe tout au long du test. En fait, il se souvient des informations d'identification jusqu'à ce que je le force à les oublier ou à désinstaller et réinstaller l'application.

Lors d'un test, après chaque test, mon application passe en arrière-plan et reprend à nouveau au début du test suivant. Je suppose que votre application nécessite qu'un utilisateur saisisse ses informations d'identification chaque fois que vous la mettez en avant depuis l'arrière-plan (application bancaire peut-être?). Y a-t-il un paramètre dans votre application qui "se souviendra de vos informations d'identification"? Si oui, vous pouvez facilement l'activer juste après votre première connexion lors de votre test.

En dehors de cela, je pense que vous devriez parler aux développeurs de vous fournir un moyen de vous souvenir de vos informations d'identification.

2
drfrag01