여러 테스트 케이스를 실행하는 방법 TestNG 스위트

⚡ 스마트 요약

여러 테스트 케이스 실행 TestNG 스위트 인 Selenium TestNG를 사용하면 단일 TestNG.xml 파일에서 여러 클래스, 패키지 또는 하위 테스트 스위트를 실행할 수 있습니다. 이 가이드에서는 병렬 스레드, 테스트 스위트 계층 구조, 보고 및 최신 테스트 환경을 위한 AI 지원 기능을 다룹니다. TestNG 7.x 프로젝트.

  • 🧵 병렬 스레드: `thread-count`와 `parallel="tests"`를 설정하여 브라우저 및 패키지 전반에 걸쳐 전체 실행 시간을 대폭 줄이세요.
  • 🗂️ 스위트 계층 구조: 상위 testng.xml 파일에 하위 suite-file 항목을 나열하여 하나의 트리거에서 여러 테스트 스위트를 연결할 수 있습니다.
  • ⚙️ TestNG 7.x 버전 준비 완료: 예시는 다음과 일치합니다. TestNG 7.10 및 Selenium 기존 드라이버를 대체하는 4개의 W3C 드라이버 Firefox드라이버 배선.
  • 📊 스마트 보고: 상세 출력 레벨 1~10과 이메일로 전송 가능한 HTML 보고서를 통해 병렬 스레드 오류를 신속하게 진단할 수 있습니다.
  • 🤖 AI 오케스트레이션: AI 기반 스케줄러는 과거의 오류 발생률 및 지속 시간 데이터를 기반으로 스위트 순서를 재정렬하고, 재시도하며, 샤딩합니다.

여러 테스트 케이스 실행 TestNG 스위트 인 Selenium

TestNG 이 기능을 사용하면 하나의 프로젝트 내에서 테스트 메서드, 클래스 및 전체 테스트 스위트를 병렬로 실행할 수 있습니다. 병렬 실행은 스레드가 순차적으로 테스트를 시작하는 대신 동시에 테스트를 시작하기 때문에 전체 실행 시간을 단축합니다. 이 가이드에서는 이 기능을 사용하여 여러 클래스(서로 다른 테스트 스위트)를 실행하는 방법을 설명합니다. TestNG 7.x 버전과 함께 Selenium 웹드라이버.

1단계) 만들기 TestNG테스트 실행을 위한 .xml 파일

설정을 생성하려면 아래 단계를 따르십시오.

  1. 새 프로젝트를 만듭니다 Eclipse.
  2. 프로젝트에 패키지 두 개를 생성하고 이름을 지정하세요. com.suite1 com.suite2).
  3. 각 패키지에 클래스를 생성하고 (이름을 지정하세요) Flipkart.java 스냅딜.자바) 그리고 아래 코드를 해당 클래스에 복사하세요.
  4. 프로젝트에 새 파일을 만들고 이름을 지정하세요. 테스트ng.xml. 다음 사항을 확인하십시오. TestNG 플러그인이 설치되었습니다(설치 방법 안내). 여기에서 확인하세요testng.xml 파일에는 클래스 이름, 테스트 이름, 스위트 이름과 같은 모든 구성 정보가 포함되어 있습니다.

Flipkart.java

package com.suite1;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class Flipkart {

    WebDriver driver = new FirefoxDriver();
    String username = ""; // Change to your username and password
    String password = "";

    // This method navigates to the Flipkart URL
    @BeforeClass
    public void init() {
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
        driver.navigate().to("https://www.flipkart.com");
    }

    // Log in to Flipkart
    @Test
    public void login() {
        driver.findElement(By.partialLinkText("Login")).click();
        driver.findElement(By.cssSelector(".fk-input.login-form-input.user-email")).sendKeys(username);
        driver.findElement(By.cssSelector(".fk-input.login-form-input.user-pwd")).sendKeys(password);
        driver.findElement(By.cssSelector(".submit-btn.login-btn.btn")).click();
    }

    // Search for a product
    @Test
    public void searchAndSelectProduct() {
        driver.findElement(By.id("fk-top-search-box")).sendKeys("moto g3");
        driver.findElement(By.cssSelector("search-bar-submit.fk-font-13.fk-font-bold")).click();
        String css = ".gd-row.browse-grid-row:nth-of-type(1) > div:nth-child(1)>div>div:nth-child(2)>div>a";
        driver.findElement(By.cssSelector(css)).click();
    }

    @Test
    public void buyAndRemoveFromCart() {
        driver.findElement(By.cssSelector(".btn-express-checkout.btn-big.current")).click();
        driver.findElement(By.cssSelector(".remove.fk-inline-block")).click();
        Alert a = driver.switchTo().alert();
        a.accept();
    }

    @Test
    public void logout() {
        Actions s = new Actions(driver);
        WebElement user = driver.findElement(By.partialLinkText(username));
        s.moveToElement(user).build().perform();
        driver.findElement(By.linkText("Logout")).click();
    }

    @AfterClass
    public void quit() {
        driver.close();
    }
}

SnapDeal.java

