Kassettenrekorder - ein Tool zum Aufzeichnen von Autotests



Guten Tag, liebe Leser. Ich heiße Victor Burov. Ich arbeite als Entwickler bei ISPsystem und möchte meine Erfahrungen in der Testautomatisierung teilen.

So kam es, dass in unserem Land manuelle Tests vorherrschten und die Tester viel Zeit damit verbrachten, dieselben Aktionen durchzuführen. Einmal dachten wir: Warum nicht dem Panel beibringen, die Aktionen des Testers zu wiederholen, denn tatsächlich werden alle zu spezifischen API-Aufrufen. Dies würde es den Leuten ermöglichen, Tests auch ohne Programmierkenntnisse zu schreiben.

Wir haben beschlossen, ein Modul zum Erstellen automatischer Tests zu schreiben. Damit der Tester einfach die Taste drücken kann, um einen Test zu erstellen, die Bedingungen des Testfalls zu erfüllen, klicken Sie am Ende auf "Fertig stellen" - und fertig, der Test war fertig! Eine einfache Idee, aber zu realisieren war nicht einfach. Weil wir wollten, dass dieses Modul maximal an unsere Produkte angepasst wird und eine einheitliche Oberfläche nutzt, damit das aufgenommene Video wie ein vorgefertigter Testfall aussieht. Dies würde die manuelle Arbeit beim Schreiben von Tests vollständig eliminieren. Das resultierende System wurde als "Tonbandgerät" bezeichnet.


Schnittstelle zum Anzeigen von Testfallbedingungen

Arbeitsprinzip


Alle Anforderungsparameter (HTTP-Header, Umgebungsvariablen, POST-Daten, falls vorhanden) und die gesamte Antwort werden in die XML-Datei geschrieben. Jedem Datensatz ist eine Seriennummer zugeordnet. Alle Anforderungen sind in modifizierende und nicht modifizierende unterteilt. Nach dem Aufzeichnen des Tests werden viele der nicht modifizierenden Anforderungen herausgeschnitten, da sie die Ausführung der Tests nicht beeinflussen und nur den Ausführungsprozess verzögern und verwirren (daher die fehlenden Sequenznummern im Screenshot).

Während der Aufnahme können Sie mit dem Kassettenrekorder die Werteprüfung in den Feldern der Formulare und in den Listenspalten mit einem Klick festlegen. Außerdem können Sie negative Tests aufzeichnen und sich daran erinnern, welchen Fehler das Bedienfeld während der Aufzeichnung eines Tests zurückgegeben hat.

Während der Wiedergabe werden Anforderungen ohne Verwendung eines Browsers direkt an die Anwendungs-API gesendet.

Tatsächlich ist ein Kassettenrekorder ein Modul, das in alle unsere Produkte integriert ist und es Ihnen ermöglicht, ereignisreaktive Prozessoren zu installieren. Geschrieben mit COREmanager.

Ein Beispiel für die Aufzeichnung eines Anrufs mit einem Kassettenrekorder:

