Guten Tag.In diesem Artikel möchte ich meine Erfahrungen mit der Automatisierung von Funktionstests teilen. Es geht darum, ein bequemes und zuverlässiges Test-Framework zu schreiben.Was wir verwenden werden: Java, Selenide, Alure, TestNG, Maven.
Einführung
GitHub-Projekt - SelenideBoilerplate .In Artikeln zur Testautomatisierung sind Beispiele häufig weit von der Realität entfernt, zum Beispiel:driver.get (“URL”)
driver.find_element_by_id(“ID”).send_keys(“username”)
driver.find_element_by_id (“ID”).send_keys(“password”)
driver.find_element_by_id(“submit”).click()
Es gibt viele ähnliche Beispiele für Erwartungen, Seitenobjekte usw. Infolgedessen kann es für einen unerfahrenen Tester schwierig sein, alles richtig und bequem zu organisieren. Das Projekt ist mit Krücken bewachsen, weshalb es immer schwieriger wird, neue Tests zu schreiben und alte zu warten.Es gibt auch einige Tools, die meiner Meinung nach zu ausführlich und zu kompliziert sind.Ich werde ein einfaches, bequemes und leicht erweiterbares Test-Framework zeigen, das viel einfacher zu verarbeiten ist als normales Selen und das ich erfolgreich in mehreren Projekten verwendet habe. Dieses Projekt ist die Basis, bei realen Projekten ist alles etwas komplizierter (Parallelisierung, RemoteDriver, viele Tests usw.).Werkzeuge
Projektstruktur
Beginnen wir mit den Start - App und Seiten - Module .PageBuilder-Klasse
In der Regel enthalten Beispiele relativ einfache Seiten, auf denen alles in eine Klasse passt. Bei realen Projekten kann es jedoch recht große Seiten geben, auf denen alle Funktionen beschrieben werden, die in einer Klasse nicht die beste Idee sind. Dies kann beispielsweise eine Aufladeseite mit vielen verschiedenen Zahlungssystemen sein.In diesem Fall ist es besser, die Seite in mehrere Klassen und sogar Elemente (z. B. ein Produkt im Warenkorb) aufzuteilen und alles in der Hauptklasse der Seite zusammenzufassen.Daher ist es besser, alle Seiten an einem Ort zu erstellen, nämlich in der PageBuilder- Klasse .package app;
import app.pages.LoginPage;
public class PageBuilder {
public static LoginPage buildLoginPage() {
return new LoginPage("/login");
}
public static BalancePage buildBalancePage() {
DepositForm depositForm = new DepositForm();
WithdrawalForm withdrawalForm = new WithdrawalForm();
return new BalancePage("/balance", depositForm, withdrawalForm);
}
}
Klasse AppConfig
Die AppConfig- Klasse speichert die Einstellungen der zu testenden Webanwendung. Zum Beispiel - die Site-Adresse, Testbenutzer usw. In diesem Projekt ist dies einfach die Adresse der Site.package app;
public class AppConfig {
public static final String baseUrl = "https://google.com";
}
App-Klasse
Dies ist die Hauptklasse in diesem Modul. Im Konstruktor der App- Klasse werden alle Seiten erstellt.package app;
import app.pages.LoginPage;
public class App {
public LoginPage loginPage;
public App() {
loginPage = PageBuilder.buildLoginPage();
}
}
Dank dieses Ansatzes ist es nicht erforderlich, in Tests ständig Seitenobjekte zu erstellen, sondern nur das App- Objekt, aus dem die erforderlichen Seiten abgerufen werden.Auch in der App- Klasse kann es Methoden geben wie - Registrierung, Registrierung und Auftragserstellung usw.Das heißt, große Vorgänge, an denen mehrere Seitenobjekte beteiligt sind und die häufig in Tests benötigt werden.Fahren wir mit den Seitenobjekten fort
Dank Selenide ist die Arbeit mit Seitenobjekten einfach. Alle Seiten erben von der BasePage- Basisklasse . Die relative Seiten-URL wird an den Seitenobjektkonstruktor übergeben.Alle Seitenelemente verfügen über einen Modifikator für den öffentlichen Zugriff , sodass Sie Tests sowohl im imperativen als auch im deklarativen Stil schreiben können. Außerdem können Sie aus den Elementen die erforderlichen Daten wie Text oder ein Attribut abrufen.Der Locator ist nur an einem Ort gespeichert. Die gesamte Seitenlogik sollte in Seitenmethoden beschrieben werden.Wenn bei diesem Ansatz etwas kaputt geht oder sich ändert, ist es in den meisten Fällen nicht erforderlich, die Tests neu zu schreiben. Die Methode wird nur abgeschlossen oder der Locator wechselt zum tatsächlichen.
package app.pages;
import com.codeborne.selenide.SelenideElement;
import helpers.Driver;
import static com.codeborne.selenide.Selenide.*;
public class LoginPage extends BasePage {
public SelenideElement loginField = $("#login__username");
public SelenideElement passwordField = $("#login__password");
public SelenideElement signInButton = $("#login_enter");
public SelenideElement termsOfUseLabel = $("label[for=\"login_agree\"]");
public LoginPage(String pageUrl) {
super(pageUrl);
}
public void login(String email, String password) {
loginField.setValue(email);
passwordField.setValue(password);
termsOfUseLabel.click();
signInButton.click();
Driver.waitForUrlContains("account/accounts");
}
}
Sich ausruhen
Der Helfer - Modul enthält zwei wichtige Klassen:TestConfig - Aus dieser Klasse , die Sie die Einstellungen bekommen , mit denen Tests ausgeführt werden. Hier werden auch die Standardeinstellungen angezeigt.Tests werden vom Befehl ausgeführt. mvn test -Dbrowser=chrome -Dheadless=1
Die Werte der Variablen werden über die Befehlszeile übernommen und sind dank der TestConfig- Klasse in Tests und in der Anwendung verfügbar.Beispielsweise können Sie die Anwendungs-URL abhängig von der Umgebung (Entwickler, Phase, Produktion) ändern.
package helpers;
public class TestConfig {
public static String browser = "chrome";
public static String headless = "1";
public static void initConfig() {
browser = System.getProperty("browser") == null ? "chrome" : System.getProperty("browser");
headless = System.getProperty("headless") == null ? "1" : System.getProperty("headless");
}
public static boolean isHeadless() {
return headless.contains("1");
}
}
Die Treiberklasse ist mein Wrapper für Selen- und Selenid-Treiber mit einigen nützlichen Methoden.Die wichtigsten Methoden:Driver.initDriver () - hier wird der Treiber / Browser initialisiert. public static void initDriver() {
TestConfig.initConfig();
Configuration.pageLoadStrategy = "eager";
Configuration.browserSize = "1920x1080";
Configuration.holdBrowserOpen = false;
Configuration.screenshots = false;
if(TestConfig.isHeadless()) {
Configuration.headless = true;
} else {
Configuration.headless = false;
}
switch (TestConfig.browser) {
case "chrome":
Configuration.browser = Browsers.CHROME;
break;
case "firefox":
Configuration.browser = Browsers.FIREFOX;
break;
default:
Configuration.browser = Browsers.CHROME;
break;
}
}
Driver.clearCookies()
Driver.close()
Tests
Alle Testklassen werden von der A_BaseTest- Klasse geerbt , in der das App- Anwendungsobjekt erstellt wird , Logger , softAssert , der Browser öffnet und schließt, Cookies werden nach jedem Test gelöscht.Es gibt auch einen A_BaseTestListener, in dem Fehler protokolliert werden können.Die Tests sehen ungefähr so aus. Leicht zu lesen, leicht zu pflegen.import org.testng.annotations.Test;
public class ExampleTest extends A_BaseTest
{
@Test
public void loginViaEmail() {
app.loginPage.open();
app.loginPage.login("email@email.com", "passwords");
logger.info("Sample info message");
softAssert.assertEquals(2,2);
softAssert.assertAll();
}
}
Testklassen
sind in testng.xml angegeben .Der Testausgabeordner enthält Protokolle und Screenshots - Driver.takeScreenshot () .Für Berichte wird Allure verwendet . Nach Abschluss der Tests können Sie den Befehl ausführen allure serve target/allure-results
und den Bericht anzeigen.GitHub-Projekt - SelenideBoilerplate