package com.suite2;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class SnapDeal {

    WebDriver driver = new FirefoxDriver();
    String username = ""; // Change to your username and password
    String password = "";
    String pinCode = "";

    // This method navigates to the Snapdeal URL
    @BeforeClass
    public void init() {
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
        driver.navigate().to("https://www.snapdeal.com");
    }

    @Test
    public void login() {
        driver.findElement(By.xpath("//button[text()='Login']")).click();
        driver.switchTo().frame("loginIframe");
        driver.findElement(By.cssSelector("div[onClick='getLoginForm()']")).click();
        driver.findElement(By.id("j_username")).sendKeys(username);
        driver.findElement(By.id("j_password_login")).sendKeys(password);
        driver.findElement(By.id("signin_submit")).click();
        driver.switchTo().defaultContent();
    }

    @Test
    public void searchAndSelectProduct() {
        driver.findElement(By.cssSelector(".col-xs-20.searchformInput.keyword")).sendKeys("iphone 6s");
        driver.findElement(By.cssSelector(".sd-icon.sd-icon-search")).click();
        String css = ".product_grid_row:nth-of-type(1)>div:nth-child(1)";
        driver.findElement(By.cssSelector(css)).click();
    }

    @Test
    public void buyAndRemoveFromCart() {
        driver.findElement(By.xpath("//li[contains(text(),'Silver')]")).click();
        driver.findElement(By.id("pincode-check")).sendKeys(pinCode);
        driver.findElement(By.id("buy-button-id")).click();
        driver.findElement(By.cssSelector("i[title='Delete Item']")).click();
        Alert a = driver.switchTo().alert();
        a.accept();
    }

    @Test
    public void logout() {
        driver.findElement(By.linkText("START SHOPPING NOW")).click();
        Actions s = new Actions(driver);
        WebElement user = driver.findElement(By.cssSelector(".sd-icon.sd-icon-user"));
        s.moveToElement(user).build().perform();
        driver.findElement(By.linkText("Logout")).click();
    }

    @AfterClass
    public void quit() {
        driver.close();
    }
}

TestNG. XML

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite thread-count="2" verbose="1" name="Gmail Suite" parallel="tests">

  <test name="flipkart">
    <classes>
      <class name="com.suite1.Flipkart"/>
    </classes>
  </test>

  <test name="Myntra">
    <classes>
      <class name="com.suite2.SnapDeal"/>
    </classes>
  </test>
</suite>

최종 프로젝트 구조는 아래 예시와 같습니다.

만들기 TestNG테스트 실행을 위한 .xml 파일

2단계) 병렬 실행 TestNG

위의 XML 파일을 저장한 후, 다음 단계는 병렬 테스트를 실행하는 것입니다. 코드는 아래와 같습니다.

병렬 실행 TestNG

1) 스레드 수스레드 수를 정의합니다. TestNG 병렬 실행을 위해 CPU를 가동할 수 있습니다. 값이 높을수록 CPU 제한까지 더 많은 테스트를 동시에 실행합니다.

2) 장황한콘솔에 로그 실행 세부 정보를 기록합니다. 허용되는 값은 1에서 10까지입니다. 값이 높을수록 더 자세하고 세분화된 로그가 생성됩니다.

3) 이름스위트룸 이름입니다. 바로 "Gmail 모음곡".

4) 병렬: 말한다 TestNG 동시에 실행할 항목을 지정합니다. 유효한 값은 테스트, 클래스, 메서드 또는 인스턴스입니다. 기본값은 입니다. 없음.

testng.xml 파일을 마우스 오른쪽 버튼으로 클릭하고 선택하세요. 실행 계정 > TestNG 스위트완료되면 통합 결과를 확인할 수 있습니다.

위 코드를 실행하면 다음과 같은 출력이 나옵니다.

출력:

병렬 실행 TestNG

1) testng.xml에 정의된 테스트 스위트의 이름.

병렬 실행 TestNG

2) testng.xml에 정의된 테스트의 이름.

병렬 실행 TestNG

3) testng.xml에 선언된 클래스의 이름.

병렬 실행 TestNG

4) .java 파일에서 @Test 어노테이션이 붙은 메서드 이름.

병렬 실행 TestNG

SnapDeal 테스트에도 동일한 흐름이 적용되므로 두 클래스가 나란히 실행됩니다.

3단계) ​​하나의 상위 testng.xml 파일에서 여러 테스트 스위트 실행

규모가 큰 프로젝트에서 흔히 요구되는 사항 중 하나는 여러 개의 testng.xml 파일을 하나의 트리거로 연결하는 것입니다. TestNG 7.x 버전은 자식 버전을 참조하는 부모 버전 제품군을 지원합니다. 스위트 파일 각 자식 프로세스가 자체 스레드 수, 리스너 및 매개변수를 유지할 수 있도록 항목을 지정합니다. 각 자식 프로세스 모음을 별도로 저장한 다음 부모 프로세스가 해당 경로를 가리키도록 합니다. 부모 프로세스 모음에서 부모 파일만 실행합니다. Eclipse메이븐(Maven)이나 명령줄을 사용할 수 있습니다.

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Parent Suite" parallel="tests" thread-count="4">
  <suite-files>
    <suite-file path="./flipkart-suite.xml"/>
    <suite-file path="./snapdeal-suite.xml"/>
  </suite-files>
