Erstellen einer grundlegenden Testklasse für Selentests und Initialisieren über JUnit RuleChain

Mit diesem Artikel setzen wir eine Reihe von Veröffentlichungen fort, in denen erläutert wird, wie wir den Prozess des manuellen Testens (im Folgenden als Autotests bezeichnet) eines großen Informationssystems (im Folgenden als Systeme bezeichnet) in einem der wichtigsten LANIT-Projekte automatisiert haben und was daraus entstanden ist.

Wie kann eine Klassenhierarchie effizient organisiert werden? Wie verteile ich Pakete im Projektbaum? Wie können Sie sicherstellen, dass Sie Zusammenführungskonflikte mit einem Team von 10 Personen vergessen? Diese Themen stehen immer am Anfang einer neuen Entwicklung und sie haben nie genug Zeit.

Quelle

In diesem Artikel beschreiben wir die Struktur von Klassen und die Organisation von Code, die es uns ermöglichten, mit wenig Aufwand mehr als eineinhalbtausend End-2-End-UI-Tests basierend auf Junit und Selen für ein großes System von Bundesbedeutung zu entwickeln. Darüber hinaus unterstützen wir es erfolgreich und entwickeln bestehende Szenarien ständig weiter.

Hier finden Sie eine praktische Beschreibung der Struktur der Hierarchie der Basisklassen von Autotests, die Aufteilung des Projekts nach dem Funktionsmodell Java-Pakete und Beispielvorlagen von realen Klassen.

Der Artikel ist für alle Entwickler nützlich, die Selbsttests auf der Basis von Selen entwickeln.

Dieser Artikel ist Teil einer allgemeinen Veröffentlichung, in der beschrieben wurde, wie ein kleines Team den Automatisierungsprozess für das Testen der Benutzeroberfläche erstellte und ein auf Junit und Selenium basierendes Framework dafür entwickelte.

Vorherige Teile:


Basisklassenimplementierung für alle Tests und JUnit RuleChain


Das Konzept der Entwicklung von Autotests, wie es in einem früheren Artikel ( Teil 2, Technisch, Architektur und technischer Stapel, Implementierungsdetails und technische Überraschungen ) gezeigt wurde, basiert auf der Idee eines Frameworks, in dem eine Reihe von Systemfunktionen für alle Autotests bereitgestellt wird - sie sind nahtlos integriert und ermöglichen Entwicklern Autotests konzentrieren sich auf spezifische Fragen der Geschäftsimplementierung von Testklassen.

Das Framework enthält die folgenden Funktionsblöcke:

  • Regeln - Initialisierung und Finalisierung von Testinfrastrukturkomponenten als Initialisierung von WebDriver und Empfang eines Videotests. Im Folgenden näher beschrieben;
  • WebDriverHandlers - Hilfsfunktionen für die Arbeit mit dem Webtreiber als Ausführung von Java Script oder Zugriff auf Browser-Protokolle. Implementiert als eine Reihe statischer zustandsloser Methoden;
  • WebElements ist eine Bibliothek mit typischen Webelementen oder deren Gruppen, die die erforderliche funktionsübergreifende Funktionalität und das typische Verhalten enthält. In unserem Fall beinhaltet diese Funktionalität eine mögliche Überprüfung des Abschlusses von asynchronen Vorgängen auf der Seite des Webbrowsers. Implementiert als Erweiterung von Webelementen aus den Bibliotheken Selenium und Selenide.

Initialisierung der Testumgebung. Regeln


Die Schlüsselklasse für alle Testklassen ist BaseTest, von der alle Testklassen geerbt werden. Die BaseTest-Klasse definiert den Junit-Test-Runner und die verwendete RuleChain, wie unten gezeigt. Der Zugriff von angewandten Testklassen auf Funktionen, die von Regelklassen bereitgestellt werden, erfolgt über die statischen Methoden von Regelklassen.

Der BaseTest-Beispielcode wird im nächsten Feld dargestellt.

