Параллельное выполнение тестов с Selenium является одним из основных факторов, способных повлиять на скорость их выполнения. Последовательное выполнение в автоматизированном тестировании Selenium будет эффективным только тогда, когда тесты будут выполняться для небольшого числа комбинаций браузеров и ОС. Следовательно, параллельное выполнение следует использовать на ранних стадиях QA-тестирования, чтобы быстро ускорить проведение тестов.
Хотя вы можете воспользоваться преимуществами параллельного тестирования в Selenium, используя локальную Selenium Grid, это может оказаться нецелесообразным, если вы хотите проводить тестирование на множестве браузеров, операционных систем и устройств. В этом случае тестирование на облачной Selenium Grid, такой как LamdaTest, будет наиболее выгодным. Она поможет ускорить параллельное выполнение тестов, используя преимущества, которые предлагает Selenium Grid.
Будучи Java-разработчиком, я активно использую возможности фреймворка JUnit 5 для различных сценариев тестирования, включая параллельное тестирование с Selenium. JUnit 5 значительно отличается от своего предшественника (т.е. JUnit 4), причем различия начинаются с архитектуры ядра. Если вы только начинаете работать с JUnit 5, советую внимательно изучить архитектуру JUnit 5, чтобы понять, как запускать тесты с помощью этого фреймворка.
В этом учебном пособии будет подробно рассказано о том, как проводить параллельное выполнение тестов с помощью фреймворка JUnit 5. Некоторые функции JUnit 5 все еще находятся в экспериментальной фазе, включая параллельное выполнение тестов. Но, вы можете поделиться своими ценными отзывами с командой JUnit, что поможет в продвижении этой функции для выведения ее из экспериментальной фазы.
Введение во фреймворк JUnit 5
Прежде чем погрузиться в самую суть параллельного выполнения тестов JUnit 5, разрешите кратко описать основные характеристики фреймворка JUnit 5. В JUnit 4 все функциональные возможности упакованы в один пакет. В свою очередь, JUnit 5 состоит из трех отдельных подкомпонентов — JUnit Platform, JUnit Jupiter и JUnit Vintage.
Существует значительная разница в аннотациях JUnit 5 и JUnit 4. Хотя некоторые аннотации в JUnit 5 изменились с точки зрения именования, такие как @Rule и @ClassRule были удалены, а новые, @ExtendWith и @RegisterExtension, добавились в JUnit 5.
Для тех, кто использует JUnit 4, рекомендуем сравнить JUnit 4 с JUnit 5, чтобы понять различия между двумя версиями этих фреймворков. Существует множество причин, по которым JUnit 5 имеет огромное превосходство перед JUnit 4; однако, чтобы понять основные преимущества, проверьте, почему следует использовать JUnit 5.
Ниже показано архитектурное представление фреймворка JUnit 5:
В целом, JUnit 5 гораздо более расширяем благодаря своей уникальной архитектуре, обеспечивает гибкость при использовании нескольких раннеров и предоставляет набор полезных аннотаций, которые улучшают тесты.
Параллельное выполнение тестов в JUnit 5
Теперь, когда мы разобрали основные аспекты свойств фреймворка JUnit 5, рассмотрим, как осуществить параллельное выполнение тестов в JUnit 5 с точки зрения автоматизации тестирования Selenium. Для выполнения тестов потребуется рабочая настройка JUnit на вашей машине. Обязательно ознакомьтесь с нашим блогом о том, как настроить среду JUnit, в котором описанные шаги остаются неизменными и для JUnit 5.
Давайте перейдем к вопросу "Как запускать тесты JUnit 5 параллельно"? Во-первых, параллельное выполнение тестов JUnit 5 все еще находится в экспериментальной стадии, и, как ожидается, станет основной функцией в предстоящем релизе JUnit 5. Итак, чтобы включить параллельное выполнение тестов в JUnit 5, установите junit.jupiter.execution.parallel.enabled в true в файле junit-platform.properties.
Читайте - Как выполнять тесты JUnit 4 с помощью JUnit 5
Даже после установки вышеуказанного свойства в true тестовые классы и тестовые методы все равно будут выполняться последовательно. SAME_THREAD и CONCURRENT - это два режима, позволяющие контролировать последовательность выполнения тестов. Как указано в официальной документации пользователя JUnit 5, SAME_THREAD (режим выполнения по умолчанию) заставляет тест выполняться в том же потоке, который использует его родитель. С другой стороны, CONCURRENT позволяет выполнять тесты одновременно в разных, если блокировка ресурсов не заставляет выполнять их в одном потоке.
Вот параметры конфигурации для параллельного выполнения всех тестов JUnit 5:
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
Как только свойство параллельного выполнения установлено (или включено), движок JUnit Jupiter будет выполнять тесты параллельно в соответствии с конфигурациями, предоставляемыми механизмами синхронизации. В следующем разделе руководства по JUnit 5 мы подробно рассмотрим практическую реализацию параллельного выполнения тестов JUnit 5 для автоматизированного тестирования Selenium.
Если вы являетесь экспертом по Java, с помощью бесплатной сертификации JUnit вы можете получить признание своих знаний и продвинуться по карьерной лестнице.
Эта сертификация JUnit устанавливает стандарты тестирования для тех, кто хочет развивать свою карьеру в области автоматизированного тестирования Selenium с JUnit.
Вот краткий обзор сертификации JUnit от LambdaTest:
Демонстрация: Параллельное выполнение тестов JUnit 5 для автоматизированного тестирования Selenium
Давайте приступим к демонстрации параллельного выполнения тестов с помощью JUnit 5. Сначала рассмотрим простой пример на Java, состоящий из двух классов, выполняемых параллельно с использованием фреймворка JUnit 5.
Давайте рассмотрим простой пример параллельного выполнения тестов JUnit 5.
FileName – Test1.java
package SimpleTest;
import org.junit.jupiter.api.*;
public class Test1 {
@BeforeAll
public static void start() {
System.out.println("=======Starting junit 5 tests========");
}
@BeforeEach
public void setup() {
System.out.println("=======Setting up the prerequisites========");
}
@Test
void test1_FirstTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@Test
void test1_SecondTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@Test
void test1_ThirdTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@Test
void test1_FourthTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@AfterEach
public void tearDown() {
System.out.println("Tests ended");
}
@AfterAll
public static void end() {
System.out.println("All the tests are executed");
}
}
FileName – Test2.java
package SimpleTest;
import org.junit.jupiter.api.*;
public class Test2 {
@BeforeAll
public static void start() {
System.out.println("=======Starting junit 5 tests========");
}
@BeforeEach
public void setup() {
System.out.println("=======Setting up the prerequisites========");
}
@Test
void test2_FirstTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@Test
void test2_SecondTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@Test
void test2_ThirdTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@Test
void test2_FourthTest() {
System.out.println(Thread.currentThread().getStackTrace()[1]
.getMethodName()+" => executed successfully");
}
@AfterEach
public void tearDown() {
System.out.println("Tests ended");
}
@AfterAll
public static void end() {
System.out.println("All the tests are executed");
}
}
FileName – pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>ParallelTest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
<junit.jupiter.version>5.7.1</junit.jupiter.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Итак, как мы можем запускать тестовые сценарии JUnit 5 параллельно? Фреймворк JUnit 5 предоставляет для этого два различных механизма:
Способ 1: Добавить аргументы VM в конфигурацию Run
Шаг 1: Кликните правой кнопкой мыши по папке, содержащей тесты, которые вы собираетесь запускать параллельно. Кликните Create Tests (Создать тесты).
Шаг 2: В конфигурации Create Run добавьте следующие аргументы в опциях VM:
-Djunit.jupiter.execution.parallel.enabled=true
-Djunit.jupiter.execution.parallel.mode.default=concurrent
Шаг 3: Нажмите OK и запустите тесты.
Из результатов видно, что тесты JUnit 5 выполняются параллельно.
Результат выполнения
Метод 2: Параллельное выполнение тестов JUnit 5 с помощью Maven
В этом специфическом методе опции параллельного выполнения добавляются в файл pom.xml. Если вы новичок в Maven, то можете быстро просмотреть учебник Maven для Selenium, который поможет начать работу с Maven для Eclipse IDE.
Для демонстрации мы использовали предыдущий пример, в котором два теста в разных Java-файлах выполнялись параллельно. Выполните следующие шаги, чтобы реализовать параллельное выполнение в JUnit 5 с помощью указанного подхода:
Шаг 1: Установите junit.jupiter.execution.parallel.enabled
в true
и junit.jupiter.execution.parallel.mode.default в concurrent в pom.xml
.
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<properties>
<configurationParameters>
junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=concurrent
</configurationParameters>
</properties>
</configuration>
</plugin>
</plugins>
</build>
Шаг 2: Выполните команду Maven mvn clean test
, чтобы запустить тесты из командной строки. Если вас заинтересовала информация о выполнении командной строки с Maven для JUnit, обязательно ознакомьтесь с нашим подробным блогом, демонстрирующим выполнение тестов JUnit из командной строки.
Ниже показан снапшот выполнения, который свидетельствует об успешном завершении теста:
Если вам интересно узнать больше о других основных возможностях фреймворка JUnit, перейдите к подробному руководству по JUnit на учебном хабе LambdaTest.
Как осуществить параллельное выполнение тестов JUnit 5 с помощью Selenium
Подлинный потенциал параллельного тестирования в Selenium можно использовать, перенеся тесты из локальной Selenium Grid в облачную Selenium Grid, такую как LambdaTest. Вы можете ознакомиться с нашим руководством по облачному тестированию, чтобы понять основные преимущества облачных грид-систем.
LambdaTest предоставляет отличную платформу для запуска Selenium-тестов на 2000+ браузерах и операционных системах, и все это в облаке! Более того, поскольку изменения кода касаются в основном инфраструктуры, можно легко перенести существующую реализацию с локальной Selenium Grid на облачную.
После создания учетной записи на LambdaTest обязательно запишите имя пользователя и ключ доступа, которые доступны на странице профиля LambdaTest. Затем вы можете сгенерировать желаемые функции для комбинаций браузера и платформы с помощью генератора возможностей на LambdaTest.
Ниже приведен код для запуска наших тестов Junit 5 на облачной Selenium Grid, типа LambdaTest:
FileName — RunningTestsInParallelInGrid.java
import org.openqa.selenium.By;
import org.junit.jupiter.api.*;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class RunningTestsInParallelInGrid {
String username = "YOUR_USERNAME"; //Enter your username
String accesskey = "YOUR_ACCESS_KEY"; //Enter your accesskey
static RemoteWebDriver driver = null;
String gridURL = "@hub.lambdatest.com/wd/hub";
String urlToTest = "https://www.lambdatest.com/";
@BeforeAll
public static void start() {
System.out.println("=======Running junit 5 tests in parallel in LambdaTest Grid has started========");
}
@BeforeEach
public void setup() {
System.out.println("Setting up the drivers and browsers");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("browserName", "chrome"); //To specify the browser
capabilities.setCapability("version", "70.0"); //To specify the browser version
capabilities.setCapability("platform", "win10"); // To specify the OS
capabilities.setCapability("build", "Running_ParallelJunit5Tests_In_Grid"); //To identify the test
capabilities.setCapability("name", "Parallel_JUnit5Tests");
capabilities.setCapability("network", true); // To enable network logs
capabilities.setCapability("visual", true); // To enable step by step screenshot
capabilities.setCapability("video", true); // To enable video recording
capabilities.setCapability("console", true); // To capture console logs
try {
driver = new RemoteWebDriver(new URL("https://" + username + ":" + accesskey + gridURL), capabilities);
} catch (MalformedURLException e) {
System.out.println("Invalid grid URL");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Test
@DisplayName("Title_Test")
@Tag("Sanity")
public void launchAndVerifyTitle_Test() {
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
String actualTitle = driver.getTitle();
System.out.println("The page title is "+actualTitle);
String expectedTitle ="Most Powerful Cross Browser Testing Tool Online | LambdaTest";
System.out.println("Verifying the title of the webpage started");
Assertions.assertEquals(expectedTitle, actualTitle);
System.out.println("The webpage has been launched and the title of the webpage has been veriified successfully");
System.out.println("********Execution of "+methodName+" has ended********");
}
@Test
@DisplayName("Login_Test")
@Tag("Sanity")
public void login_Test() {
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement login = driver.findElement(By.xpath("//a[text()='Login']"));
login.click();
WebElement username = driver.findElement(By.xpath("//input[@name=\"email\"]"));
WebElement password = driver.findElement(By.xpath("//input[@name=\"password\"]"));
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.visibilityOf(username));
username.clear();
username.sendKeys("acvdd@gmail.com");
password.clear();
password.sendKeys("abc@123");
WebElement loginButton = driver.findElement(By.xpath("//button[text()='Login']"));
loginButton.click();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
String actual = driver.getTitle();
String expected = "Welcome - LambdaTest";
Assertions.assertEquals(expected, actual);
System.out.println("The user has been successfully logged in");
System.out.println("********Execution of "+methodName+" has ended********");
}
@Test
@DisplayName("Logo_Test")
public void logo_Test() {
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
System.out.println("Verifying of webpage logo started..");
WebElement logo = driver.findElement(By.xpath("//*[@id=\"header\"]/nav/div/div/div[1]/div/a/img"));
boolean is_logo_present = logo.isDisplayed();
if(is_logo_present) {
System.out.println("The logo of LambdaTest is displayed");
}
else {
Assertions.assertFalse(is_logo_present,"Logo is not present");
}
System.out.println("********Execution of "+methodName+" has ended********");
}
@Test
@DisplayName("Blog_Test")
public void blogPage_Test() {
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement resources = driver.findElement(By.xpath("//*[text()='Resources ']"));
List<WebElement> options_under_resources = driver.findElements(By.xpath("//*[text()='Resources ']/../ul/a"));
boolean flag = resources.isDisplayed();
if(flag) {
System.out.println("Resources header is visible in the webpage");
Actions action = new Actions(driver);
action.moveToElement(resources).build().perform();
WebDriverWait wait=new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.visibilityOfAllElements(options_under_resources));
for(WebElement element : options_under_resources) {
if(element.getText().equals("Blog")){
System.out.println("Clicking Blog option has started");
element.click();
System.out.println("Clicking Blog option has ended");
driver.manage().timeouts().pageLoadTimeout(20,TimeUnit.SECONDS);
Assertions.assertEquals("LambdaTest Blogs", driver.getTitle());
break;
}
else
Assertions.fail("Blogs option is not available");
}
}
else {
Assertions.fail("Resources header is not visible");
}
System.out.println("********Execution of "+methodName+" has ended********");
}
@Test
@DisplayName("Cerification_Test")
public void certificationPage_Test() {
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement resources = driver.findElement(By.xpath("//*[text()='Resources ']"));
List<WebElement> options_under_resources = driver.findElements(By.xpath("//*[text()='Resources ']/../ul/a"));
boolean flag = resources.isDisplayed();
if(flag) {
System.out.println("Resources header is visible in the webpage");
Actions action = new Actions(driver);
action.moveToElement(resources).build().perform();
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.visibilityOfAllElements(options_under_resources));
for (int i = 0; i < options_under_resources.size(); i++) {
String value = options_under_resources.get(i).getText();
if (value.equals("Certifications")) {
System.out.println("Clicking Certifications option has started");
action.moveToElement(options_under_resources.get(i)).build().perform();
options_under_resources.get(i).click();
System.out.println("Clicking Certifications option has ended");
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
String expectedCertificationPageTitle = "LambdaTest Selenium Certifications - Best Certifications For Automation Testing Professionals";
String actualCertificationPageTitle = driver.getTitle();
Assertions.assertEquals(expectedCertificationPageTitle, actualCertificationPageTitle);
break;
}
}
}
System.out.println("********Execution of "+methodName+" has ended********");
}
@Test
@DisplayName("Support_Test")
public void supportPage_Test() {
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement supportHeader = driver.findElement(By.xpath("(//div//*[text()='Support'])[1]"));
boolean flag = supportHeader.isDisplayed();
if(flag) {
System.out.println("support header is visible in the webpage");
supportHeader.click();
}
else {
Assertions.fail("support header is not visible");
}
System.out.println("********Execution of "+methodName+" has ended********");
}
@AfterEach
public void tearDown() {
System.out.println("Quitting the browsers has started");
driver.quit();
System.out.println("Quitting the browsers has ended");
}
@AfterAll
public static void end() {
System.out.println("Tests ended");
}
}
Как упоминалось ранее, параллельное выполнение тестов JUnit 5 может быть достигнуто путем добавления аргументов в опциях VM в конфигурации Run или запуском через Maven путем добавления плагина в файл pom.xml.
Обзор кода
Вместо того чтобы подробно разбирать код, остановимся на наиболее важных аспектах.
Для начала создадим экземпляр Remote WebDriver, используя возможности браузера и платформы, добавленные в методе setup(). Затем, как показано ниже, для доступа к LambdaTest Grid используется пара - имя пользователя/ключ доступа.
driver = new RemoteWebDriver(new URL("https://" + username + ":" + accesskey + gridURL), capabilities);
Класс включает в себя 6 методов тестирования, причем каждый метод применяет соответствующие локаторы Selenium для поиска соответствующих Web-элементов. Например, в тестовом методе login_Test()
локатор XPath Selenium используется для поиска элементов email и password на странице. Если вам нужен краткий обзор XPath, обязательно ознакомьтесь с нашим подробным руководством по использованию локаторов XPath в Selenium.
WebElement username = driver.findElement(By.xpath("//input[@name=\"email\"]"));
WebElement password = driver.findElement(By.xpath("//input[@name=\"password\"]"));
При выполнении теста существует вероятность того, что динамически загруженный контент (или Web-элемент) может отсутствовать на странице. Взаимодействие с элементом, который пока не является частью DOM, может привести к исключениям. Поскольку работа с динамическим содержимым является одной из основных проблем автоматизации Selenium, ее необходимо решать путем добавления подходящей задержки (задержек), чтобы сделать соответствующий WebElement доступным для доступа в DOM.
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
Предполагаемые условия в Selenium WebDriver используются в соответствующих местах реализации для обеспечения того, что Web-элементы, с которыми осуществляется взаимодействие, были видимыми, интерактивными и т. д. Например, в тестовом методе blogPage_Test()
выполняется ожидание условия visibilityOfAllElements
(видимость всех элементов). Затем, если определенные элементы видимы, с ними выполняются надлежащие действия.
wait.until(ExpectedConditions.visibilityOfAllElements(options_under_resources));
Утверждения (asserts) JUnit с Selenium используются во всех методах тестирования для подтверждения сбоев, возникающих в процессе автоматизированного тестирования Selenium. Ниже приведены некоторые ассерты из нескольких методов тестирования:
Assertions.assertEquals(expectedCertificationPageTitle, actualCertificationPageTitle);
Assertions.assertFalse(is_logo_present,"Logo is not present");
Выполнение
Ниже показан снапшот выполнения, свидетельствующий о параллельном исполнении тестов:
Как показано ниже, мы видим, что выполнение теста завершилось успешно.
Чтобы проверить статус выполнения теста, перейдите на дашборд автоматизации LambdaTest, где можно даже посмотреть видео.
Как осуществить параллельное выполнение тестов JUnit 5 с помощью параметризации в Selenium
В предыдущем разделе мы выполнили шесть различных тестов на одной комбинации браузера и платформы. Однако такой подход может дать сбой, если тесты необходимо выполнить сочетаниями по "N" различных комбинаций.
Именно здесь параметризованное тестирование с помощью JUnit в Selenium будет очень эффективным, поскольку соответствующие комбинации тестов могут быть переданы в качестве параметров параметризованным методам тестирования. Как и его предшественник, JUnit 5 также обладает гибкостью, позволяющей использовать параметризацию в Selenium для сокращения LOC (Lines of Code) и достижения лучшего покрытия тестов меньшим количеством кода.
Добавьте следующую зависимость в pom.xml, чтобы вы могли параметризовать тесты с помощью фреймворка JUnit 5:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>
Для демонстрации мы будем проводить тесты на браузерах Chrome и Firefox на LambdaTest Selenium Grid. Комбинации браузеров и платформ создаются с помощью генератора возможностей LambdaTest.
FileName - crossBrowserTests.java
package crossBrowserTests;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import static org.junit.jupiter.params.provider.Arguments.arguments;
public class crossBrowserTest {
String username = "user_name"; //Enter your username
String accesskey = "access_key"; //Enter your accesskey
static RemoteWebDriver driver = null;
String gridURL = "@hub.lambdatest.com/wd/hub";
String urlToTest = "https://www.lambdatest.com/";
@BeforeAll
public static void start() {
System.out.println("=======Starting junit 5 tests in LambdaTest Grid========");
}
@BeforeEach
public void setup(){
System.out.println("=======Setting up drivers and browser========");
}
public void browser_setup(String browser) {
System.out.println("Setting up the drivers and browsers");
DesiredCapabilities capabilities = new DesiredCapabilities();
if(browser.equalsIgnoreCase("Chrome")) {
capabilities.setCapability("browserName", "chrome"); //To specify the browser
capabilities.setCapability("version", "70.0"); //To specify the browser version
capabilities.setCapability("platform", "win10"); // To specify the OS
capabilities.setCapability("build", "Running_Junit5Tests_In_Grid_Chrome"); //To identify the test
capabilities.setCapability("name", "JUnit5Tests_Chrome");
capabilities.setCapability("network", true); // To enable network logs
capabilities.setCapability("visual", true); // To enable step by step screenshot
capabilities.setCapability("video", true); // To enable video recording
capabilities.setCapability("console", true); // To capture console logs
}
if(browser.equalsIgnoreCase("Firefox")) {
capabilities.setCapability("browserName", "Firefox"); //To specify the browser
capabilities.setCapability("version", "76.0"); //To specify the browser version
capabilities.setCapability("platform", "win10"); // To specify the OS
capabilities.setCapability("build", "Running_Junit5Tests_In_Grid_Firefox"); //To identify the test
capabilities.setCapability("name", "JUnit5Tests_Firefox");
capabilities.setCapability("network", true); // To enable network logs
capabilities.setCapability("visual", true); // To enable step by step screenshot
capabilities.setCapability("video", true); // To enable video recording
capabilities.setCapability("console", true); // To capture console logs
}
try {
driver = new RemoteWebDriver(new URL("https://" + username + ":" + accesskey + gridURL), capabilities);
} catch (MalformedURLException e) {
System.out.println("Invalid grid URL");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@ParameterizedTest
@MethodSource("browser")
public void launchAndVerifyTitle_Test(String browser) {
browser_setup(browser);
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
String actualTitle = driver.getTitle();
System.out.println("The page title is "+actualTitle);
String expectedTitle ="Most Powerful Cross Browser Testing Tool Online | LambdaTest";
System.out.println("Verifying the title of the webpage started");
Assertions.assertEquals(expectedTitle, actualTitle);
System.out.println("The webpage has been launched and the title of the webpage has been veriified successfully");
System.out.println("********Execution of "+methodName+" has ended********");
}
@ParameterizedTest
@MethodSource("browser")
public void login_Test(String browser) {
browser_setup(browser);
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement login = driver.findElement(By.xpath("//a[text()='Login']"));
login.click();
WebElement username = driver.findElement(By.xpath("//input[@name='email']"));
WebElement password = driver.findElement(By.xpath("//input[@name='password']"));
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.visibilityOf(username));
username.clear();
username.sendKeys("abcwdwd@gmail.com");
password.clear();
password.sendKeys("abc@123");
WebElement loginButton = driver.findElement(By.xpath("//button[text()='Login']"));
loginButton.click();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
String actual = driver.getTitle();
String expected = "Welcome - LambdaTest";
Assertions.assertEquals(expected, actual);
System.out.println("The user has been successfully logged in");
System.out.println("********Execution of "+methodName+" has ended********");
}
@ParameterizedTest
@MethodSource("browser")
public void logo_Test(String browser) {
browser_setup(browser);
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
System.out.println("********Execution of "+methodName+" has been started********");
System.out.println("Launching LambdaTest website started..");
driver.get(urlToTest);
driver.manage().window().maximize();
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
System.out.println("Verifying of webpage logo started..");
WebElement logo = driver.findElement(By.xpath("//*[@id=\"header\"]/nav/div/div/div[1]/div/a/img"));
boolean is_logo_present = logo.isDisplayed();
if(is_logo_present) {
System.out.println("The logo of LambdaTest is displayed");
}
else {
Assertions.assertFalse(is_logo_present,"Logo is not present");
}
System.out.println("********Execution of "+methodName+" has ended********");
}
@AfterEach
public void tearDown() {
System.out.println("Quitting the browsers has started");
driver.quit();
System.out.println("Quitting the browsers has ended");
}
@AfterAll
public static void end() {
System.out.println("Tests ended");
}
static Stream<Arguments> browser() {
return Stream.of(
arguments("Chrome"),
arguments("Firefox")
);
}
}
Краткое описание кода
Поскольку мы используем параметризацию в JUnit 5, необходимый пакет импортируется в начале процесса имплементации.
import org.junit.jupiter.params.ParameterizedTest;
Также импортируется пакет org.junit.jupiter.params.provider
, поскольку поток физических аргументов будет использоваться в качестве входных данных для аннотированного метода @ParameterizedTest
.
import static org.junit.jupiter.params.provider.Arguments.arguments;
Поток аргументов Browser определяется так, как показано ниже. Каждый метод тестирования использует 'browser' в качестве входного аргумента, по которому выполняются методы тестирования.
static Stream<Arguments> browser() {
return Stream.of(
arguments("Chrome"),
arguments("Firefox")
);
}
Каждый метод тестирования вызывает метод browser_setup()
, в котором устанавливаются соответствующие возможности браузера и платформы в зависимости от определенной комбинации тестов. Например, удаленный драйвер Chrome инстанцируется, если параметр (т.е. браузер) установлен на Chrome. Тот же принцип применим и к браузеру Firefox.
public void browser_setup(String browser) {
System.out.println("Setting up the drivers and browsers");
DesiredCapabilities capabilities = new DesiredCapabilities();
if(browser.equalsIgnoreCase("Chrome")) {
.............................................
.............................................
.............................................
Поскольку каждый метод теста является параметризованным, он определяется под аннотацией @ParameterizedTest
. Аналогично, аннотация @MethodSource
используется для доступа к значениям, возвращаемым из фабричных методов класса, под которым объявлена аннотация.
Как видно ниже, @MethodSource
предоставляет доступ к значению "browser", которое представляет собой поток аргументов (т.е. Stream< Arguments >). Следовательно, три метода тестирования [т.е. launchAndVerifyTitle_Test()
, login_Test()
и logo_Test()
] будут запущены в двух комбинациях браузеров (т.е. Chrome и Firefox).
@ParameterizedTest
@MethodSource("browser")
public void launchAndVerifyTitle_Test(String browser) {
browser_setup(browser);
String methodName = Thread.currentThread()
.getStackTrace()[1]
.getMethodName();
...................................
...................................
...................................
Таким образом, вы должны увидеть шесть тестовых сценариев, выполняющихся параллельно на Selenium Grid LambdaTest. Помимо этих изменений, остальная логика имплементации остается прежней, как упоминалось ранее.
Метод tearDown()
, определенный в аннотации @AfterEach
, выполняется после каждого запуска теста, чтобы последующие тесты выполнялись на новой комбинации браузера и ОС.
@AfterEach
public void tearDown() {
System.out.println("Quitting the browsers has started");
driver.quit();
System.out.println("Quitting the browsers has ended");
}
Метод, определенный в аннотации @AfterAll
, выполняется только после завершения выполнения всех тестов.
@AfterAll
public static void end() {
System.out.println("Tests ended");
}
Выполнение
Ниже показан снапшот процесса, который показывает, что параллельное выполнение тестов с использованием JUnit 5 было выполнено на браузерах Chrome и Firefox.
Ниже показан снапшот дашборда автоматизации LambdaTest, который показывает, что три метода тестирования были запущены на двух различных комбинациях браузеров (т.е. Chrome и Firefox). Название сборки, отображаемое на дашборде, было установлено при настройке желаемых возможностей браузера.
apabilities.setCapability("build", "Running_Junit5Tests_In_Grid_Chrome");
//To identify the test
capabilities.setCapability("name", "JUnit5Tests_Chrome");
.............................................
.............................................
.............................................
capabilities.setCapability("build", "Running_Junit5Tests_In_Grid_Firefox");
//To identify the test
capabilities.setCapability("name", "JUnit5Tests_Firefox");
Консоль выполнения IntelliJ показывает, что три теста были успешно выполнены для двух различных комбинаций браузеров.
Заключение
В этом руководстве было рассмотрено, как осуществлять параллельное выполнение тестов с помощью фреймворка JUnit 5 различными способами. Для тестов мы также использовали облачную грид-систему LambdaTest, которая поддерживает 2000+ браузеров и различные платформы. Надеюсь, что эта статья помогла вам разобраться в параллельном выполнении тестов с помощью JUnit 5.
Продолжайте исследовать!
Материал подготовлен в рамках курса «Java QA Engineer. Professional». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.
AlexanderAlexandrovich
А почему не используете selenid?