Erstellen eines Tools zum schnellen und effizienten Schreiben von Autotests auf Selen

Grundlegende Bausteinautomatisierung - Testen
Rod Johnson
Bild

Ich bin kein Botschafter für das Testen von Webschnittstellen, aber dieser Aufsatz ist eher für Genossen nützlich, die bereits Erfahrung auf diesem Gebiet haben.

Es wird auch für Anfänger nützlich sein, wie Ich stelle den Quellcode zur Verfügung, mit dem Sie sehen können, wie die Wechselwirkung mit dem Selen im Endprodukt organisiert ist.

Ich werde darüber sprechen, wie ich von Grund auf mit wenig Entwicklungserfahrung eine Plattform zum Ausführen von Tests geschrieben habe und über die Plattform selbst. Ich selbst glaube, dass sich mein Produkt als sehr effektiv erwiesen hat, was bedeutet, dass es für viele nützlich sein wird und einen Platz für Überlegungen bietet.

Vom Konzept


Der Testprozess hängt vom Informationssystem ab.

Um sich an mein Konzept zu erinnern, muss man verstehen, auf welche Systeme ich mich zuerst konzentriere - das sind Systeme, bei denen normalerweise bestimmte lineare Geschäftsprozesse als Schlüssel für die Durchführung von Regressionstests festgelegt werden.

Also ein System wie srm. Eine wichtige Geschäftseinheit sind Anbieterangebote. Die wichtigste Überlegung bei der Durchführung von Regressionstests ist die Integrität des Geschäftsprozesses.
Der Geschäftsprozess beginnt mit der Registrierung des Lieferanten im System, dann geht die Erstellung des kommerziellen Angebots weiter - er geht in die Phase der Prüfung, die von verschiedenen Arten interner Benutzer durchgeführt wird (und jeder Benutzer hat eine eindeutige Schnittstelle), bis die Entscheidung über die Prüfung des Angebots an den Lieferanten zurückgegeben wird.

Es stellt sich heraus, dass wir verschiedene Schnittstellen durchlaufen und fast immer mit verschiedenen arbeiten. In der Tat - wenn Sie es nur direkt betrachten - sieht es so aus, als würden Sie sich ein Videoband ansehen - d. H. Dies ist ein Prozess, der einen Anfang und ein Ende hat und absolut linear ist - keine Verzweigung, wenn wir einen Test schreiben, kennen wir immer das erwartete Ergebnis. Das heißt, Ich möchte sagen, dass wir bereits bei Betrachtung dieses Bildes den Schluss ziehen können, dass es unwahrscheinlich ist, dass Tests polymorph durchgeführt werden. In Anbetracht dessen habe ich beim Erstellen einer Plattform zum Ausführen von Tests als Schlüsselfaktor die Geschwindigkeit für das Schreiben von Tests festgelegt.

Die Konzepte, die ich mir selbst gesetzt habe:

  1. Autotest sollte so schnell wie möglich erstellt werden. Wenn Sie dies qualitativ erreichen, sollten andere Aspekte wie Zuverlässigkeit und Benutzerfreundlichkeit von selbst kommen.
  2. Tests müssen deklarativ deklariert werden und getrennt vom Code leben. Ich habe nicht einmal eine andere Option gesehen. Dies erhöht die Schreibgeschwindigkeit, da Wenn Sie einen vorgefertigten Interpreter haben - unsere Plattform -, müssen Sie später nichts hinzufügen, Sie müssen nicht noch einmal in den Code gehen - im Allgemeinen können Sie die fertige Plattform mithilfe der IDE vergessen. So sind Tests einfacher zu warten. In dieser Form sind sie leichter zu schreiben zu lernen, weil Entwicklungsfähigkeiten sind nicht erforderlich, sondern nur ein Verständnis der Auszeichnungssprache. In dieser Form sind sie für alle Teilnehmer des Prozesses verständlich.

Was ich zu Beginn abgelehnt habe:

  1. Wickeln Sie Ihr System NICHT in ein Testframework. Sie können die Ausführung eines Prozesses ohne Testframework starten. "Sie wollen ein Fahrrad erfinden!" - werden viele sagen. Ich denke anders. Beliebte verwendete Test-Frameworks wurden hauptsächlich zum Testen des Codes von innen erstellt, und wir werden den externen Teil des Systems von außen testen. Es ist, als hätte ich ein Rennrad und müsste den Berg im Gelände hinunterfahren (unhöflich, aber der Gedankengang spiegelt sich wider). Im Allgemeinen werden wir das Framework selbst schreiben - mit Blackjack und ... (obwohl mir bewusst ist, dass beispielsweise JUnit 5 für solche Aufgaben bereits viel besser geeignet ist).
  2. Weigerung, Wrapper für Selen zu verwenden. Tatsächlich ist die Schlüsselbibliothek selbst klein. Um zu verstehen, dass Sie 5 Prozent seiner Funktionalität nutzen müssen, während Sie es vollständig schaufeln, dauert es mehrere Stunden. Hören Sie auf, überall nach einer Möglichkeit zu suchen, weniger Code zu schreiben, und gewöhnen Sie sich an das Töpfchen. In der modernen Welt führt dieser Wunsch oft zu Absurdität und schadet fast immer der Flexibilität (ich meine die Ansätze, „weniger Code zu schreiben“ und nicht die Fälle von architektonischen Rahmenbedingungen).
  3. Eine schöne Präsentation der Ergebnisse ist nicht erforderlich. Diesen Artikel eingeführt, weil Ich bin nicht ein einziges Mal damit konfrontiert. Wenn der Autotest abgeschlossen ist, muss ich zwei Dinge wissen: das Gesamtergebnis (positiv / negativ) und ob es einen Fehler gab - wo genau. Vielleicht müssen Sie noch Statistiken führen. Alles andere in Bezug auf die Ergebnisse ist ABSOLUT nicht wesentlich. Ein schönes Design als bedeutendes Plus zu betrachten oder in der Anfangsphase Zeit mit diesem schönen Design zu verbringen - sind überflüssige Vorführungen.

Ich werde etwas mehr über den Entwicklungsstand im Unternehmen und die Bedingungen für die Erstellung des Tools sprechen, um einige Details vollständig zu klären.