Aufzeichnen
<params> <param name="CONTENT_LENGTH">210</param> <param name="CONTENT_TYPE">application%2Fx%2Dwww%2Dform%2Durlencoded%3B%20charset%3DUTF%2D8</param> <param name="HTTPS">on</param> <param name="HTTP_ACCEPT">text%2Fhtml%2C%20%2A%2F%2A%3B%20q%3D0%2E01</param> <param name="HTTP_ACCEPT_LANGUAGE">en%2DUS%2Cen%3Bq%3D0%2E5</param> <param name="HTTP_CACHE_CONTROL">no%2Dcache</param> <param name="HTTP_CONNECTION">keep%2Dalive</param> <param name="HTTP_COOKIE">corelang5%3Dorion%3Aru%3B%20ispmgrlang5%3Dorion%3Aru%3B%20ipmgrlang5%3Dorion%3Aru%3B%20ipmgrses5%3Dbdd69179d627%3B%20ispmgrses5%3D14157f7bbc5e%3B%20menupane%3D30%5Faccount%2D1%253A30%5Fdomains%2D1%253A30%5Fwebserver%2D1%253A30%5Fantispam%2D1%253A30%5Fmaintain%2D1%253A30%5Ftool%2D1%253A30%5Fstat%2D1%253A30%5Fsrvset%2D1%253A30%5Fsysstat%2D1%253A30%5Fintegration%2D1%253A30%5Fset%2D1%253A30%5Fmgrhelp%2D1</param> <param name="HTTP_HOST">172%2E31%2E240%2E175%3A1500</param> <param name="HTTP_ISP_CLIENT">Web%2Dinterface</param> <param name="HTTP_PRAGMA">no%2Dcache</param> <param name="HTTP_REFERER">https%3A%2F%2F172%2E31%2E240%2E175%3A1500%2Fispmgr</param> <param name="HTTP_USER_AGENT">Mozilla%2F5%2E0%20%28X11%3B%20Ubuntu%3B%20Linux%20x86%5F64%3B%20rv%3A24%2E0%29%20Gecko%2F20100101%20Firefox%2F24%2E0</param> <param name="HTTP_X_REQUESTED_WITH">XMLHttpRequest</param> <param name="QUERY_STRING"/> <param name="REMOTE_ADDR"></param> <param name="REMOTE_PORT">38640</param> <param name="REQUEST_METHOD">POST</param> <param name="REQUEST_URI">%2Fispmgr</param> <param name="SCRIPT_NAME">%2Fispmgr</param> <param name="SERVER_ADDR">172%2E31%2E240%2E175</param> <param name="SERVER_NAME">172%2E31%2E240%2E175</param> <param name="SERVER_PORT">1500</param> </params> <postdata>func%3Demaildomain%2Eedit%26elid%3D%26name%3Dtest%2Eemail%26owner%3Dusr%26ipsrc%3Dauto%26defaction%3Derror%26redirval%3D%26spamassassin%3Doff%26avcheck%3Doff%26clicked%5Fbutton%3Dok%26progressid%3Dfalse%5F1424243906672%26sok%3Dok%26sfrom%3Dajax%26operafake%3D1424243906673</postdata> <answer> <doc lang="ru" func="emaildomain.edit" binary="/ispmgr" host="https://172.31.240.175:1500" features="cba82687e7756e2c0195c88d4180f5d50" notify="0" theme="/manimg/orion/" css="main.css" logo="logo-ispmgr.png" logolink="" favicon="favicon-ispmgr.ico" localdir="default/"> <metadata name="emaildomain.edit" type="form" mgr="ispmgr" decorated="yes"> <form> <field name="name"> <input type="text" name="name" required="yes" check="domain" convert="punycode" maxlength="255"/> </field> //   <buttons> <button name="ok" type="ok"/> <button name="cancel" type="cancel"/> </buttons> </form> </metadata> <messages name="emaildomain.edit" checked="cba82687e7756e2c0195c88d4180f5d5"> <msg name="currentmonth"> </msg> // </messages> <doc lang="ru" func="emaildomain.edit" binary="/ispmgr" host="https://172.31.240.175:1500" features="cba82687e7756e2c0195c88d4180f5d50" notify="0" theme="/manimg/orion/" css="main.css" logo="logo-ispmgr.png" logolink="" favicon="favicon-ispmgr.ico" localdir="default/"> <slist name="owner"> <val key="usr">usr</val> </slist> <slist name="defaction"> <val msg="yes" key="error">  </val> </slist> <slist name="ipsrc"> <val msg="yes" key="auto"> </val> </slist> <name/> <avcheck>off</avcheck> <owner>usr</owner> <ipsrc>auto</ipsrc> </doc> <id>test.email</id> <ok/> <tparams> <clicked_button>ok</clicked_button> </tparams> </doc> </answer> <localmacro> <macros name="mpre_HostIP" field="ipsrc">auto</macros> </localmacro> 

Verbesserungen (über die wir nicht im Voraus nachgedacht haben)


Warten


Eine Person kann "nur warten", ein Computer - nein. Eines der ersten Probleme, die der Kassettenrekorder lösen sollte, war das Schreiben von Vaters. Was die Leute nicht erfunden haben, um auf den Abschluss der Operation zu warten. Die Erwartung von Hintergrundaufgaben und die Möglichkeit, für eine bestimmte Anzahl von Sekunden einen Stopp am angegebenen Schritt hinzuzufügen, wurden implementiert.

Testschritte aufzeichnen und bearbeiten


Wahrscheinlich erinnert sich jeder an die Zeiten der Schreibmaschinen: ein Fehler - und Sie müssen die gesamte Seite neu drucken.



Damit der Tester nicht den gesamten Test mit einer fehlerhaften Aktion neu schreiben musste, wurde ein Mechanismus hinzugefügt, um den Test von jedem Schritt nach dem Speichern neu aufzuzeichnen. Die Möglichkeit zum Bearbeiten ist praktisch, wenn Sie den Test an Änderungen im Verhalten der getesteten Funktionen anpassen müssen.

Makros für Variablen


Während der Tests änderten sich die Werte in den übertragenen und überprüften Parametern je nach Server, auf dem sie ausgeführt wurden. Ein Beispiel für solche Daten sind IP-Adressen. Es ist unmöglich, sie in der Testaufzeichnungsphase zu erkennen, daher habe ich ein Makrosystem hinzugefügt. Auf diese Weise konnten wir Tests erstellen, die nicht so stark an die Umgebung gebunden sind. Der Nachteil der Lösung besteht darin, dass Makros nach der Aufzeichnung manuell angegeben werden müssen.

