
Das Seitenobjektmuster erschien in Webtests und erwies sich dort als sehr gut. Als ich anfing, Tests für Android-Anwendungen zu automatisieren, dachte ich als erstes darüber nach. Ich suchte im Netzwerk nach Informationen, fragte meine Kollegen und fand im Prinzip keine Gründe, es nicht zu versuchen. Ich schlage vor zu sehen, was daraus wurde.
Das klassische Seitenobjekt impliziert zwei Abstraktionsebenen: Seitenelemente und Tests. Ich hebe noch eine hervor - Geschäftslogik. Ich stelle fest, dass die Art und Weise, wie Sie Ihr Framework erstellen, die Leichtigkeit des Schreibens von Tests in der Zukunft sowie deren Unterstützung erheblich beeinflussen wird. Ich versuche, den Testcode so aussehen zu lassen, als wäre er ein normaler Testfall, der von einem normalen Tester geschrieben wurde. Das heißt, Ich fange am Ende an:
- Ich schreibe einen schönen und klaren Testfallcode,
- Ich implementiere Methoden aus dem Testfall in der Geschäftslogikschicht.
- Ich beschreibe die Elemente, die für den Test benötigt werden.
Dieser Ansatz ist gut, weil wir nichts extra tun - das Framework baut so weit auf, wie es für die Tests erforderlich ist. Wir können sagen, dass dies das Konzept von MVP beim Testen ist: Sie haben schnell ein Stück gemacht, und es hat bereits begonnen, Vorteile zu bringen. Wenn Sie zuerst Tausende von Zeilen schreiben, die Seiten Ihrer Anwendung beschreiben und wie Sie mit ihnen interagieren, und nach drei Monaten beim ersten Klick aus dem Loch herauskommen und feststellen, dass Sie alles anders machen mussten, ist der größte Teil Ihrer Kreation für immer zum Scheitern verurteilt. " Staub sammeln “in den Kellern von Git ... Ein echter Tester weiß, dass es umso billiger ist, einen Fehler zu beheben, je früher er gefunden wird. Verwenden Sie diesen Ansatz in allem - haben Sie in ein paar Stunden einen Test geschrieben, ihn ausprobiert, haben ihn nicht gemocht - haben ihn rausgeworfen, eine Lektion gelernt, sind weitergefahren.
Die Eingabe lautet also:
- Android-Anwendung für den Handel an der Börse;
- Java, um mit Entwicklern im selben Stack zu arbeiten;
- Grundgerüst UI Automator;
- Sie müssen einen Anmeldetest in die Anwendung schreiben.
Projektvorbereitung
Da ich versucht habe, so viel wie möglich in den Entwicklungsprozess zu integrieren, habe ich nicht begonnen, ein neues Projekt zu erstellen. Gemäß der
Dokumentation müssen instrumentelle Tests im Ordner
src/androidTest/java
. In meinem Fall wurde der Kollektor bereits konfiguriert. Wenn etwas nicht stimmt, lesen Sie
die Build-Konfiguration . Wir brauchen auch eine Entwicklungsumgebung, Android SDK, Emulator, Tools, Plattform-Tools und die notwendigen Plattformen für den Emulator. Wenn Sie Android Studio verwenden, kann dies alles schnell über den SDK-Manager installiert werden:

Testschicht
Wie ich oben geschrieben habe, werden wir den Anmeldetest in der Anwendung automatisieren. Denken Sie daran, dass der Code wie ein normaler Testfall aussehen sollte:
Voraussetzung: Führen Sie die Anwendung aus.
Schritt 1: Melden Sie sich mit dem Konto myLogin / myPassword an.
Schritt 2: Überprüfen Sie den Namen des aktuellen Benutzers.
Erwartetes Ergebnis: Derzeitiger Benutzer ist Ivan Ivanov.
Kleiner Haftungsausschluss: Gemäß den Best Practices des Designtests müssen Sie unter der Voraussetzung ein Konto erstellen / finden. Ich habe diesen Moment der Einfachheit halber weggelassen.Unsere Klasse wird so aussehen:
@RunWith(AndroidJUnit4.class) public class LoginTests { private TestApplication myApp; @Before public void setUp() { myApp = new TestApplication(); } @Test public void testLogin() { myApp.login("myLogin","myPassword"); String currentUser = myApp.getCurrentUserName(); assertEquals("Wrong name", " ", currentUser); } @After public void tearDown() { myApp.close(); } }
Geschäftslogik
Der Test verwendet die
TestApplication()
-Klasse und ihre beiden Methoden:
login()
und
getCurrentUserName()
. Außerdem benötigen Sie einen Klassenkonstruktor (der die Anwendung darin startet) und die Methode
close()
. Die Vorderseite ist klar:
public class TestApplication { private UiDevice device; private PageObject page; public TestApplication() { } public void login(String login, String password) { } public String getCurrentUserName() { return "" } public void close() { } }
Eine Instanz unserer Klasse hat zwei Variablen:
device
, das zur Klasse android.support.test.uiautomator.UiDevice
- über dieses interagieren wir mit unserem Gerät;page
, die PageObject
Klasse, die wir im nächsten Abschnitt erstellen werden.
Beginnen wir mit dem Konstruktor. Erstellen Sie darin Instanzen unserer Variablen und führen Sie die Anwendung aus:
public TestApplication() {
Einige Tipps zum Starten der AnwendungUm die zu testende Anwendung besser steuern zu können, können Sie die Erwartungen für den Start des Starters (wenn Sie den Emulator "kalt" ausführen) und die Anwendung selbst hinzufügen. Dies wird auch in der
Dokumentation empfohlen.
Hinweis: Das Ausführen der Anwendung über android.content.Context.getTargetContext()
ist nur geeignet, wenn sich Ihre Tests im selben Projekt wie die Anwendung selbst befinden. Wenn separat, muss das Menü durchlaufen werden.Die Geschäftslogik des Tests sind die spezifischen Schritte, die der Benutzer ausführen muss, um ein aussagekräftiges (für den Benutzer) Ergebnis zu erzielen. Die Anmeldung mit Ihrem eigenen Ultraschall ist ein wichtiges Ergebnis. Schritte: Klicken Sie auf die Schaltfläche "Anmelden", geben Sie den Benutzernamen in das Feld "Anmelden" ein, geben Sie das Kennwort in das Feld "Kennwort" ein und klicken Sie auf die Schaltfläche "Anmelden". Daher ist unsere Methode mit Schritten gefüllt:
public void login(String login, String password) { page.login().click(); page.loginEntry().setText(login); page.passwordEntry().setText(password); page.signIn().click(); }
Um den aktuellen Benutzer zu erhalten, ist alles einfacher. Rufen Sie einfach den Feldwert ab:
public String getCurrentUserName() { return page.currentUserName().getText(); } }
Um die Anwendung zu schließen, klicken Sie einfach auf die Schaltfläche Home:
public void close() { device.pressHome(); }
Beschreibung der Seitenelemente
Das Konzept dieser Ebene besteht darin, dass sie gebrauchsfertige Elemente zurückgeben sollte (in unserem Kontext ist dies die Klasse
android.support.test.uiautomator.UiObject2
). Das heißt, der Verbraucher sollte sich keine Gedanken über den Zustand des Objekts machen. Wenn er zurückkehrt, können Sie sofort mit ihm interagieren: Klicken Sie auf den Text, füllen Sie ihn aus oder lesen Sie ihn. Dies ist eine wichtige Konsequenz - in dieser Schicht werden wir die Erwartungen verwirklichen:
private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); }
Die oben definierte Methode wird von der öffentlichen Schnittstelle unserer
PageObject
Klasse verwendet. Beispiel für das Anmeldefeld:
public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); }
Es bleibt zu bestimmen, mit welchem Selektor wir das Feld finden. Die Instanz von
android.support.test.uiautomator.BySelector
am bequemsten mit den statischen Methoden der Klasse
android.support.test.uiautomator.By
. Ich stimmte der Entwicklung zu, dass es überall, wann immer möglich, eine eindeutige Ressourcen-ID geben wird:
private BySelector loginEntrySelector() { return By.res(packageName, "login"); }
Es ist praktisch, die Benutzeroberfläche im Dienstprogramm uiautomatorviewer zu überprüfen, das im Toolpaket enthalten ist (installiert im Abschnitt Vorbereitung):

Wählen Sie das gewünschte Element aus und sehen Sie sich im Abschnitt Knotendetails die Ressourcen-ID an. Es besteht aus dem Namen des Pakets und der Kennung. Wir haben den Namen des Pakets im Konstruktor der
TestApplication
Klasse erhalten und ihn beim Erstellen des
PageObject
.
Vollständiger Code:
Klasse PageObject public class PageObject { private UiDevice device; private final String packageName; private BySelector loginButtonSelector() { return By.res(packageName, "user_view"); } private BySelector loginEntrySelector() { return By.res(packageName, "login"); } private BySelector passwordEntrySelector() { return By.res(packageName, "password"); } private BySelector signInSelector() { return By.res(packageName, "btnLogin"); } private BySelector userNameSelector() { return By.res(packageName, "user_name"); } public PageObject(UiDevice device, String packageName) { this.device = device; this.packageName = packageName; } public UiObject2 login() { return getUiObject(loginButtonSelector()); } public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); } public UiObject2 passwordEntry() { return getUiObject(passwordEntrySelector()); } public UiObject2 signIn() { return getUiObject(signInSelector()); } public UiObject2 currentUserName() { return getUiObject(userNameSelector()); } private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); } }
Ausführen von Tests
Das ist alles, es bleibt zu laufen. Stellen Sie zunächst eine Verbindung zum Gerät her oder starten Sie den Emulator. Überprüfen Sie die Verbindung mit dem Befehl
adb devices
(das Dienstprogramm adb ist Teil der Plattform-Tools):
List of devices attached emulator-5554 device
Wenn Sie einen Gradle haben, dann tun Sie es
gradlew.bat connectedAndroidTest
und genießen Sie, wie "Roboter injiziert werden, nicht Menschen" (c).