</suite>

이 패턴은 회귀 테스트, 스모크 테스트, 건전성 테스트를 분리하면서도 재사용할 수 있도록 합니다. 또한 Maven Surefire에서 상위 파일을 실행하도록 설정할 수도 있습니다. <suiteXmlFile>parent-suite.xml</suiteXmlFile> 플러그인 구성 내부에는 동일한 병렬 레이아웃이 지속적 통합 파이프라인에서 작동하도록 하는 기능이 있습니다.

4단계) 병렬을 위한 최고의 사례 TestNG 실행

  • 핀 TestNG 7.x: TestNG 7.10 이상 버전 Selenium 4. 따라서 W3C 표준을 준수하는 드라이버는 스레드 전반에 걸쳐 일관되게 동작합니다.
  • 상태 공유를 피하십시오: 를 이동 웹드라이버 각 스레드가 자체 세션을 유지하도록 필드를 ThreadLocal에 저장합니다.
  • 스레드 개수 조정: 먼저 CPU 코어 수를 확인하고, 그 다음 이메일로 전송되는 HTML 보고서와 그리드 로드를 살펴본 후, 문제가 해결되면 레벨을 올리세요.
  • 테스트 데이터를 분리합니다: 로그인이 겹치지 않도록 스레드별로 고유한 사용자, 장바구니 및 PIN 코드를 사용하세요.
  • 오류 발생 시 스크린샷을 캡처하세요. 그것들을 다음을 통해 연결하세요 ITestListener 불안정한 병렬 실행을 더 빠르게 디버깅할 수 있습니다.
  • AI 지원을 활용하세요: 같은 도구 Testimmabl과 CodiumAI는 불안정한 테스트를 표시하고 다음 실행 전에 안정적인 선택기를 제안할 수 있습니다.

맺음말

위 예시는 사용 방법을 보여줍니다. TestNG 병렬 테스트를 실행하기 위해. TestNG 7.x 버전에서는 단일 XML 파일을 사용하여 여러 테스트 클래스를 실행하고, 여러 하위 스위트를 연결하고, 병렬 스레드를 조정할 수 있으므로 대규모 테스트도 처리할 수 있습니다. Selenium 프로젝트가 훨씬 빨리 완료됩니다.

자주 묻는 질문

각 수업을 별도의 공간에 배치하세요 testng.xml 파일 안에 `parallel=”tests”` 태그를 추가하고 스레드 수를 최소 2로 설정하세요. TestNG 두 테스트를 각각 별도의 스레드에서 시작하므로 클래스가 순차적으로 실행되는 것이 아니라 동시에 실행됩니다.

네. 하위 파일 목록을 포함하는 상위 스위트를 구축하세요. 각 하위 스위트 파일 경로는 자체 구성을 실행합니다. 이 패턴은 다음과 같은 환경에서 작동합니다. Eclipse, 메이븐 슈어파이어, 그리고 Gradle그리고 다음으로부터 지원을 받습니다. TestNG 6 버전 이후부터, 현재의 7.x 버전을 포함합니다.

parallel 속성은 테스트, 클래스, 메서드, 인스턴스 또는 없음 중 하나를 허용합니다. 각 경우에 테스트를 선택하세요. `@Test` 태그는 자체 포함을 의미하고, 클래스는 전체 클래스 격리를 의미하며, 메서드는 개별 `@Test` 메서드가 스레드로부터 안전한 경우를 의미합니다. 기본값은 `none`이며, 이 경우 모든 것이 순차적으로 실행됩니다.

ThreadLocal을 사용하세요 또는 드라이버를 정적 필드로 초기화하는 대신 `@BeforeMethod` 블록 내에서 초기화할 수 있습니다. 이렇게 하면 각 스레드가 자체 브라우저 세션을 소유하게 되어 병렬 처리를 방해하는 경쟁 조건을 제거할 수 있습니다. TestNG 계속하다 Selenium 그리드.

AI 오케스트레이터는 이전 실행 데이터를 분석하여 오류를 예측하고, 불안정한 테스트를 격리하고, 느린 테스트의 순서를 재조정합니다. Launchable과 같은 플랫폼이 이러한 기능을 제공합니다. Testim그리고 mabl 플러그를 꽂으세요 TestNG 따라서 실패 가능성이 가장 높은 스위트부터 먼저 실행되므로 지속적 통합 서버의 피드백 루프가 단축됩니다.

네. Launchable과 BuildPulse의 AI 기반 스케줄러는 테스트별 과거 실행 시간과 실패율을 측정하여 testng.xml 파일을 균형 잡힌 샤드로 분할합니다. 각 샤드는 별도의 에이전트에서 실행되므로 전체 실행 시간은 줄어들면서 병렬 활용률은 높게 유지됩니다.

이 게시물을 요약하면 다음과 같습니다.