Ein weiteres Problem, das die Arbeit mit dem Kassettenrekorder erheblich erschwert, ist die Verwendung nicht nativer Schlüssel. Wir haben es nicht sofort bemerkt, als wir den Kassettenrekorder auf ISPmanager getestet haben, der native Bezeichner verwendet. In einigen anderen Bereichen wird der Datensatz jedoch durch eine eindeutige ID identifiziert. Daher musste ich dem Kassettenrekorder beibringen, die Kennung nach dem Erstellen des Datensatzes oder Objekts nicht nur zu erhalten (da sich die ID von Anfang zu Start ändern kann), sondern sie auch bei allen nachfolgenden Anforderungen zu ersetzen.

Unterstützung des JUnit-Formats


Von Bändern generierte Tests werden automatisch in der Jenkins-Umgebung für die kontinuierliche Integration ausgeführt. Nach Abschluss der Tests wird eine XML-Datei erstellt, die die Daten im JUnit-Format enthält. Damit die Datei korrekt erstellt werden kann, wurde eine Einschränkung für die Benennung von Tests eingeführt. Beispielsweise fiel der Test User.Create.xml in die Testsuite mit dem Namen User und hatte daher einen Testfall namens Create. Im Fehlerfall wurde ein Fehlerknoten mit einer vollständigen Beschreibung des Fehlers hinzugefügt.

Metriken


Die Anzahl der eindeutigen aufgerufenen Funktionen wird während des Testdurchlaufs berechnet und das Verhältnis als Prozentsatz der Gesamtzahl der Funktionen bestimmt, ausgenommen diejenigen, die nur für den internen Gebrauch verfügbar sind. Somit wird die einfachste Testabdeckung gemessen. Darüber hinaus zeigen die Metriken die Gesamtzeit für den Abschluss des Tests und die Anzahl der erfolgreichen und fehlgeschlagenen Tests.

Repository testen


Das Test-Repository löst zunächst das Problem der Übertragung vorgefertigter Tests auf andere Server. Es ist auch praktisch, wenn mehrere Tester Tests schreiben. Auf Basis unseres CORE-Managers wurde ein kleines Panel zum Speichern von Speichertests entwickelt und bereitgestellt. Das Tonbandgerät verfügt über ein Modul zum Synchronisieren von Tests mit dem Speicher. Wenn Sie einen neuen Test schreiben oder Tests aus dem Repository entladen, sind sie automatisch nicht mehr zum Laden in das Repository verfügbar, sodass keine Verwirrung entsteht. Nach dem Ändern des Tests wird die Versionsnummer erhöht, sodass nur Tests nach dem Laden der Änderungen in das Repository geladen werden.

Schwierigkeiten (na ja, wo ohne sie)


Die Verwendung eines Tonbandgeräts zeigte, dass nicht alle API-Funktionen unseren internen Empfehlungen entsprachen. Insbesondere haben nicht alle Funktionen die Datensatzkennung nach ihrer Erstellung zurückgegeben. Ich musste zurückkehren, einschließlich eines Arbeitscodes, und ihn an die Anforderungen anpassen.

Deadlock ist ein weiteres Problem. Das Panel impliziert die Ausführung einiger kritischer Aktionen im exklusiven Modus. Und das Tonbandgerät, das Teil desselben Panels war und solche Funktionen verursachte, ließ das gesamte System einfrieren. Dies konnte nur mit Hilfe von GDB festgestellt werden (niemand erinnerte sich an diese Funktion). Leider gab es Krücken, da bei der Ausführung der Tests des Tonbandgeräts entschieden wurde, diese Funktionen im Multithread-Modus auszuführen. Theoretisch war es möglich, ein Tonbandgerät nicht mit einem Modul, sondern mit einem separaten Panel zu entwerfen. Aber wir haben es nicht versucht.

Leider ist auch das Schreiben und Vergessen gescheitert. Die Benutzeroberfläche unserer Produkte ändert sich und wird immer komplizierter. Darüber hinaus wächst die Anzahl der Schnittstellenkomponenten aktiv. Daher muss der Kassettenrekorder von Zeit zu Zeit geändert werden, damit er beim Erscheinen neuer Komponenten deren Struktur analysieren und die Ergebnisse von Abfragen verarbeiten kann.

Fazit


Die Erstellung eines Tonbandgeräts hat dazu beigetragen, die Qualität der getesteten Produkte zu verbessern. Zeit und Ressourcen für die Schulung von Testern gespart. Auf dem Weg dorthin konnten wir mit dem Kassettenrekorder unsere API auf Übereinstimmung mit internen Empfehlungen überprüfen und die API daher etwas „logischer“ gestalten.

Source: https://habr.com/ru/post/de421007/


All Articles