paint-brush
So führen Sie täglich über 5000 Tests auf Mobilgeräten durch; Aus dem Playbook von inDrive (Teil 2)von@indrivetech
10,163 Lesungen
10,163 Lesungen

So führen Sie täglich über 5000 Tests auf Mobilgeräten durch; Aus dem Playbook von inDrive (Teil 2)

von inDrive.Tech7m2023/06/08
Read on Terminal Reader
Read this story w/o Javascript

Zu lang; Lesen

Im ersten Teil dieses Artikels haben wir beschrieben, wie Sie mit Appium und Selenoid schnell und einfach eine Infrastruktur zum Ausführen von UI-Tests auf Android aufbauen können. Wir setzen unsere Geschichte fort, um zu erklären, wie wir die Einführung von UI-Tests in iOS in den Prozess integriert haben. Wir verwenden den Go Grid Router (GGR) von den Leuten von Aerokube. GGR ist ein Load Balancer, der zum Erstellen skalierbarer und hochverfügbarer Selenium-Cluster verwendet wird.

People Mentioned

Mention Thumbnail
featured image - So führen Sie täglich über 5000 Tests auf Mobilgeräten durch; Aus dem Playbook von inDrive (Teil 2)
inDrive.Tech HackerNoon profile picture
0-item
1-item
2-item
3-item

Im ersten Teil dieses Artikels haben wir beschrieben, wie Sie mit Appium und Selenoid schnell und einfach eine Infrastruktur zum Ausführen von UI-Tests auf Android aufbauen können. Wir setzen unsere Geschichte fort, um zu erklären, wie wir die Einführung von UI-Tests in iOS in den Prozess integriert haben.

Skalierung mit GGR

Die maximale Anzahl paralleler Workflows innerhalb eines Hosts wird durch seine Ressourcen begrenzt. Daher benötigten wir ein Tool zum Zusammenfassen mehrerer Hosts in einem Cluster. Hierfür nutzen wir den Go Grid Router (GGR) von Aerokube. Basierend auf der Beschreibung in der Dokumentation handelt es sich bei GGR um einen Load Balancer, der zum Erstellen skalierbarer und hochverfügbarer Selenium-Cluster verwendet wird.





Das Projekt mit den Tests führt im Rahmen des verwendeten Prozesses eine Abfrage in GGR aus. Es fragt die in seiner Konfiguration angegebenen Selenoid-Parameter ab und verteilt die Last auf diese basierend auf der verwendeten Plattform, der Verfügbarkeit freier Flüsse und dem vordefinierten spezifischen Gewicht jedes Selenoids.



Die Bereitstellung von GGR und GGR-Benutzeroberfläche ist einfach:


  • Installieren Sie Docker .
  • Erstellen Sie ein Verzeichnis für GGR-Konfigurationsdateien mkdir -p /etc/grid-router/quota .
  • Erstellen Sie eine Datei „users.htpasswd“ $ htpasswd -bc /etc/grid-router/users.htpasswd test test-password .
  • Erstellen Sie eine Kontingentdatei, in der Sie die Adresse des bereitgestellten Selenoid als Host angeben:



 $ cat /etc/grid-router/quota/test.xml <qa:browsers xmlns:qa="urn:config.gridrouter.qatools.ru"> <browser name="android" defaultVersion="10.0" defaultPlatform="android"> <version number="10.0"> <region name="1"> <host name="0.0.0.0" port="4444" count="1"/> </region> </version> </browser> </qa:browsers>



  • Führen Sie den GGR-Container aus:


 docker run -d \ --name ggr \ -v /etc/grid-router/:/etc/grid-router:ro \ --net host aerokube/ggr:latest-release \ -listen=:4445 -guests-allowed



  • Ändern Sie im Testprojekt den Appium-Port in den Port des laufenden GGR:


 val driver = AndroidDriver(URL("http://localhost:4445/wd/hub"), capabilities)



  • Führen Sie den GGR-UI-Container aus:


 docker run -d \ --name ggr_ui \ -p 8888:8888 \ -v /etc/grid-router/quota:/etc/grid-router/quota:ro \ aerokube/ggr-ui:latest-release



  • Führen Sie den Selenoid-UI-Container aus, in dem wir den GGR-UI-Port über selenoid-uri übergeben:


 docker run -d \ --name selenoid-ui \ -p 4446:4446 \ --link selenoid:selenoid \ aerokube/selenoid-ui:1.10.4 \ --selenoid-uri "<http://ggr-ui:8888>"


Unsere Selenoid-Benutzeroberfläche sollte nun den Status aller mit GGR verbundenen Selenoid-Cluster anzeigen.


Nun fahren wir mit der Durchführung von Tests unter iOS fort