Aufgrund einiger vertraulicher Umstände gebe ich das Unternehmen, in dem ich arbeite, nicht bekannt.

In unserem Unternehmen gibt es die Entwicklung bereits seit vielen Jahren, und daher sind alle Prozesse seit langem etabliert. Sie liegen jedoch weit hinter den aktuellen Trends.
Alle IT-Vertreter wissen, dass es notwendig ist, den Code mit Tests abzudecken, Skripte für Autotests zu schreiben, um die Anforderungen für zukünftige Funktionen zu koordinieren, flexible Technologien erheblich Zeit und Ressourcen zu sparen und CI, das einfach Leben kostet und vereinfacht. Aber das alles erreicht uns bisher nur langsam ...

Dies gilt auch für den Software-Qualitätskontrolldienst - alle Tests werden manuell durchgeführt, wenn Sie den Prozess „von oben“ betrachten - dies ist der „Engpass“ des gesamten Entwicklungsprozesses.

Montagebeschreibung


Die Plattform wird mit JDK 12 in Java geschrieben

Wichtige Infrastruktur-Tools - Selenium Web Driver, OJDBC

Damit die Anwendung funktioniert, muss der FireFox-Browser Version 52 auf dem PC installiert sein

Zusammensetzung der Anwendungserstellung


Bild

Mit der Anwendung werden 3 Ordner und 2 Dateien benötigt:

BuildKit- Ordner - enthält:

  • jdk12, über das die Anwendung gestartet wird (JVM);
  • geckodriver.exe - damit Selenium Web Driver mit dem FireFox-Browser funktioniert;
  • SprintAutoTest.jar - direkt die Anwendungsinstanz

• Ordner " Berichte " - Berichte werden dort gespeichert, nachdem die Anwendung den Testfall abgeschlossen hat. Es sollte auch den Ordner ErrorScreens enthalten, in dem der Screenshot im Fehlerfall gespeichert wird

TestSuite- Ordner - Webpakete, Javascripts, eine Reihe von Testfällen (das Ausfüllen dieses Ordners wird separat ausführlich besprochen)

• Datei config.properties - enthält eine Konfiguration für die Verbindung mit einer Oracle-Datenbank sowie Werte mit expliziten Erwartungen für WebDriverWait

• Starter.bat - Datei zum Starten der Anwendung (es ist möglich, die Anwendung automatisch zu starten, ohne TestCase manuell anzugeben, wenn Sie am Ende den Namen TestCase als Parameter eingeben).

Kurze Beschreibung der Anwendung


Die Anwendung kann mit oder ohne Parameter (Name TestCase) gestartet werden. In diesem Fall müssen Sie den Namen des Testfalls selbst in die Konsole eingeben.

Ein Beispiel für den allgemeinen Inhalt einer Bat-Datei, die ohne Parameter ausgeführt werden soll : Starten Sie "AutoTest Launcher"% cd% \ BuildKit \ jdk-12 \ bin \ java.exe -Xmx768M -jar - Enable-Vorschau% cd% \ BuildKit \ SprintAutoTest.jar

Beim allgemeinen Start der Anwendung werden die XML-Dateien im Verzeichnis "\ TestSuite \ TestCase" angezeigt (ohne den Inhalt der Unterordner anzuzeigen). In diesem Fall erfolgt die primäre Validierung der XML-Dateien auf die Richtigkeit der Struktur (dh alle Tags aus Sicht des XML-Markups sind korrekt), und die im Tag "testCaseName" angegebenen Namen werden verwendet, wonach der Benutzer aufgefordert wird, einen der möglichen Namen für den verfügbaren Test einzugeben Fälle. Im Falle einer fehlerhaften Eingabe werden Sie vom System aufgefordert, den Namen erneut einzugeben.

Nachdem der Name TestCase empfangen wurde, wird das interne Modell erstellt, bei dem es sich um eine Reihe von TestCase (Testskript) - WebPackage (Speicherung von Elementen) in Form von Java-Objekten handelt. Nach dem Erstellen des Modells wird TestCase (das ausführbare Objekt des Programms) direkt erstellt. In der Erstellungsphase von TestCase findet auch eine sekundäre Validierung statt. Es wird überprüft, ob sich alle in TestCase angegebenen Formulare im zugehörigen WebPackage befinden und ob sich alle in Aktion angegebenen Elemente im WebPackage auf den angegebenen Seiten befinden. (Die Struktur von TestCase und WebPackage wird unten ausführlich beschrieben.)

Nach dem Erstellen von TestCase wird das Skript direkt ausgeführt

Skriptoperationsalgorithmus (Schlüssellogik)


TestCase ist eine Sammlung von Aktionsentitäten, die wiederum eine Sammlung von Ereignisentitäten ist.

Testfall
-> Liste {Aktion}
-> Liste {Ereignis}

Wenn TestCase gestartet wird, wird die Aktion nacheinander gestartet (jede Aktion gibt ein logisches Ergebnis zurück).

Wenn die Aktion gestartet wird, wird das Ereignis nacheinander gestartet (jedes Ereignis gibt ein logisches Ergebnis zurück).

Das Ergebnis jedes Ereignisses wird gespeichert.

Dementsprechend wird der Test entweder abgeschlossen, wenn alle Aktionen erfolgreich abgeschlossen wurden oder wenn die Aktion false zurückgegeben hat.

* Absturzmechanismus

Weil Mein zu testendes System ist uralt und hat Fehler / Bugs entdeckt, die keine Fehler sind. Einige Ereignisse funktionieren nicht beim ersten Mal. Die Plattform verfügt über einen Mechanismus, der vom obigen Konzept eines streng linearen Tests abweichen kann (er ist jedoch stark typisiert). Wenn Sie solche Fehler abfangen, können Sie die Fälle zuerst wiederholen und zusätzliche Aktionen ausführen, um Aktionen wiederholen zu können

Am Ende der Anwendung wird ein Bericht generiert, der im Verzeichnis "\ Reports" gespeichert wird. Im Fehlerfall wird ein Screenshot erstellt, der unter "\ Reports \ ErrorScreens" gespeichert wird.

TestSuite-Füllung