@RunWith(FilterTestRunner.class) public class BaseTest { private TemporaryFolder downloadDirRule                                                                  = new TemporaryFolder(getSomething().getWorkingDir());      @Rule     public RuleChain rules = RuleChain             .outerRule(new Timeout(TimeoutEnum.GLOBAL_TEST_TIMEOUT.value(),                                                                       TimeUnit.SECONDS))             .around(new TestLogger())             .around(new StandStateChecker())             .around(new WaitForAngularCreator())             .around(downloadDirRule)             .around(new DownloaderCreator(downloadDirRule))             .around(new EnvironmentSaver())             .around(new SessionVideoHandler())             .around(new DriverCreator(downloadDirRule))             .around(new BrowserLogCatcher(downloadDirRule))             .around(new ScreenShooter())             .around(new AttachmentFileSaver())             .around(new FailClassifier())             .around(new PendingRequestsCatcher());     //            final protected SomeObject getSomething() {         return Something.getData();    }    … } 

FilterTestRunner.class - eine Erweiterung von BlockJUnit4ClassRunner, die das Filtern der Zusammensetzung ausführbarer Tests basierend auf regulären Ausdrücken nach dem Wert der speziellen Filter- Annotation (value = "some_string_and_tag") ermöglicht. Die Implementierung ist unten angegeben.

org.junit.rules.Timeout - wird verwendet, um die maximale Fortsetzung von Tests zu begrenzen. Es sollte zuerst installiert werden, da es den Test in einem neuen Zweig startet.

TestLogger ist eine Klasse, mit der der Test Ereignisse im json-Format für die Verwendung in ELK-Analysen protokollieren kann. Bereichert Ereignisse mit Testdaten aus org.junit.runner.Description. Zusätzlich generiert es automatisch Ereignisse für ELK im json-Format, um den Test mit seiner Dauer und seinem Ergebnis zu starten und zu beenden

StandStateChecker ist eine Klasse, die die Verfügbarkeit der Webschnittstelle des Zielstands prüft, BEVOR der Webtreiber initialisiert wird. Bietet eine schnelle Überprüfung, ob der Stand grundsätzlich verfügbar ist.

WaitForAngularCreator - eine Klasse, die den Webtreiberhandler initialisiert, um den Abschluss asynchroner Winkeloperationen zu steuern. Es wird verwendet, um "spezielle" Tests mit langen synchronen Aufrufen anzupassen.

org.junit.rules.TemporaryFolder - Dient zum Festlegen eines eindeutigen temporären Ordners zum Speichern von Dateien zum Hoch- und Herunterladen von Dateien über einen Webbrowser.

DownloaderCreator ist eine Klasse, die Upload-Vorgänge in ein temporäres Verzeichnis von Dateien unterstützt, die vom Browser heruntergeladen und über die Selenoid-Videofunktion aufgezeichnet wurden.

EnvironmentSaver - Eine Klasse, die dem Allure-Bericht allgemeine Informationen zur Testumgebung hinzufügt.  

SessionVideoHandler - eine Klasse, die gegebenenfalls eine Videotestdatei hochlädt und Allure auf den Bericht anwendet.

DriverCreator ist eine Klasse, die WebDriver (die wichtigste Klasse für Tests) abhängig von den eingestellten Parametern initialisiert - local, solenoid oder ggr-selenoid. Darüber hinaus führt die Klasse die für unsere Tests erforderlichen Java-Skripts aus. Alle Regeln, die auf den Webtreiber zugreifen, müssen nach dieser Klasse initialisiert werden.

BrowserLogCatcher - eine Klasse, die schwerwiegende Nachrichten aus dem Browserprotokoll liest, sie in ELK (TestLogger) protokolliert und auf den Allure-Bericht anwendet.

ScreenShooter - Eine Klasse, die bei nicht erfolgreichen Tests einen Screenshot des Browserbildschirms erstellt und als WebDriverRunner.getWebDriver () auf den Bericht anwendet. GetScreenshotAs (OutputType.BYTES)

AttachmentFileSaver - eine Klasse, mit der Sie dem Allure-Bericht eine Reihe beliebiger Dateien hinzufügen können, die für die Geschäftslogik der Tests erforderlich sind. Wird zum Anhängen von Dateien verwendet, die in das System hochgeladen oder von dort heruntergeladen wurden.

FailClassifier ist eine spezielle Klasse, die im Falle eines Testabsturzes ermittelt, ob dieser Absturz durch Infrastrukturprobleme verursacht wurde. Überprüft, ob auf dem Bildschirm (nach einem Absturz) spezielle modale Fenster vom Typ "Systemfehler Nr. XXXXXXXXXX" sowie Systemmeldungen vom Typ 404 und dergleichen vorhanden sind. Ermöglicht die Aufteilung abgelaufener Tests in Abstürze (gemäß Szenario) oder Systemprobleme. Funktioniert mit der Erweiterung org.junit.rules.TestWatcher. # Methode fehlgeschlagen.

PendingRequestsCatcher ist eine weitere spezielle Klasse, die versucht, weiter zu klassifizieren, ob der Absturz durch unvollständige, hängengebliebene oder sehr lange Pausen zwischen dem Angular- und dem Web-Frontend verursacht wurde. Neben Funktionstests können problematische und einfrierende Ruhezeiten unter hoher Belastung sowie die Gesamtstabilität der Freisetzung identifiziert werden. Zu diesem Zweck protokolliert die Klasse in ELK alle Ereignisse mit eingefrorenen Restanforderungen, die sie empfängt, indem sie spezielle Js im Browser über einen offenen Webtreiber startet.

Implementierungsvorlage für Testklassen


 package autotest.test.<sub-system>; @Feature("     TMS") @Story("    TMS") @Owner("       ") @TmsLink("    .   ") public class <   >_Test extends BaseTest { /** *           **/    Login orgTest; /**         **/    Login loginStep1;    ...    Login loginStepN;    /** *   -      -   * ...         **/      /** *    *              *    Utils.allure.message("     -", business_object) *     null,             . *             preconditions  actions    *  Utils.allure.message("      ", documentNumber) **/ @Step("  ") private void init(Login login) {    some_business_object = //         login        Utils.allure.message("     -", some_business_object)                           // ...             /**     */        loginStep1 = LoginFactory.get(_Some_Login_);    ...    loginStepN = LoginFactory.get(_Some_Login_); }    /** *       **/    @Test    @Filter("       JUnit")    @DisplayName("    TMS")    public void <   >_<>_<__>_Test() {  //            orgTest = LoginFactory.get(_Some_Login_);                //               init(orgTest);           //    -.                preconditions();               //             actions(orgTest); }    /** *        **/ @Step(" ") protected void preconditions() {    loginStep1.login();    new SomeAction().apply(someTestObject1, ..., someTestObjectN);        Utils.allure.message("   -      -", someTestObjectN)        ...    }    /** *        */ @Step(" ") protected void actions(Login testLogin) {    testLogin.reLogin();               //                new SomeAction().apply(someTestObject1, ..., someTestObjectN); } } 

Implementierungsvorlage für Test-Skriptklassen


 package autotest.business.actions.some_subsystem; public class SomeAction {            //   PageClassA pageA = new PageClassA(); PageClassB pageB = new PageClassB();    @Step("     TMS")    @Description("     TMS")    public void apply(someTestObject1, ..., someTestObjectN) {    //   TMS        step_1(...);        step_2(...);        ...        step_N(...);    }    @Step("  1    TMS")    private void step_1(...) {       pageA.createSomething(someTestObject1);// just as an example create }    @Step("  2    TMS")    private void step_2(...) {   pageA.checkSomething(someTestObject1);// just as an example }                       ... } 

Implementieren der FilterTestRunner-Testfilterklasse


Hier ist eine Implementierung der BlockJUnit4ClassRunner-Erweiterung zum Filtern von Tests basierend auf beliebigen Tag-Sätzen.

 /** * Custom runner for JUnit4 tests. * Provide capability to do additional filtering executed test methods * accordingly information that could be provided by {@link FrameworkMethod} */ public class FilterTestRunner extends BlockJUnit4ClassRunner { private static final Logger LOGGER = Logger.getLogger(FilterTestRunner.class.getName()); public FilterTestRunner(Class<?> klass) throws InitializationError {    super(klass); } /** * This method should be used if you want to hide filtered tests completely from output **/ @Override protected List<FrameworkMethod> getChildren() {    //  ,        @Filter       TestFilter filter = TestFilterFactory.get();    List<FrameworkMethod> allMethods = super.getChildren();    List<FrameworkMethod> filteredMethod = new ArrayList<>();    for (FrameworkMethod method: allMethods) {        if (filter.test(method)) {            LOGGER.config("method [" + method.getName() +"] passed by filter [" + filter.toString() + "]" );            filteredMethod.add(method);        } else {            LOGGER.config("method [" + method.getName() +"] blocked by filter [" + filter.toString() + "]" );        }    }    return Collections.unmodifiableList(filteredMethod); } /** * This method should be used if you want to skip filtered tests but no hide them @Override protected boolean isIgnored(FrameworkMethod method) {    …    if (filter.test(method)) {        return super.isIgnored(method);    } else {     return true;  }} */ } 

Im nächsten Teil werde ich darüber sprechen, wie wir den Vorgang des Hochladens einer Datei aus dem Container mit dem Browser in das Testframework implementiert und das Problem gelöst haben, den Namen der vom Browser heruntergeladenen Datei zu finden.

Gerne ergänzen wir unser Team. Aktuelle Stellenangebote finden Sie hier .

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


All Articles