Wir verwenden unsere eigene Mac-Mini-Farm, um UI-Tests auf iOS durchzuführen. Die Farm kann ebenfalls aus ausgemusterten, aber betriebsbereiten MacBooks zusammengestellt werden. Alternativ können sie gemietet werden. Auf jedem Host muss Folgendes installiert werden:

  • Appium (Appium 2.x muss verwendet werden, wenn man mit iOS≥16 arbeitet).
  • Xcode.

Einige frühe Probleme

Wir konnten die Struktur, die bei der Ausführung von Android-Tests verwendet wurde, nicht reproduzieren, da wir keine Möglichkeit fanden, iOS-Simulatoren in Docker-Containern auszuführen. Eine Option, die wir in Betracht gezogen haben, war die Ausführung von Docker-OSX , aber wir hatten Zweifel an der Rechtmäßigkeit seiner Verwendung für Zwecke, die nichts mit der OS X-Sicherheitsforschung zu tun haben. Also entschieden wir uns, einen anderen Weg zu gehen.



Iteration Nr. 1: GGR→Appium

Wir haben Appium (Port 4723) als Selenoid-Host für iOS-Tests in der zuvor erstellten GGR-Konfigurationsdatei hinzugefügt:


 <qa:browsers xmlns:qa="urn:config.gridrouter.qatools.ru"> <browser name="android" defaultVersion="10.0" defaultPlatform="android"> <version number="10.0"> <region name="1"> <host name="0.0.0.0" port="4444" count="1"/> </region> </version> </browser> <browser name="iPhone 14" defaultVersion="16.2" defaultPlatform="iOS"> <version number="16.2"> <region name="1"> <host name="0.0.0.0" port="4723" count="1"/> </region> </version> </browser> </qa:browsers>


In einem solchen Fall sieht das iOS-Schema so aus:



Die in dieser Iteration verwendete Struktur ist betriebsbereit. Das Problem besteht darin, dass wir in diesem Fall nur Tests in einem Workflow auf jedem Mac mini ausführen können, was verschwenderisch ist. Außerdem wird der Cluster nicht in der Selenoid-Benutzeroberfläche angezeigt.

Iteration #2: GGR→Selenoid→Appium

Mit Selenoid können Sie mit mehr als nur Containern arbeiten. Die oben genannten Probleme beeinflussten unsere Entscheidung, Selenoid auch bei der Ausführung von iOS-Tests zu verwenden, allerdings als ausführbare Datei:


  • Laden Sie Selenoid ( amd64 / arm64 ) herunter.

  • Erstellen Sie eine browsers.json- Konfigurationsdatei.

  • Stellen Sie sicher, dass Sie Appium- und Starteinstellungen in der Konfigurationsdatei angeben:


 { "iPhone 14": { "default": "16.2", "versions": { "16.2": { "image": ["appium", "--log-timestamp", "--log-no-colors", ...] } } } }


  • Erteilen Sie die Erlaubnis, die Selenoid-Datei auszuführen. In unserem Fall haben wir chmod 755 verwendet.

  • Führen Sie Selenoid über das Terminal aus. Wir haben die folgenden Parameter verwendet: selenoid -conf ~/browsers.json -disable-docker -capture-driver-logs -service-startup-timeout 4m -session-attempt-timeout 4m -timeout 6m -limit 2 .

    • Die angegebenen Timeouts sind notwendig, da Standard-Timeouts möglicherweise nicht ausreichen, um die App aus dem Cloud-Speicher herunterzuladen und den Simulator zu starten.
    • Der Parameter -limit wurde verwendet, um die maximale Anzahl laufender Simulatoren festzulegen. Dies ist der Referenzwert, den die GGR künftig verwenden wird. Als Anhaltspunkt für die Einstellung des Parameters dient die Leistung des Hosts.
    • Weitere Informationen zu den Starteinstellungen finden Sie in der Selenoid- Dokumentation .
  • Bei Bedarf kann auf jedem Mac mini eine PLIST-Datei erstellt werden, um Selenoid im Falle eines plötzlichen Systemneustarts automatisch auszuführen.


Nun sieht der Prozess des Clusters so aus:



Mit diesem Ansatz erreichen wir teilweise die Funktionalität der Selenoid-Benutzeroberfläche und die Möglichkeit, Tests über mehrere Flows hinweg auf demselben Host auszuführen.



Der Nachteil besteht darin, dass Sie auf jedem Mac mini eine Vielzahl von Routineaufgaben manuell ausführen müssen, um einen Simulator zu erstellen und ihn durch Angabe der UUID und Portzuweisung mit Appium zu verknüpfen. Dies kann zu einem Problem werden, wenn Sie später auf eine neue iOS-Version aktualisieren müssen.

Iteration #3: GGR→Selenoid→Bash→Appium

Wir haben eine große Mac-Mini-Farm, die mit der Zeit weiter wachsen wird. Vor diesem Hintergrund suchten wir nach einer Möglichkeit, die Skalierung zu vereinfachen, sodass wir Simulatoren nicht manuell erstellen und sie dann mit Appium verbinden müssen. Mit dem bisherigen Schema hätten Appium und Simulatoren eine lange Lebensdauer gehabt, was zu unvorhersehbaren Folgen hätte führen können.