Also die Beschreibung des Tests. Wie bereits erwähnt, ist der Hauptparameter, der zum Ausführen benötigt wird, der Name des auszuführenden Tests. Dieser Name wird in der XML-Datei im Verzeichnis „/ TestSuite / TestCase“ gespeichert. Alle Testskripte werden in diesem Verzeichnis gespeichert. Es kann eine beliebige Anzahl von ihnen geben. Der Name des Testfalls stammt nicht aus dem Dateinamen, sondern aus dem Tag „testCaseName“ in der Datei.

TestCase legt fest, was genau getan wird - d. H. Aktion. Im Verzeichnis "/ TestSuite / WebPackage" in XML-Dateien werden alle Locators gespeichert. Das heißt, Alles in bester Tradition - Aktionen werden separat gespeichert, Webformular-Locators separat.

TestCase speichert auch den WebPackage-Namen im Tag "webPackageName".

Gesamtbild ist schon da. Zum Ausführen müssen 2 XML-Dateien vorhanden sein: TestCase und WebPackage. Sie bilden einen Haufen. WebPackage ist unabhängig - der Bezeichner ist der Name im Tag "webPackageName". Dementsprechend ist hier die erste Regel: Die Namen TestCase und WebPackage müssen eindeutig sein. Das heißt, Noch einmal - tatsächlich besteht unser Test aus einer Reihe von TestCase- und WepPackage-Dateien, die durch den in TestCase angegebenen WebPackage-Namen verbunden sind. In der Praxis automatisiere ich ein System und stricke alle meine Testfälle zu einem WebPackage, in dem ich eine Menge Beschreibungen aller Formulare habe.

Die nächste Ebene der logischen Zerlegung basiert auf einem Muster wie dem Seitenobjekt.

Seitenobjekt
Page Object ist eine der nützlichsten und am häufigsten verwendeten Architekturlösungen in der Automatisierung. Dieses Entwurfsmuster hilft, die Arbeit mit einzelnen Seitenelementen zu kapseln. Das Seitenobjekt simuliert sozusagen die Seiten der zu testenden Anwendung als Objekte.

Trennung von Logik und Implementierung

Es gibt einen großen Unterschied zwischen der Testlogik (was zu überprüfen ist) und ihrer Implementierung (wie zu überprüfen ist). Ein Beispiel für ein Testszenario: "Der Benutzer gibt einen falschen Benutzernamen oder ein falsches Kennwort ein, drückt die Anmeldetaste und erhält eine Fehlermeldung." Dieses Skript beschreibt die Logik des Tests, während die Implementierung Aktionen wie das Suchen nach Eingabefeldern auf der Seite, das Ausfüllen, das Überprüfen auf Fehler usw. umfasst. Wenn sich beispielsweise die Methode zum Anzeigen einer Fehlermeldung ändert, hat dies keine Auswirkungen auf das Testskript. Sie müssen auch falsche Daten eingeben, die Anmeldetaste drücken und den Fehler überprüfen. Dies wirkt sich jedoch direkt auf die Implementierung des Tests aus. Es ist erforderlich, die Methode zu ändern, mit der die Fehlermeldung empfangen und verarbeitet wird. Durch die Trennung der Logik des Tests von seiner Implementierung werden Autotests flexibler und in der Regel einfacher zu warten.

*! Es kann nicht gesagt werden, dass dieser architektonische Ansatz vollständig angewendet wurde. Es geht nur darum, die Beschreibung des Testskripts Seite für Seite zu zerlegen. Dies hilft, Tests schneller zu schreiben und zusätzliche automatische Überprüfungen auf allen Seiten hinzuzufügen, stimuliert die korrekte Beschreibung der Locators (sodass sie auf verschiedenen Seiten nicht gleich sind) und erstellt eine "schöne" logische Struktur des Tests. Die Plattform selbst ist nach den Prinzipien der "Clean Architecture" implementiert.

Als nächstes werde ich versuchen, die Struktur von WebPackage und TestCase nicht detailliert darzustellen. Für sie habe ich ein DTD-Schema für WebPackage und XSD 1.1 für TestCase erstellt.

! WICHTIG


Durch die Beibehaltung von DTD- und XSD-Schemata wird das Konzept des schnellen Testschreibens implementiert.

Wenn Sie WebPackage und TestCase direkt schreiben, müssen Sie den XML-Editor mit integrierten Echtzeit-DTD- und XSD-Validierungsfunktionen mit automatischer Generierung von Tags verwenden, wodurch das Schreiben eines automatischen Tests weitgehend automatisiert wird (alle erforderlichen Tags werden automatisch ersetzt, Attributwerte werden in Dropdown-Listen angezeigt mögliche Werte, je nach Art des Ereignisses werden entsprechende Tags generiert) .

Wenn diese Schemata mit der XML-Datei selbst „verschraubt“ werden, können Sie die Richtigkeit der Struktur der XML-Datei vergessen, wenn Sie eine spezielle Umgebung verwenden. Meine Wahl fiel auf oXygen XLM Editor. Noch einmal - ohne ein solches Programm werden Sie die Essenz der Schreibgeschwindigkeit nicht verstehen. Idee ist dafür nicht sehr geeignet. Das "alternative" XSD 1.1-Konstrukt, das für TestCase von entscheidender Bedeutung ist, wird nicht verarbeitet.

Webpaket


WebPackaege - Eine XML-Datei, die die Elemente von Webformularen beschreibt und sich im Verzeichnis "\ TestSuite \ WebPackage" befindet. (Es können so viele Dateien vorhanden sein, wie Sie möchten. Der Name der Dateien kann beliebig sein - nur der Inhalt ist von Bedeutung.)

