Question

Nous construisons une application Android complexe composé de nombreux écrans et des flux de travail répartis dans de nombreuses activités. Nos flux de travail sont semblables à ce que vous pouvez voir sur une machine ATM de la Banque, par exemple, il y a un Activity pour vous connecter à considérer que le passage à un menu principal Activity qui peut passer à d'autres activités en fonction des choix de l'utilisateur.

Depuis que nous avons tant de flux de travail dont nous avons besoin pour créer des tests automatisés couvrant plusieurs activités afin que nous puissions tester un flux de travail de bout en bout. Par exemple, en utilisant l'exemple ATM, nous voulons saisir un code PIN valide, vérifiez que nous envoie au menu principal, choisissez retirer de l'argent, vérifier que nous sommes sur le retrait écran de caisse, etc., etc., et finalement nous trouver Retour dans le menu principal ou sur « connecté ».

Nous avons joué avec les API de test qui viennent avec Android (par exemple ActivityInstrumentationTestCase2) et aussi avec positons , mais ne semble capable de tester au-delà des limites d'un seul Activity, et alors que nous pouvons trouver une certaine utilité dans ces outils pour certains tests unitaires, ils ne seront pas répondre à nos besoins pour les scénarios de tests qui coupent à travers de multiples activités.

Nous sommes ouverts à un cadre xUnit, les scripts, les enregistreurs GUI / play-back, etc. et apprécierions des conseils.

Était-ce utile?

La solution

Je me sens un peu maladroit au sujet de répondre à ma propre question de prime, mais ici il est ...

Je l'ai cherché haut et bas sur ce sujet et ne peux pas croire qu'il n'y a pas de réponse publiée nulle part. Je suis venu très près. Je peux certainement exécuter des tests qui couvrent les activités maintenant, mais ma mise en œuvre semble avoir quelques problèmes de synchronisation où les tests ne passent pas toujours fiable. Ceci est le seul exemple que je connaisse qui teste sur plusieurs activités avec succès. Espérons que mon extraction et anonymisation de celui-ci n'a pas introduit d'erreurs. Ceci est un test simpliste où je tape un nom d'utilisateur et mot de passe dans une activité de connexion, puis observez un message de bienvenue approprié apparaît sur une autre activité « bienvenue »:

package com.mycompany;

import android.app.*;
import android.content.*;
import android.test.*;
import android.test.suitebuilder.annotation.*;
import android.util.*;
import android.view.*;
import android.widget.*;

import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsNull.*;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.*;
import static com.mycompany.R.id.*;

public class LoginTests extends InstrumentationTestCase {

   @MediumTest
   public void testAValidUserCanLogIn() {

      Instrumentation instrumentation = getInstrumentation();

      // Register we are interested in the authentication activiry...
      Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(AuthenticateActivity.class.getName(), null, false);

      // Start the authentication activity as the first activity...
      Intent intent = new Intent(Intent.ACTION_MAIN);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      intent.setClassName(instrumentation.getTargetContext(), AuthenticateActivity.class.getName());
      instrumentation.startActivitySync(intent);

      // Wait for it to start...
      Activity currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Type into the username field...
      View currentView = currentActivity.findViewById(username_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyUsername");

      // Type into the password field...
      currentView = currentActivity.findViewById(password_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyPassword");

      // Register we are interested in the welcome activity...
      // this has to be done before we do something that will send us to that
      // activity...
      instrumentation.removeMonitor(monitor);
      monitor = instrumentation.addMonitor(WelcomeActivity.class.getName(), null, false);

      // Click the login button...
      currentView = currentActivity.findViewById(login_button;
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(Button.class));
      TouchUtils.clickView(this, currentView);

      // Wait for the welcome page to start...
      currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Make sure we are logged in...
      currentView = currentActivity.findViewById(welcome_message);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(TextView.class));
      assertThat(((TextView)currentView).getText().toString(), is("Welcome, MyUsername!"));
   }
}

Ce code est évidemment pas très lisible. Je l'ai fait extrait dans une bibliothèque simple avec une API comme l'anglais, donc je peux dire des choses comme ceci:

type("myUsername").intoThe(username_field);
click(login_button);

Je l'ai testé à une profondeur d'environ 4 activités et je suis convaincu que l'approche fonctionne bien comme je le disais, il semble y avoir un problème occasionnel de temps que je ne l'ai pas complètement compris. Je suis toujours intéressé à l'audition de toute autre façon de tester dans toutes les activités.

Autres conseils

Jetez un oeil à Robotium un cadre de test open-source créé pour faire des tests automatiques boîte noire d'applications Android nettement plus rapide et plus facile que ce qui est possible avec les tests d'instrumentation Android hors-the-box ».

Page d'accueil: http://www.robotium.org/
La source: http://github.com/jayway/robotium

S'il vous plaît noter que le projet Robotium est maintenu par l'entreprise où je travaille

Vous pouvez toujours utiliser Robotium. Il prend en charge les tests de Blackbox comme Sélénium mais pour Android. Vous le trouverez à Robotium.org

Je ne suis pas surpris n'a mentionné quelques-uns des plus grands outils de tests fonctionnels automatisés . Par rapport à Robotium, ceux-ci ne nécessitent pas l'écriture de code Java.

MonkeyTalk : un outil open source soutenu par la société Gorilla Logique. Avantages: permet d'enregistrer ainsi qu'un langage de script de niveau supérieur plus facile pour les utilisateurs non-techniques, et est multi-plateforme (y compris iOS). Compte tenu de ces avantages que les exigences, nous avons trouvé que ce la meilleure solution. Il permet également la personnalisation au-delà de ce qui peut être fait dans leur langage de script utilisant Javascript.

Calabash Android : un outil open-source caractéristiques de style de concombre. Plus: écrire fonctionnalités dans la langue Gherkin qui est entreprise Lisible, domaine Langue spécifique qui vous permet de décrire le comportement des logiciels sans préciser comment ce comportement est mis en œuvre. Similaire, mais pas de support exacte est disponible pour iOS concombre-ios . capacités d'enregistrement ne sont pas aussi bien, car ils produisent une sortie binaire.

Quelques autres références:

J'ai créé un outil enregistrement et de lecture pour Android et diffuser à la GitHub . Il est facile à configurer et à utiliser, ne nécessite aucune programmation, va à l'encontre des appareils réels (qui ne doivent pas être enraciné) et enregistre automatiquement des captures d'écran comme il joue des tests.

Tout d'abord, utilisez 'ActivityInstrumentationTestCase2', pas 'InstrumentationTestCase', en tant que votre classe de base. J'utilise Robotium et tester régulièrement sur plusieurs activités. Je trouve que je dois préciser l'activité de connexion comme le type générique (et l'argument de classe au constructeur).

