Bonjour.Dans cet article, je voudrais partager mon expérience dans l'automatisation des tests fonctionnels. Il s'agira d'écrire un cadre de test pratique et fiable.Ce que nous utiliserons: Java, Selenide, Alure, TestNG, Maven.
introduction
Projet GitHub - SelenideBoilerplate .Souvent dans les articles sur l'automatisation des tests, les exemples sont loin de la rĂ©alitĂ©, par exemple: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()
Il existe de nombreux exemples similaires d'attentes, d'objets de page, etc. En consĂ©quence, il peut ĂȘtre difficile pour un testeur dĂ©butant de tout organiser correctement et commodĂ©ment. Le projet est surchargĂ© de bĂ©quilles, c'est pourquoi il devient de plus en plus difficile d'Ă©crire de nouveaux tests et de maintenir les anciens.Il y a aussi des outils trop verbeux et trop compliquĂ©s Ă mon avis.Je vais vous montrer un framework de test simple, pratique et facilement extensible, qui est beaucoup plus facile Ă travailler que le sĂ©lĂ©nium ordinaire et que j'ai utilisĂ© avec succĂšs sur plusieurs projets. Ce projet est la base, sur des projets rĂ©els tout est un peu plus compliquĂ© (parallĂ©lisation, remoteDriver, nombreux tests, etc.).Outils
Structure du projet
Commençons par les modules d' application et de pages .PageBuilder, classe
En rĂšgle gĂ©nĂ©rale, les exemples donnent des pages assez simples oĂč tout tient dans une seule classe. Mais sur de vrais projets, il peut y avoir des pages assez grandes, dĂ©crivant toutes les fonctionnalitĂ©s dont dans une classe n'est pas la meilleure idĂ©e. Par exemple, cela pourrait ĂȘtre une page de recharge avec de nombreuses formes de systĂšmes de paiement diffĂ©rents.Dans ce cas, il est prĂ©fĂ©rable de diviser la page en plusieurs classes et mĂȘme Ă©lĂ©ments (par exemple, un produit dans le panier) et de tout regrouper dans la classe principale de la page.Par consĂ©quent, il est prĂ©fĂ©rable de crĂ©er toutes les pages au mĂȘme endroit, Ă savoir dans la classe PageBuilder .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);
}
}
Classe AppConfig
La classe AppConfig stocke les paramÚtres de l'application Web testée. Par exemple - l'adresse du site, les utilisateurs de test, etc. Dans ce projet, il s'agit simplement de l'adresse du site.package app;
public class AppConfig {
public static final String baseUrl = "https://google.com";
}
Classe d'application
Il s'agit de la classe principale de ce module. Dans le constructeur de la classe App , toutes les pages sont créées.package app;
import app.pages.LoginPage;
public class App {
public LoginPage loginPage;
public App() {
loginPage = PageBuilder.buildLoginPage();
}
}
Grùce à cette approche, il n'est pas nécessaire de créer constamment des objets de page dans les tests, seul l'objet App est créé à partir duquel les pages nécessaires sont obtenues.Dans la classe App , il peut également y avoir des méthodes telles que: enregistrement, enregistrement et création de commande, etc.C'est-à -dire de grandes opérations dans lesquelles plusieurs objets de page sont impliqués et qui sont souvent nécessaires dans les tests.Passons aux objets de page
GrĂące Ă Selenide, travailler avec des objets de page est facile. Toutes les pages hĂ©ritent de la classe de base BasePage . L'URL de page relative est transmise au constructeur d'objet de page.Tous les Ă©lĂ©ments de page ont un modificateur d' accĂšs public , vous pouvez donc Ă©crire des tests dans des styles impĂ©ratifs et dĂ©claratifs. De plus, Ă partir des Ă©lĂ©ments, vous pouvez obtenir les donnĂ©es nĂ©cessaires, telles que du texte ou un attribut.Le localisateur est stockĂ© en un seul endroit. Toute logique de page doit ĂȘtre dĂ©crite dans les mĂ©thodes de page.Avec cette approche, si quelque chose se casse ou change, dans la plupart des cas, il n'est pas nĂ©cessaire de réécrire les tests, la mĂ©thode est juste finalisĂ©e ou le localisateur change pour le test rĂ©el.
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");
}
}
Du repos
Le module helpers contient 2 classes importantes:TestConfig - A partir de cette classe, vous pouvez obtenir les paramÚtres avec lesquels les tests sont exécutés. Les paramÚtres par défaut sont également affichés ici.Les tests sont exécutés par la commande. mvn test -Dbrowser=chrome -Dheadless=1
Les valeurs des variables sont extraites de la ligne de commande et, grùce à la classe TestConfig, sont disponibles dans les tests et dans l'application.Par exemple, vous pouvez modifier l'URL de l'application en fonction de l'environnement (développeur, stade, production).
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");
}
}
La classe Driver est mon enveloppe sur les pilotes sélénium et séléniure avec quelques méthodes utiles.Les méthodes les plus importantes:Driver.initDriver () - ici le pilote / navigateur est initialisé. 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()
Les tests
Toutes les classes de test sont hĂ©ritĂ©es de la classe A_BaseTest , dans laquelle l'objet d'application App est créé , logger , softAssert , le navigateur s'ouvre et se ferme, les cookies sont effacĂ©s aprĂšs chaque test.Il existe Ă©galement un A_BaseTestListener oĂč les erreurs peuvent ĂȘtre enregistrĂ©es.Les tests ressemblent Ă ceci. Facile Ă lire, facile Ă entretenir.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();
}
}
Les classes de test sont spécifiées dans testng.xml .Le dossier de sortie de test contient des journaux et des captures d'écran - Driver.takeScreenshot () .Pour les rapports, Allure est utilisé . Une fois les tests terminés, vous pouvez exécuter la commande allure serve target/allure-results
et consulter le rapport.Projet GitHub - SelenideBoilerplate