Auf der Suche nach einer Lösung haben wir festgestellt, dass in der Selenoid-Konfigurationsdatei ein Bash-Skript als Host angegeben werden kann:


 { "iPhone 14": { "default": "16.2", "versions": { "16.2": { "image": ["~/bin/config/start_appium.sh", "iPhone 14"] } } } }


So sieht unseres aus:


 #!/bin/bash set -ex DEVICE_NAME=$1 APPIUM_PORT=$(echo $2 | cut -d '=' -f 2) function clean() { if [ -n "$APPIUM_PID" ]; then kill -TERM "$APPIUM_PID" fi if [ -n "$DEVICE_UDID" ]; then xcrun simctl delete $DEVICE_UDID fi } trap clean SIGINT SIGTERM # Each simulator has a udid, so to run the same devices in parallel - clone and run # only clones. You cannot clone a running device. After closing the session, delete the clone. cloned_device_name="[APPIUM] ${DEVICE_NAME} ($(date +%Y%m%d%H%M%S))" DEVICE_UDID=$(xcrun simctl clone "$DEVICE_NAME" "$cloned_device_name") # https://github.com/appium/appium-xcuitest-driver#important-simulator-capabilities WDA_LOCAL_PORT=$(($APPIUM_PORT+1000)) MJPEG_SERVER_PORT=$(($WDA_LOCAL_PORT+1000)) DEFAULT_CAPABILITIES='"appium:udid":"'$DEVICE_UDID'","appium:automationName":"'XCUITest'","appium:wdaLocalPort":"'$WDA_LOCAL_PORT'","appium:mjpegServerPort":"'$MJPEG_SERVER_PORT'"' appium --base-path=/wd/hub --port=$APPIUM_PORT --log-timestamp --log-no-colors --allow-insecure=get_server_logs,adb_shell \ --allow-cors --log-timestamp --log {choose_directory_for_logs} \ --default-capabilities "{$DEFAULT_CAPABILITIES}" & APPIUM_PID=$! wait


Wenn das Skript verwendet wird, achten Sie genau auf die angegebenen Funktionen und Appium-Starteinstellungen. Diese werden hier unter der Annahme eingerichtet, dass Appium 2.x für die Ausführung verwendet wird. Für Appium 1.x muss der Anbieter nicht in den Funktionen angegeben werden, und es gibt keine Option zur Angabe von --base-pat.


Das Skript löst das Problem parallel laufender Simulatoren:


  • Wenn mehrere Appiums von einem Mac mini aus direkt mit GGR verbunden sind, entsteht ein Problem mit den Emulatoren , da Sie nicht denselben Emulator mit identischen UDIDs ausführen können. Sie müssen die UDID jedes Mal manuell duplizieren und fest codieren. (Zum Beispiel, wenn Sie die iOS-Version oder das Simulatormodell ändern müssen.)

  • Schlechte Skalierbarkeit . Es ist notwendig, Appium jedes Mal manuell auszuführen und es regelmäßig auf Konflikte mit Ports und Simulatoren zu überprüfen.


Die Verwendung von Selenoid ermöglicht es, diesen Prozess auf ein einziges Skript zu vereinfachen, das keine Konflikte zwischen mehreren Appium + Simulator-Paaren innerhalb eines einzelnen Hosts verursacht. Es startet Appium und beendet es, wenn es ein entsprechendes Signal von Selenoid empfängt. Außerdem klont es die Simulatoren beim Start dynamisch und löscht sie, sobald die Sitzung endet.


Der von uns entwickelte Prozess sieht folgendermaßen aus:



Als Nächstes fügen wir die Selenoid-Adressen jedes Mac mini zur Konfigurationsdatei des bereitgestellten GGR hinzu und führen dabei die Android- und iOS-Strukturen zusammen:



Fazit: Zusammenfassung

Die zusammengestellte Infrastruktur ermöglicht es uns, insgesamt etwa 500 UI-Tests pro Stunde über 36 Workflows auf beiden Plattformen durchzuführen. Das Hinzufügen eines neuen Hosts für Android-Tests kann mithilfe des Workflows auf GitHub Actions vollständig automatisiert werden und dauert etwa zwei Minuten. In naher Zukunft planen wir, die Bereitstellung des Selenoid-Clusters auch auf einem Mac mini zu automatisieren.



Im weiteren Verlauf würden wir gerne die Ausführung von Docker-OSX- Containern auf einem Mac mini mit Linux ausprobieren, um alle Prozesse zu vereinheitlichen und die Bereitstellung auf ihnen zu vereinfachen, ohne gegen die MacOS-Nutzungsregeln zu verstoßen. Wenn Sie entsprechende Erfahrungen gemacht haben, würden wir uns freuen, wenn Sie diese in den Kommentaren teilen.


Gepostet von Ivan Grigoriev .