DTD (am Anfang des Dokuments eingefügt):
<!DOCTYPE webPackage [ <!ELEMENT webPackage (webPackageName, forms)> <!ELEMENT webPackageName (#PCDATA)> <!ELEMENT forms (form+)> <!ELEMENT form (formName, elements+)> <!ELEMENT formName (#PCDATA)> <!ELEMENT elements (element+)> <!ELEMENT element (name, locator)> <!ATTLIST element type (0|1|2|3|4|5|6|7) #REQUIRED> <!ATTLIST element alwaysVisible (0|1) #IMPLIED> <!ELEMENT name (#PCDATA)> <!ELEMENT locator (#PCDATA)> <!ATTLIST locator type (1|2) #IMPLIED> ]> 


Im Allgemeinen sieht es ungefähr aus
 <webPackage> <webPackageName>_</webPackageName> <forms> <form> <formName>______</formName> <elements> <element type="2" alwaysVisible="1"> <name>_</name> <locator type="2">.//div/form/div/div/form/table/tbody/tr/td[text()=""]/following-sibling::td/input</locator> </element> <element type="2"> <name>__</name> <locator>.//div/form/div/div/form/table/tbody/tr/td[text()=""]/following-sibling::td/input</locator> </element> ....... </elements> </form> ....... </forms> </webPackage> 


Wie bereits erwähnt, damit sich die Elemente nicht auf einem Haufen befinden, wird alles nach Webformularen zerlegt

Die Schlüsselentität ist
 <element> 

Das Element-Tag hat zwei Attribute:

  • Typ
  • immer sichtbar

Das type- Attribut ist erforderlich und gibt den Elementtyp an. Legen Sie in der Plattform den Bytetyp fest

Im Moment hat er speziell für sich selbst in der Plattform die folgenden Typen implementiert:

• 0 - hat keine funktionale Bedeutung, normalerweise eine Art Inschrift
• 1 - Taste (Taste)
• 2 - Eingabefeld
• 3 - Kontrollkästchen (CheckBox)
• 4 - Dropdown-Liste (auswählen) - nicht tatsächlich implementiert, aber einen Platz dafür gelassen
• 5 - für die Dropdown-Liste srm: Schreiben Sie den Namen, warten Sie, bis der Wert angezeigt wird - wählen Sie ihn gemäß der spezifischen xpath-Vorlage aus - den Typ speziell für mein System
• 6 - srm select - wird für typische Funktionen wie Suche usw. verwendet. - Geben Sie speziell für mein System ein

Das AlwaysVisible- Attribut - optional - zeigt an, ob ein Element immer im Formular vorhanden ist und während der Erst- / Endvalidierung von Action verwendet werden kann (d. H. Im automatischen Modus können Sie überprüfen, ob es beim Öffnen des Formulars beim Schließen alle Elemente enthält, die sich immer darauf befinden Formen, alle diese Elemente sind verschwunden)

Mögliche Werte:

  • 0 - Standardmäßig (oder wenn das Attribut nicht festgelegt ist) - Das Element befindet sich möglicherweise nicht auf der Seite (nicht validieren).
  • 1 - Das Element ist immer auf der Seite vorhanden

Ein optionales optionales Typattribut wird mit dem Locator-Tag implementiert

Mögliche Werte:

  • 1 - Suche nach einem Element anhand der ID (gib jeweils nur die ID im Locator an)
  • 2 - Standardmäßig (oder wenn das Attribut nicht festgelegt ist) - Suche auf xpath - Es wird empfohlen, nur auf xpath zu suchen, da Diese Methode kombiniert fast alle Vorteile des Restes und ist universell

Testfall


TestCase - Die XML-Datei, die das Testskript direkt beschreibt, befindet sich im Verzeichnis "\ TestSuite \ TestCase" (es können beliebig viele Dateien vorhanden sein. Der Name der Dateien kann beliebig sein - nur der Inhalt ist von Bedeutung).

XSD-Schaltung:
 <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <xs:element name="testCase"> <xs:complexType> <xs:sequence> <xs:element name="testCaseName" type="xs:string"/> <xs:element name="webPackageName" type="xs:string"/> <xs:element name="actions" type="actionsType"/> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="actionsType"> <xs:sequence> <xs:element name="action" type="actionType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="actionType"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="orderNumber" type="xs:positiveInteger"/> <xs:element name="runConfiguration" type="runConfigurationType"/> </xs:sequence> </xs:complexType> <xs:complexType name="runConfigurationType"> <xs:sequence> <xs:element name="formName" type="xs:string"/> <xs:element name="repeatsOnError" type="xs:positiveInteger" minOccurs="0"/> <xs:element name="events" type="eventsType"/> <xs:element name="exceptionBlock" type="eventsType" minOccurs="0"/> </xs:sequence> <xs:attribute name="openValidation" use="required"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="closeValidation" use="required"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> <xs:complexType name="eventBaseType"> <xs:sequence> <xs:element name="orderNumber" type="xs:positiveInteger"/> </xs:sequence> <xs:attribute name="type" use="required"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="goToURL"/> <xs:enumeration value="checkElementsVisibility"/> <xs:enumeration value="checkElementsInVisibility"/> <xs:enumeration value="fillingFields"/> <xs:enumeration value="clickElement"/> <xs:enumeration value="dbUpdate"/> <xs:enumeration value="wait"/> <xs:enumeration value="scrollDown"/> <xs:enumeration value="userInput"/> <xs:enumeration value="checkInputValues"/> <xs:enumeration value="checkQueryResultWithUtilityValue"/> <xs:enumeration value="checkFieldsPresenceByQueryResult"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="invertResult" use="optional" default="0"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="hasExceptionBlock" use="optional" default="0"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="0"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> <xs:complexType name="eventsType"> <xs:sequence> <xs:element name="event" type="eventBaseType" maxOccurs="unbounded"> <xs:alternative test="@type='goToURL'" type="eventGoToURL"/> <xs:alternative test="@type='checkElementsVisibility'" type="eventCheckElementsVisibility"/> <xs:alternative test="@type='checkElementsInVisibility'" type="eventCheckElementsVisibility"/> <xs:alternative test="@type='fillingFields'" type="eventFillingFields"/> <xs:alternative test="@type='checkInputValues'" type="eventFillingFields"/> <xs:alternative test="@type='clickElement'" type="eventClickElement"/> <xs:alternative test="@TYPE='dbUpdate'" type="eventRequest"/> <xs:alternative test="@type='wait'" type="utilityValueInteger"/> <xs:alternative test="@type='scrollDown'" type="eventClickElement"/> <xs:alternative test="@type='userInput'" type="eventClickElement"/> <xs:alternative test="@type='checkQueryResultWithUtilityValue'" type="eventRequestWithValue"/> <xs:alternative test="@type='checkFieldsPresenceByQueryResult'" type="eventRequestWithValue"/> </xs:element> </xs:sequence> </xs:complexType> <!--   EVENTS --> <xs:complexType name="eventGoToURL"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="url" type="xs:anyURI"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventCheckElementsVisibility"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="fields" type="fieldType"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventFillingFields"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="fields" type="fieldTypeWithValue"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventClickElement"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="elementName" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventRequest"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="dbRequest" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="utilityValueInteger"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="utilityValue" type="xs:positiveInteger"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="eventRequestWithValue"> <xs:complexContent> <xs:extension base="eventBaseType"> <xs:sequence> <xs:element name="dbRequest" type="xs:string"/> <xs:element name="utilityValue" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <!--   EVENTS --> <xs:complexType name="fieldType"> <xs:sequence> <xs:element name="field" maxOccurs="unbounded"> <xs:complexType> <xs:choice> <xs:element name="element" type="xs:string"/> <xs:element name="xpath" type="xs:string"/> </xs:choice> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="fieldTypeWithValue"> <xs:sequence> <xs:element name="field" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="element" type="xs:string"/> <xs:element name="value" type="valueType"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="valueType"> <xs:complexContent> <xs:extension base="xs:anyType"> <xs:attribute name="type" use="optional" default="1"> <xs:simpleType> <xs:restriction base="xs:byte"> <xs:enumeration value="1"/> <xs:enumeration value="2"/> <xs:enumeration value="3"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:extension> </xs:complexContent> </xs:complexType> </xs:schema> 


Gesamtansicht:
 <!DOCTYPE testCase SYSTEM "./TestSuite/TestCase/entities.dtd" []> <testCase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="testShema.xsd"> <testCaseName>__testCase</testCaseName> <webPackageName>_webPackage__webPackageName</webPackageName> <actions> <action> <name>          </name> <orderNumber>10</orderNumber> <runConfiguration openValidation="1" closeValidation="1"> <formName>______</formName> <events> <event type="goToURL"> <orderNumber>10</orderNumber> <url>&srmURL;</url> </event> ....... </events> </runConfiguration> </action> ....... </actions> </testCase> 


Hier in dieser Zeile können Sie sehen, wie Sie das xsd-Schema so befestigen, dass der XML-Editor es sieht:

 <testCase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="testShema.xsd"> 

In TestCase verwende ich auch DTD-Entitäten, die separat im selben Verzeichnis gespeichert sind - eine Datei mit der Erweiterung .dtd. Darin speichere ich fast alle Datenkonstanten. Ich habe die Logik auch so aufgebaut, dass zum Starten eines neuen Tests und während des gesamten Tests neue eindeutige Entitäten erstellt und ein neues Raumschiff registriert wurden. Es reichte aus, eine Ziffer in dieser Datei zu ändern.

Die Struktur ist sehr einfach - ich werde ein Beispiel geben:
 <?xml version="1.0" encoding="UTF-8"?> <!ENTITY mainNumber '040'> <!ENTITY mail '@mail.ru'> <!ENTITY srmURL 'https://srm-test.ru'> 


Solche Konstanten werden wie folgt in den Tag-Wert eingefügt:

 <url>&srmURL;</url> 

- kann kombiniert werden.

! Empfehlung - Wenn Sie testCase schreiben, sollten Sie diese DTD-Entitäten im Dokument angeben und, nachdem alles stabil funktioniert hat, in eine separate Datei übertragen. Mein XML-Editor hat Probleme damit - er kann DTD nicht finden und berücksichtigt XSD nicht, daher empfehle ich dies

testCase

testCase - Das übergeordnete Tag enthält:

  • testCaseName - Der Name unseres Testfalls. Dieser Parameter wird an die Anwendungseingabe übergeben
  • webPackageName - Der Name von WebPackage, der in webPackageName angegeben ist (siehe Abschnitt oben zu WebPackage).
  • Aktionen - Aktionsentitätscontainer

Aktion

Enthält:

  • name - name - es wird empfohlen, den Formularnamen und die Schlüsselaktionen anzugeben - was und warum
  • orderNumber - Seriennummer - Parameter, der für die Sortieraktion erforderlich ist (eingeführt aufgrund der Tatsache, dass beim Parsen von XML in Java mit bestimmten Tools das Parsen in einer Umgebung mit mehreren Threads durchgeführt werden kann, sodass die Reihenfolge fortgesetzt werden kann) - Wenn Sie die nächste Aktion angeben, können Sie springen - d.h. Beim Sortieren ist es nur „mehr / weniger“ wichtig, und so ist es möglich, Aktionen zwischen den bereits beschriebenen zu liefern, ohne die gesamte Nummerierung ändern zu müssen
  • runConfiguration - die tatsächliche Beschreibung dessen, was als Teil der Aktion geschehen wird

runConfiguration

Enthält:

  • openValidation- Attribut - optional, Standard ist "0"
    • 0 - Führen Sie keine erste Formularvalidierung durch
    • 1 - erste Formularvalidierung
  • Attribut closeValidation - optional, Standard ist "0"
    • 0 - Führen Sie keine endgültige Formularvalidierung durch
    • 1 - endgültige Formularvalidierung
  • formName - der Name des Formulars, in dem die Aktionen ausgeführt werden - der formName-Wert von WebPackage
  • repeatsOnError - optional, gibt an, wie viele Wiederholungen im Fehlerfall durchgeführt werden sollen
  • Ereignisse - Ereignisentitätscontainer
  • exceptionBlock - optional - Ein Container mit Ereignisentitäten, die im Fehlerfall ausgeführt werden

Veranstaltung

Minimale strukturelle Einheit - Diese Entität zeigt an, welche Aktionen ausgeführt werden

Jedes Ereignis ist etwas Besonderes und kann eindeutige Tags und Attribute haben.

Der Basistyp enthält:

  • Typattribut - Gibt den Elementtyp an
  • Das Attribut hasExceptionBlock ist ein optionales Attribut. Standardmäßig ist "0" erforderlich, um den Fehlermechanismus zu implementieren. Das Attribut gibt an, dass bei diesem Ereignis ein Fehler erwartet werden kann
    • 0 - kein Fehler erwartet
    • 1 - Ein möglicher Fehler wird bei der Aktion erwartet
  • Attribut invertResult - optionales Attribut, standardmäßig "0" - das Attribut gibt an, dass das Ergebnis des Ereignisses geändert werden muss
    • 0 - Hinterlasse das Ergebnis des Ereignisses
    • 1 - Ändern Sie das Ergebnis des Ereignisses in das Gegenteil

*! Ein Mechanismus zur Beschreibung des erwarteten Fehlers
Lassen Sie mich Ihnen ein triviales Beispiel geben, wo ich es zum ersten Mal verwendet habe und was zu tun ist, damit es funktioniert.

Fall: Captcha-Eingabe. Im Moment konnte ich sozusagen eine Überprüfung auf Roboterabstürze nicht automatisieren - sie schreiben mir keinen Captcha-Testdienst (aber es ist einfacher für mich, ein neuronales Netzwerk zur Erkennung zu erstellen))) Wir können also beim Eingeben einen Fehler machen. In diesem Fall mache ich ein Steuerungsereignis, in dem ich überprüfe, ob wir kein Element haben - eine Benachrichtigung über einen falschen Steuercode, ich habe das Attribut hasExceptionBlock darauf gesetzt. Zuvor habe ich um eine Aktion gebeten, dass wir mehrere Wiederholungen haben können (5), und schließlich habe ich exceptionBlock registriert, in dem ich geschrieben habe, dass ich die Exit-Taste für die Benachrichtigung drücken muss, und dann wurde die Aktion wiederholt.