Le constructeur « ActivityInstrumentationTestCase2 » ignore l'argument du paquet et ne l'exige pas. Le constructeur qui prend le paquet est obsolète.

De l'Javadocs: « ActivityInstrumentationTestCase2 (String pkg, classe activityClass) Ce constructeur est dépréciée. utiliser ActivityInstrumentationTestCase2 (classe) au lieu "

Utilisation de la classe de base recommandée permet le cadre de gérer certains passe-partout, comme le démarrage de votre activité. Cela se fait par l'appel à 'getActivity (), si nécessaire.

Nous avons trouvé cet utile avec quelques modifications. Tout d'abord getInstrumentation().waitForIdleSync() guérira le flakiness SingleShot parle de et aussi InstrumentationTestCase a une fonction de lauchActivity qui peut remplacer les lignes d'activité de départ.

vous pouvez le faire comme ceci pour éviter les temps d'attente flocons désynchronisés:

final Button btnLogin = (Button) getActivity().findViewById(R.id.button);
Instrumentation instrumentation = getInstrumentation();

// Register we are interested in the authentication activity...
Instrumentation.ActivityMonitor aMonitor = 
        instrumentation.addMonitor(mynextActivity.class.getName(), null, false);

getInstrumentation().runOnMainSync(new Runnable() {
         public void run() {
             btnLogin.performClick();
         }
     });

getInstrumentation().waitForIdleSync();

//check if we got at least one hit on the new activity
assertTrue(getInstrumentation().checkMonitorHit(aMonitor, 1)); 

Je travaille sur à peu près la même chose, et je vais probablement aller avec une variation sur la réponse acceptée à cette question, mais je n'ai rencontré Calculuon ( GitHub ) au cours de mes recherches pour une solution

Je ne l'ai pas utilisé personnellement, mais ApplicationTestCase semble que cela pourrait être ce que vous cherchez.

Will a accepté le travail d'approche avec les différentes activités de différentes applications, signé par différents certificats? Dans le cas contraire, Robotium la meilleure façon de tester les activités dans une même application.

Il y a une autre façon de faire l'activité multiple utilisant ActivityInstrumentation classe .. Son scénario d'automatisation normale ... Tout d'abord le focus de ce objet que vous voulez, puis envoyer une clé Aussi simple que cela exemple de code

button.requestFocus();
sendKeys(KeyEvent.KEYCODE_ENTER);

La seule chose est de comprendre les tous les appels API va nous aider.

Cette réponse est basée sur la réponse acceptée, mais modifié pour résoudre le problème de synchronisation qui pour moi est devenu cohérent après l'ajout d'environ un demi-douzaine de tests. @ Pajato1 obtient le crédit pour résoudre le problème de synchronisation, tel que cité dans les commentaires de réponse acceptée.

/**
 * Creates a test Activity for a given fully qualified test class name.
 *
 * @param fullyQualifiedClassName The fully qualified name of test activity class.
 *
 * @return The test activity object or null if it could not be located.
 */
protected AbstractTestActivity getTestActivity(final String fullyQualifiedClassName) {
    AbstractTestActivity result = null;

    // Register our interest in the given activity and start it.
    Log.d(TAG, String.format("Running test (%s) with main class: %s.", getName(), fullyQualifiedClassName));
    instrumentation = getInstrumentation();

    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setClassName(instrumentation.getTargetContext(), fullyQualifiedClassName);
    // Wait for the activity to finish starting
    Activity activity = instrumentation.startActivitySync(intent);

    // Perform basic sanity checks.
    assertTrue("The activity is null!  Aborting.", activity != null);
    String format = "The test activity is of the wrong type (%s).";
    assertTrue(String.format(format, activity.getClass().getName()), activity.getClass().getName().equals(fullyQualifiedClassName));
    result = (AbstractTestActivity) activity;

    return result;
}

Essayez le test de l'outil Monkey

Etape 1:

ouvrir le terminal de studio androïde (Outils-> borne ouverte)

Étape 2:

Pour utiliser le singe, ouvrez une invite de commande et juste naviagte dans le répertoire suivant.

 export PATH=$PATH:/home/adt-bundle-linux-x86-20140702/sdk/platform-tools

Étape 3:

ajouter cette commande de singe dans le terminal et appuyez sur Entrée ..

voir la magie dans votre émulateur.

adb shell monkey -p com.example.yourpackage -v 500

500- il est le nombre de fréquence ou le nombre d'événements à envoyer pour le test.

vous pouvez modifier ce nombre ..

Plus référence,

http://www.tutorialspoint.com/android/android_testing.htm

http://androidtesting.blogspot.in/ 2012/04 / android-test avec-singe-tool.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top