Как стать автором
Обновить
1004.17
OTUS
Цифровые навыки от ведущих экспертов

Параллельное тестирование с JUnit 5 и Selenium [Учебное пособие]

Время на прочтение23 мин
Количество просмотров16K
Автор оригинала: Shalini Baskaran

Параллельное выполнение тестов с 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

Теперь, когда мы разобрали основные аспекты свойств фреймворка 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");

Выполнение

Ниже показан снапшот выполнения, свидетельствующий о параллельном исполнении тестов:

Как показано ниже, мы видим, что выполнение теста завершилось успешно.

Параллельное тестирование с junit 5
Параллельное тестирование с junit 5

Чтобы проверить статус выполнения теста, перейдите на дашборд автоматизации LambdaTest, где можно даже посмотреть видео.

Дашборд автоматизации LambdaTest
Дашборд автоматизации 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». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

Теги:
Хабы:
Всего голосов 3: ↑2 и ↓1+1
Комментарии1

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS