Wir erstellen eine komplexe Android-Anwendung, die aus vielen Bildschirmen und Workflows besteht, die auf viele Aktivitäten verteilt sind. Unsere Workflows ähneln denen, die Sie möglicherweise am Geldautomaten einer Bank sehen. Beispielsweise gibt es eine Activity
Anmeldung, die zu einem Hauptmenü übergeht, Activity
das je nach Auswahl des Benutzers zu anderen Aktivitäten übergehen kann.
Da wir so viele Workflows haben, müssen wir automatisierte Tests erstellen, die mehrere Aktivitäten umfassen, damit wir einen Workflow von Ende zu Ende testen können. Am Beispiel eines Geldautomaten möchten wir beispielsweise eine gültige PIN eingeben, überprüfen, ob wir zum Hauptmenü gelangen, Bargeld abheben auswählen, sicherstellen, dass wir uns auf dem Bildschirm für Bargeld abheben usw. usw. befinden, und uns schließlich wiederfinden zurück im Hauptmenü oder "abgemeldet".
Wir haben mit den Test-APIs gespielt, die mit Android (z. B. ActivityInstrumentationTestCase2
) und auch mit Positron geliefert werden , aber beide scheinen nicht in der Lage zu sein, über die Grenzen eines einzelnen zu testen Activity
, und obwohl wir in diesen Tools für einige Unit-Tests einen Nutzen finden können, haben sie gewonnen Erfüllen Sie nicht unsere Anforderungen zum Testen von Szenarien, die sich über mehrere Aktivitäten erstrecken.
Wir sind offen für ein xUnit-Framework, Skripte, GUI-Rekorder / Wiedergaben usw. und würden uns über Ratschläge freuen.
quelle
Antworten:
Es ist mir ein bisschen unangenehm, meine eigene Kopfgeldfrage zu beantworten, aber hier ist es ...
Ich habe hoch und niedrig gesucht und kann nicht glauben, dass nirgendwo eine Antwort veröffentlicht wird. Ich bin sehr nahe gekommen. Ich kann jetzt definitiv Tests ausführen, die sich über Aktivitäten erstrecken, aber meine Implementierung scheint einige Zeitprobleme zu haben, bei denen die Tests nicht immer zuverlässig bestehen. Dies ist das einzige mir bekannte Beispiel für Tests, die mehrere Aktivitäten erfolgreich durchführen. Hoffentlich hat meine Extraktion und Anonymisierung keine Fehler verursacht. Dies ist ein vereinfachter Test, bei dem ich einen Benutzernamen und ein Kennwort in eine Anmeldeaktivität eingebe und dann beobachte, dass bei einer anderen "Willkommen" -Aktivität eine ordnungsgemäße Begrüßungsnachricht angezeigt wird:
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!")); } }
Dieser Code ist offensichtlich nicht sehr lesbar. Ich habe es tatsächlich in eine einfache Bibliothek mit einer englischsprachigen API extrahiert, sodass ich einfach Folgendes sagen kann:
type("myUsername").intoThe(username_field); click(login_button);
Ich habe bis zu einer Tiefe von ungefähr 4 Aktivitäten getestet und bin zufrieden, dass der Ansatz funktioniert, obwohl es, wie gesagt, gelegentlich ein Timing-Problem gibt, das ich nicht vollständig herausgefunden habe. Ich bin immer noch daran interessiert, von anderen Testmethoden für verschiedene Aktivitäten zu hören.
quelle
ActivityInstrumentationTestCase2
Werfen Sie einen Blick auf Robotium , ein Open-Source- Testframework , das entwickelt wurde, um das automatische Black-Box-Testen von Android-Anwendungen erheblich schneller und einfacher zu machen, als dies mit sofort einsatzbereiten
Android-Instrumentierungstests möglich ist.
Homepage: http://www.robotium.org/
Quelle: http://github.com/jayway/robotium
Bitte beachten Sie, dass das Robotium-Projekt von der Firma verwaltet wird, für die ich arbeite
quelle
Sie könnten immer Robotium verwenden. Es unterstützt Blackbox-Tests wie Selenium, jedoch für Android. Sie finden es auf Robotium.org
quelle
Ich bin überrascht, dass niemand einige der führenden Tools für automatisierte Funktionstests erwähnt hat . Im Vergleich zu Robotium muss hierfür kein Java-Code geschrieben werden.
MonkeyTalk : Ein Open-Source-Tool, das von der Firma Gorilla Logic unterstützt wird. Vorteile: Bietet Aufzeichnung sowie eine übergeordnete Skriptsprache, die für nicht technische Benutzer einfacher ist, und ist plattformübergreifend (einschließlich iOS). Angesichts dieser Vorteile als Anforderungen haben wir festgestellt, dass dies die beste Lösung ist. Es ermöglicht auch Anpassungen, die über das hinausgehen, was in ihrer Skriptsprache mit Javascript möglich ist.
Calabash-Android : Ein Open-Source-Tool für Funktionen im Gurkenstil. Vorteile: Schreiben Sie Funktionen in der Gherkin-Sprache Business Readable, Domain Specific Language, mit der Sie das Verhalten von Software beschreiben können, ohne genau zu beschreiben, wie dieses Verhalten implementiert wird. Eine ähnliche, aber nicht genaue Unterstützung ist für iOS in Gurken-ios verfügbar. Die Aufnahmefunktionen sind nicht so gut, da sie eine Binärausgabe erzeugen.
Einige andere Referenzen:
quelle
Ich habe ein Aufnahme- und Wiedergabetool für Android erstellt und es auf GitHub verfügbar gemacht . Es ist einfach zu konfigurieren und zu verwenden, erfordert keine Programmierung, läuft auf realen Geräten (die nicht gerootet werden müssen) und speichert automatisch Screenshots, während Tests getestet werden.
quelle
Verwenden Sie zunächst 'ActivityInstrumentationTestCase2' und nicht 'InstrumentationTestCase' als Basisklasse. Ich benutze Robotium und teste routinemäßig über mehrere Aktivitäten hinweg. Ich habe festgestellt, dass ich die Anmeldeaktivität als generischen Typ (und Klassenargument für den Konstruktor) angeben muss.
Der Konstruktor 'ActivityInstrumentationTestCase2' ignoriert das Paketargument und benötigt es nicht. Der Konstruktor, der das Paket übernimmt, ist veraltet.
Aus den Javadocs: "ActivityInstrumentationTestCase2 (String pkg, Class activityClass) Dieser Konstruktor ist veraltet. Verwenden Sie stattdessen ActivityInstrumentationTestCase2 (Class)."
Durch die Verwendung der empfohlenen Basisklasse kann das Framework bestimmte Boilerplates verarbeiten, z. B. das Starten Ihrer Aktivität. Dies geschieht bei Bedarf durch den Aufruf von 'getActivity ()'.
quelle
Fand dies mit ein paar Modifikationen nützlich. Erstens
getInstrumentation().waitForIdleSync()
heilt die Flakigkeit, von der SingleShot spricht, undInstrumentationTestCase
hat auch einelauchActivity
Funktion, die die Startaktivitätslinien ersetzen kann.quelle
Sie können dies folgendermaßen tun, um zu vermeiden, dass die Wartezeiten für Flocken nicht synchron sind:
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));
quelle
Ich arbeite an so ziemlich dem gleichen Thema und werde wahrscheinlich eine Variation der akzeptierten Antwort auf diese Frage vornehmen , aber ich bin bei meiner Suche nach einer Lösung auf Calculuon ( gitHub ) gestoßen .
quelle
Ich habe es nicht persönlich verwendet, aber ApplicationTestCase scheint das zu sein, wonach Sie suchen.
quelle
Funktioniert der akzeptierte Ansatz mit verschiedenen Aktivitäten aus verschiedenen Anwendungen, die von verschiedenen Zertifikaten signiert sind? Wenn nicht, ist Robotium der beste Weg, um Aktivitäten innerhalb derselben Anwendung zu testen.
quelle
Es gibt eine andere Möglichkeit, die Mehrfachaktivität mithilfe der ActivityInstrumentation-Klasse auszuführen. Dies ist ein normales Automatisierungsszenario. Konzentrieren Sie sich zuerst auf das gewünschte Objekt und senden Sie dann einen Schlüssel, der so einfach wie dieser Beispielcode ist
button.requestFocus(); sendKeys(KeyEvent.KEYCODE_ENTER);
Das einzige, was wir verstehen, ist, dass jeder API-Aufruf hilft.
quelle
Diese Antwort basiert auf der akzeptierten Antwort, wurde jedoch geändert, um das Timing-Problem zu lösen, das für mich nach dem Hinzufügen von etwa einem halben Dutzend Tests konsistent wurde. @ pajato1 erhält die Gutschrift für die Lösung des Timing-Problems, wie in den akzeptierten Antwortkommentaren angegeben.
/** * 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; }
quelle
Probieren Sie das Monkey-Tool aus
Schritt 1:
Öffnen Sie das Android Studio Terminal (Tools-> Open Terminal)
Schritt 2:
Um monkey zu verwenden, öffnen Sie eine Eingabeaufforderung und navigieren Sie einfach in das folgende Verzeichnis.
export PATH=$PATH:/home/adt-bundle-linux-x86-20140702/sdk/platform-tools
Schritt 3:
Fügen Sie diesen Affenbefehl in das Terminal ein und drücken Sie die Eingabetaste.
Sehen Sie die Magie in Ihrem Emulator.
adb shell monkey -p com.example.yourpackage -v 500
500 - Dies ist die Häufigkeit oder die Anzahl der Ereignisse, die zum Testen gesendet werden sollen.
Sie können diese Anzahl ändern.
Mehr Referenz,
http://www.tutorialspoint.com/android/android_testing.htm
http://androidtesting.blogspot.in/2012/04/android-testing-with-monkey-tool.html
quelle