Beispiele aus meinem Kontext.

So habe ich die Veranstaltung registriert:

 <event type="checkElementsInVisibility" hasExceptionBlock="1"> <orderNumber>57</orderNumber> <fields> <field> <element>___</element> </field> </fields> </event> 

Und hier AusnahmeBlock nach Ereignissen

  <exceptionBlock> <event type="clickElement"> <orderNumber>10</orderNumber> <elementName>_____</elementName> </event> </exceptionBlock> 

Und ja, Aktionen auf einer Seite können in mehrere Aktionen zerlegt werden.

+ Wer hat 2 Parameter in der Konfiguration bemerkt: defaultTimeOutsForWebDriverWait, lowTimeOutsForWebDriverWait. Deshalb sind sie es auch. Weil Ich habe den gesamten Webtreiber in einem Singleton, und ich wollte nicht jedes Mal ein neues WebDriverWait erstellen, dann habe ich 1 schnelles und es ist im Fehlerfall (na ja, oder wenn Sie nur hasExceptionBlock = "1" setzen, dann wird es mit weniger Zeit dumm sein explizites Warten) - Nun, Sie müssen zustimmen, warten Sie eine Minute, um sicherzustellen, dass die Nachricht nicht vollständig veröffentlicht wurde, und erstellen Sie jedes Mal ein neues WebDriverWait. Nun, diese Situation, auf der die Seite nicht klebt, erfordert eine Krücke - ich habe mich dazu entschlossen.

Ereignistypen


Hier werde ich einen minimalen Satz meiner Ereignisse angeben, z. B. einen Scout-Satz, mit dem ich fast alles auf meinem System testen kann.

Und jetzt ist es für den Code reibungslos zu verstehen, was ein Ereignis ist und wie es aufgebaut ist. Der Code implementiert im Wesentlichen das Framework. Ich habe 2 Klassen - DataBaseWrapper und SeleniumWrapper. In diesen Klassen wird die Interaktion mit Infrastrukturkomponenten beschrieben und auch die Plattformfunktionen werden berücksichtigt. Ich werde die Schnittstelle geben, die SeleniumWrapper implementiert

 package logic.selenium; import models.ElementWithStringValue; import models.webpackage.Element; import org.openqa.selenium.WebElement; public interface SeleniumService { void initialization(boolean webDriverWait); void nacigateTo(String url); void refreshPage(); boolean checkElementNotPresent(Element element); WebElement findSingleVisibleElement(Element element); WebElement findSingleElementInDOM(Element element); void enterSingleValuesToWebField(ElementWithStringValue element); void click(Element element); String getInputValue(Element element); Object jsReturnsValue(String jsFunction); //Actions actions void doubleClick(Element element); void moveMouseToElement(Element element); void pressKey(CharSequence charSequence); void getScreenShot(String storage); } 

Es beschreibt alle Merkmale von Selen- und Overlay-Plattformchips - tatsächlich ist der Hauptchip die Methode "enterSingleValuesToWebField". Denken Sie daran, dass wir in WebPackage den Elementtyp angeben. Hier erfahren Sie, wie Sie beim Ausfüllen der Felder auf diesen Typ reagieren können. Wir schreiben 1 mal und vergessen. Die obige Methode sollte zunächst für sich selbst korrigiert werden. Beispielsweise sind die derzeit gültigen Typen 5 und 6 nur für mein System geeignet. Wenn Sie so etwas wie einen Filter haben und viel filtern müssen und dies typisch ist (in Ihrer Webanwendung), müssen Sie zunächst die Maus über das Feld bewegen, warten, bis einige Felder angezeigt werden, zu einigen wechseln, warten Es gibt etwas, dann gehen Sie dorthin und geben Sie ein ... Verschreiben Sie den Wirkungsmechanismus 1 Mal dumm, geben Sie diesem alles in der Schalterstruktur einen eindeutigen Typ - stören Sie sich nicht weiter - erhalten Sie eine polymorphe Methode für alle ähnlichen Anwendungsfilter.

Im Paket "package logo.testcase.events" gibt es also eine abstrakte Klasse, die die allgemeinen Aktionen des Ereignisses beschreibt. Um Ihr eigenes eindeutiges Ereignis zu erstellen, müssen Sie eine neue Klasse erstellen, von dieser abstrakten Klasse erben und DataBaseService und SeleniumService bereits im Kit haben. Anschließend bestimmen Sie, welche Daten Sie benötigen und was Sie damit tun sollen. Irgendwie so. Nun, und dementsprechend müssen Sie nach dem Erstellen eines neuen Ereignisses die TestCaseActionFactory-Factory-Klasse und, wenn möglich, das XSD-Schema beenden. Wenn ein neues Attribut hinzugefügt wird, ändern Sie das Modell selbst. In der Tat ist es sehr einfach und schnell.

Also ein Scout-Set.

goToURL - normalerweise die erste Aktion - klicken Sie auf den angegebenen Link

Ein Beispiel:
 <event type="goToURL"> <orderNumber>10</orderNumber> <url>testURL</url> </event> 


fillFields - Füllen bestimmter Elemente

Spezielle Tags:

  • Felder - Entity Container Fiel
    • Feld - enthält das Element-Tag
      • Element - Gibt den Namen des Elements aus webPackage an
      • value - welcher Wert angegeben werden soll, hat ein optionales Typattribut (wenn das Element ein Kontrollkästchen ist, wird einer der Werte angezeigt: "check" oder "uncheck")

  • Typattribut - Gibt an, wie der Wert übernommen werden soll. Optional ist der Standardwert "1".
    • 1 - der angegebene Wert wird übernommen
    • 2 - In diesem Fall wird die angegebene JS-Funktion aus dem Verzeichnis "\ TestSuite \ JS" ausgeführt! WICHTIG - der Name der txt-Datei wird ohne ".txt" angegeben (und bisher habe ich Anwendungen für js-Funktionen bisher nur in dieser Form gefunden - ich verwende sie an einer Stelle, um ein zufälliges Gasthaus zu generieren, aber das Spektrum möglicher Anwendungen ist breit).
    • 3 - In diesem Fall wird die Abfrage in der Datenbank als Wert angegeben, und das Programm ersetzt das erste Ergebnis dieser Abfrage

Ein Beispiel:
 <event type="fillingFields"> <orderNumber>10</orderNumber> <fields> <field> <element>test</element> <value>test</value> </field> </fields> </event> 


checkElementsVisibility - Überprüft, ob die angegebenen Elemente im Formular vorhanden sind (nämlich sichtbar und nicht nur im DOM). Im Feldattribut kann entweder ein Element aus WebPackage oder direkt xpath angegeben werden

Ein Beispiel:
 <event type="checkElementsVisibility"> <orderNumber>10</orderNumber> <fields> <field> <element>test</element> </field> <field> <xpath>test</xpath> </field> </fields> </event> 


checkElementsInVisibility - ähnlich wie checkElementsVisibility, aber umgekehrt

clickElement - Klicken Sie auf das angegebene Element

Ein Beispiel:
 <event type="clickElement"> <orderNumber>10</orderNumber> <elementName>test</elementName> </event> 


checkInputValues - Überprüfen Sie die eingegebenen Werte

Ein Beispiel:
 <event type="checkInputValues"> <orderNumber>10</orderNumber> <fields> <field> <element>test</element> <value>test</value> </field> </fields> </event> 


dbUpdate - Führen Sie ein Update in der Datenbank durch ( oXygen reagiert seltsamerweise auf 1 Ereignis vom Typ dbUpdate - Ich weiß nicht, was ich damit machen soll, und ich verstehe nicht warum ).

Ein Beispiel:
 <event type="dbUpdate"> <orderNumber>10</orderNumber> <dbRequest>update - </dbRequest> </event> 


CheckQueryResultWithUtilityValue - Überprüfen Sie den vom Benutzer eingegebenen Wert mit dem Wert aus der Datenbank

Ein Beispiel:
 <event type="checkQueryResultWithUtilityValue"> <orderNumber>10</orderNumber> <dbRequest>select ...</dbRequest> <utilityValue>test</utilityValue> </event> 


checkFieldsPresenceByQueryResult - Überprüfen Sie das Vorhandensein von Elementen im Formular anhand von xpath by pattern. Wenn das gewünschte Muster nicht angegeben ist, erfolgt die Suche gemäß dem Muster .//* [text () [enthält (normalize-space (.), "$")]], Wobei anstelle von "$" ein Wert aus der Datenbank angezeigt wird. Wenn Sie Ihr eigenes Muster beschreiben, sollten Sie an der Stelle, an der Sie den Wert aus der Datenbank ablegen möchten, "$" angeben. In meinem System gibt es sogenannte Gitter, in denen es Werte gibt, die normalerweise aus einer bestimmten Sicht gebildet werden. Dieses Ereignis, um solche Gitter zu testen

Ein Beispiel:
 <event type="checkFieldsPresenceByQueryResult"> <orderNumber>10</orderNumber> <dbRequest>test</dbRequest> <utilityValue></utilityValue> </event> 


Warten Sie - alles ist einfach - warten Sie auf die angegebene Anzahl von Millisekunden. Obwohl dies als Krücke angesehen wird, werde ich leider mit Sicherheit sagen - manchmal ist es unmöglich, darauf zu verzichten

Ein Beispiel:
 <event type="wait"> <orderNumber>10</orderNumber> <utilityValue>1000</utilityValue> </event> 


scrollDown - Scrollen Sie vom angegebenen Element nach unten. Dies geschieht folgendermaßen: Es klickt auf das angegebene Element und drückt die Taste „PgDn“. In meinen Fällen, in denen ich nach unten scrollen musste, funktioniert es einwandfrei:

Ein Beispiel:
 <event type="scrollDown"> <orderNumber>10</orderNumber> <elementName>test</elementName> </event> 


userInput - Geben Sie einen Wert in das angegebene Element ein. Das einzige halbautomatische Gerät in meiner Automatisierung, das nur für Captcha verwendet wird. Das Element, in das der Wert eingegeben werden soll, wird angezeigt. Der Wert wird im Popup-Dialogfeld eingegeben.

Ein Beispiel:
 <event type="userInput"> <orderNumber>10</orderNumber> <elementName>capch_input</elementName> </event> 


Über den Code


Also habe ich versucht, die Plattform gemäß den Prinzipien von Onkel Bobs Clean Architecture zu gestalten.

Pakete:

Anwendung - Initialisierung und Start + Konfigurationen und Bericht (schimpfe nicht mit mir für die Berichtsklasse - das macht es so schnell wie möglich, dann so schnell wie möglich)

Logik - die Schlüssellogik + Dienste von Selen und DB. Es gibt Ereignisse.

Modelle - POJO in XML und alle Hilfsobjektklassen

utils - singleton für selen und db

Um den Code auszuführen, müssen Sie jdk 12 herunterladen und überall angeben, damit sich die Chips einschalten. In Idea erfolgt dies über Projektstruktur -> Module und Projekt. Vergessen Sie auch nicht den Maven-Läufer.Und wenn Sie in der Bat-Datei beginnen, fügen Sie --enable-Preview hinzu. Ein Beispiel war.

Nun, damit alles beginnt, müssen Sie nach dem JDK den ojdbc-Treiber herunterladen und den dzharnik im Verzeichnis "SprintAutoTest \ src \ lib" ablegen. Ich biete es nicht an, weil Im Moment ist bei Oracle dort alles ernst - zum Herunterladen muss man sich registrieren, aber ich bin sicher, dass jeder irgendwie damit fertig wird (stellen Sie sicher, dass alle Ordner erstellt wurden, sonst wird der Bericht nicht gespeichert).

Zusammenfassung


Wir haben also einen Teststarter, der Tests schreibt, für die es sehr schnell geht. Während der Arbeitswoche konnte ich 1,5 Stunden manuelle Arbeit automatisieren, die vom Roboter in 5-6 Minuten ausgeführt wird. Dies sind ungefähr 3700 Zeilen des verketteten Testfalls und 830 beschriebene Elemente (mehr als 4800 Zeilen). Die Zahlen sind grob und werden daher nicht gemessen, aber diejenigen, die sich mit Automatisierung beschäftigen, sollten verstehen, dass dies ein sehr hoher Indikator ist, insbesondere für roboterunfreundliche Systeme. Gleichzeitig teste ich alles - Geschäftslogik, während ich einige negative Tests auf die Richtigkeit der ausgefüllten Attribute durchführe, und als Bonus überprüfe ich jedes Webformular, bei dem ich nicht faul bin, und beschreibe alle Funktions- und Schlüsselelemente, die unabhängig voneinander benötigt werden ich oder nicht (Ein kleiner Exkurs - Ich benutze closeValidation hauptsächlich nur, wenn ich einen Test schreibe.Wenn es stabil ist und klar ist, dass sich die Locators nicht überschneiden, schalte ich es für alle Aktionen aus, damit der Prozess schneller verläuft.

Auf den ersten Blick scheint es viele XML-Zeilen zu geben, aber in der Praxis werden sie halbautomatisch generiert, und ein Fehler kann nur in direkt eingegebenen Parametern gemacht werden (da wir tatsächlich zwei Validierungsstufen haben - die erste ist die XML des Schemas, die zweite Überprüfung des Vorhandenseins der angegebenen Formulare und Elemente zu Beginn von TestCase).

Von den Minuspunkten gibt es keine klaren Grenzen der Tests. Als solche fehlen sie und Sie können mir die Schuld geben, dass dies nur ein Makro-Launcher ist, keine Tests. Ich sage Folgendes:

In der Plattform werden Tests konzeptionell aus verschiedenen Blickwinkeln in mehrere Abstraktionsebenen unterteilt:

  • + — « » + — ( – .. -)
  • ( action — event c + )
  • , , – -. , – . , . , – ,
  • Jede Aktion auf der Seite ist ein Komponententest (Rückgabe eines einzelnen Ergebnisses wahr oder falsch)

Wenn Sie meinen Ansatz mit etwas vergleichen, sind die Minuspunkte von beispielsweise der beliebten Gurke und das Konzept von BDD für mich wichtiger (genau dann, wenn wir diejenigen wie mein System testen):

  • Wir können die Durchführung von Tests beim Testen einer instabilen Webanwendung nicht garantieren. Das heißt, In meinem Fall können wir für die meisten Tests keine Garantie für deren Ausführung übernehmen, und sie fallen auf das „Wann“, was meiner Meinung nach im Allgemeinen nicht akzeptabel ist, wenn wir das Testen mit einer Reihe von Tests beschreiben.
  • Nun und überall wird dieses ohnehin enorme Beispiel mit einem Login gegeben. Ja, trotz all meiner Praxis ist es genau im Login, dass es nie Fehler gegeben hat (obwohl es auf jeden Fall abgedeckt werden sollte, das ist sicher). Und das Beispiel ist gut, aber für den Rest der Tests müssen Sie endlose Krücken aus Given und When formen - in dem System, das ich für echte Tests angegeben habe, werden 99% benötigt, um die Zwischenbedingungen zu beschreiben, während wir zu diesem Test selbst kommen - viel Ärger, ein wenig Essenz und auch klettere in den Code.

Von dem, was ich tun möchte, um darüber nachzudenken, aber meine Hände haben noch nicht erreicht:

  • Nicht einen, sondern mehrere Tests nacheinander in einem Lauf ausführen
  • Ich denke, Entitäten werden gepumpt, damit sie aufgrund eines neuen Tests Werte generieren können, und sie wurden während der Ausführung gespeichert
  • Zentralisierte Versionskontrolle durchführen. Nicht nur git, sondern um anzugeben, welche Version des Tests ausgeführt werden soll, oder auch ein intelligentes Modul, das versteht, welche Version relevant ist, welche noch nicht
  • Wie gesagt, um einen neuen Test mit neuen Werten zu starten, muss ich eine Ziffer ändern, sozusagen automatisieren und ein intelligentes Modul dafür erstellen
  • Obwohl es mich nicht sonderlich stört, dass ich alle Locators an einem Ort gespeichert habe, müsste ich auf eine gute Weise eine noch benutzerfreundlichere Struktur für ihre Speicherung erstellen
  • habe mich nicht mit Selenserver beschäftigt. Ich denke, es lohnt sich, darüber nachzudenken sowie über die Möglichkeit einer weiteren Anpassung an CI, Team City usw.

Nun, das ist alles. Ich füge einen Verweis auf github hinzu: Quellcodes .

Ich werde mich sehr über konstruktive Kritik freuen, ich hoffe, dieses Projekt wird wirklich nützlich sein.

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


All Articles