NỘI DUNG BÀI HỌC

✅ Cài đặt và sử dụng Extent report
✅ Cài đặt và sử dụng Allure report

Nếu bạn chưa biết mô hình đối tượng trang (Page Object) thì trước khi bắt đầu bài viết này mình khuyên bạn nên xem lại bài viết mô hình POM trong Selenium Java của An. Tại vì những ví dụ sẽ chạy test case hoàn chỉnh nên An chạy code theo dạng page object cho nhanh á.

Nội dung chính:


1. Cài đặt Extent Report trong Selenium Java


Bây giờ, mình sẽ thêm gói Extent Report và trình lắng nghe Listeners trong pom.xml như được hiển thị bên dưới.


Cấu trúc source tổng quát như này

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

 

Bước 1: Thêm thư viện Extent Reports vào pom.xml trong Maven Project

<!-- https://mvnrepository.com/artifact/com.aventstack/extentreports -->
<dependency>
	<groupId>com.aventstack</groupId>
	<artifactId>extentreports</artifactId>
	<version>5.0.9</version>
</dependency>

Hoặc vào link này để download bản tùy ý:

https://mvnrepository.com/artifact/com.aventstack/extentreports

 

Bước 2: Thêm Extent Reports class

An đã tạo package "extentreports" trong package "utils" và thêm hai class bên dưới vào package đó. (ảnh minh họa trên cùng)


+ ExtentManager Class:

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;

public class ExtentManager {

    private static final ExtentReports extentReports = new ExtentReports();

    public synchronized static ExtentReports getExtentReports() {
        ExtentSparkReporter reporter = new ExtentSparkReporter("./ExtentReports/ExtentReport.html");
        reporter.config().setReportName("Demo Extent Report");
        extentReports.attachReporter(reporter);
        extentReports.setSystemInfo("Framework Name", "Selenium Java Framework | Anh Tester");
        extentReports.setSystemInfo("Author", "Anh Tester");
        return extentReports;
    }
}


Cái "./ExtentReports/ExtentReport.html" là đường dẫn xuất ra file html của report. Folder "ExtentReports" sẽ nằm ngoài cùng ngang cấp src.


+ ExtentTestManager Class:

import anhtester.com.browsers.BaseSetup;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.Status;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

import java.util.HashMap;
import java.util.Map;

public class ExtentTestManager {
    static Map<Integer, ExtentTest> extentTestMap = new HashMap<>();
    static ExtentReports extent = ExtentManager.getExtentReports();

    public static ExtentTest getTest() {
        return extentTestMap.get((int) Thread.currentThread().getId());
    }

    public static synchronized ExtentTest saveToReport(String testName, String desc) {
        ExtentTest test = extent.createTest(testName, desc);
        extentTestMap.put((int) Thread.currentThread().getId(), test);
        return test;
    }

    public WebDriver getDriver() {
        WebDriver driver = BaseSetup.getDriver();
        return driver;
    }

    public static void addScreenShot(String message) {
        String base64Image = "data:image/png;base64,"
                + ((TakesScreenshot) BaseSetup.getDriver()).getScreenshotAs(OutputType.BASE64);
        getTest().log(Status.INFO, message,
                MediaEntityBuilder.createScreenCaptureFromBase64String(base64Image).build());
    }

    public static void addScreenShot(Status status, String message) {

        String base64Image = "data:image/png;base64,"
                + ((TakesScreenshot) BaseSetup.getDriver()).getScreenshotAs(OutputType.BASE64);
        getTest().log(status, message,
                MediaEntityBuilder.createScreenCaptureFromBase64String(base64Image).build());
    }

    public static void logMessage(String message) {
        getTest().log(Status.INFO, message);
    }

    public static void logMessage(Status status, String message) {
        getTest().log(status, message);
    }

}


Lưu ý: cái BaseSetup.getDriver() có nghĩa là lấy giá trị driver hiện hành. Nếu các bạn đã design theo kiểu nào thì lấy ra theo kiểu đó chứ không phải luôn như vậy nhé. Có thể là DriverManager.getDriver()

 

 

  • extentTestMap lưu giữ thông tin của id luồng và các cá thể ExtentTest.
  • Phiên bản ExtentReports được tạo bằng cách gọi phương thức createExtentReports () từ ExtentManager.
  • Tại phương thức saveToReport(), một phiên bản của ExtentTest đã được tạo và đưa vào extentTestMap với id luồng hiện tại.
  • Tại phương thức getTest(), trả về cá thể ExtentTest trong scopeTestMap bằng cách sử dụng id luồng hiện tại.


Bước 3: Add Listener class

Chổ này bài trước mình học là tạo TestListener rồi đúng không. Nay mình tạo thêm cái mới là "ReportListener" để cho dễ tùy chọn. (hình minh họa trên cùng)

import anhtester.com.browsers.BaseSetup;
import anhtester.com.utils.extentreports.ExtentTestManager;
import anhtester.com.utils.helpers.CaptureHelpers;
import anhtester.com.utils.logs.Log;
import com.aventstack.extentreports.Status;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

import static anhtester.com.utils.extentreports.ExtentManager.getExtentReports;

public class ReportListener implements ITestListener {

    WebDriver driver;

    public String getTestName(ITestResult result) {
        return result.getTestName() != null ? result.getTestName()
                : result.getMethod().getConstructorOrMethod().getName();
    }

    public String getTestDescription(ITestResult result) {
        return result.getMethod().getDescription() != null ? result.getMethod().getDescription() : getTestName(result);
    }

    @Override
    public void onStart(ITestContext iTestContext) {
        driver = BaseSetup.getDriver();
        Log.info("Start testing " + iTestContext.getName());
        iTestContext.setAttribute("WebDriver", driver);
        //Gọi hàm startRecord video trong CaptureHelpers class
        try {
            CaptureHelpers.startRecord(iTestContext.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFinish(ITestContext iTestContext) {
        Log.info("End testing " + iTestContext.getName());
        //Kết thúc và thực thi Extents Report
        getExtentReports().flush();
        //Gọi hàm stopRecord video trong CaptureHelpers class
        CaptureHelpers.stopRecord();
    }

    @Override
    public void onTestStart(ITestResult iTestResult) {
        Log.info(getTestName(iTestResult) + " test is starting...");
        ExtentTestManager.saveToReport(iTestResult.getName(), iTestResult.getTestName());
    }

    @Override
    public void onTestSuccess(ITestResult iTestResult) {
        Log.info(getTestName(iTestResult) + " test is passed.");
        //ExtentReports log operation for passed tests.
        ExtentTestManager.logMessage(Status.PASS, getTestDescription(iTestResult));
    }

    @Override
    public void onTestFailure(ITestResult iTestResult) {
        Log.error(result.getThrowable().toString());
        Log.error(getTestName(iTestResult) + " test is failed.");

        ExtentTestManager.addScreenShot(Status.FAIL, getTestName(iTestResult));
        ExtentTestManager.logMessage(Status.FAIL, iTestResult.getThrowable().toString());
    }

    @Override
    public void onTestSkipped(ITestResult iTestResult) {
        Log.warn(getTestName(iTestResult) + " test is skipped.");
        ExtentTestManager.logMessage(Status.SKIP, getTestName(iTestResult) + " test is skipped.");
        ExtentTestManager.logMessage(Status.SKIP, iTestResult.getThrowable().toString());
    }

    @Override
    public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) {
        Log.error("Test failed but it is in defined success ratio " + getTestName(iTestResult));
        ExtentTestManager.logMessage("Test failed but it is in defined success ratio " + getTestName(iTestResult));
    }
}


Chổ CaptureHelpers có gọi cái Record video nếu bạn chưa có thì xem lại bài trước hoặc bỏ nó luôn cũng được nhen.


Còn cái Log class thì mình đã thêm hôm trước trong bài ghi Log rồi nên dùng lại thôi nhen.

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log {
    //Initialize Log4j instance
    private static final Logger Log =  LogManager.getLogger(Log.class);

    //Info Level Logs
    public static void info (String message) {
        Log.info(message);
    }

    //Warn Level Logs
    public static void warn (String message) {
        Log.warn(message);
    }

    //Error Level Logs
    public static void error (String message) {
        Log.error(message);
    }

    //Fatal Level Logs
    public static void fatal (String message) {
        Log.fatal(message);
    }

    //Debug Level Logs
    public static void debug (String message) {
        Log.debug(message);
    }
}

 

Bước 4: Gọi ReportListener class vào test case

Chổ này thì mình có thể gọi 2 cấp độ class hoặc suite tùy ý như bài hôm trước về Listener An đã nói rồi á. Có quên thì xem lại phát biết ngay nè.

Gọi trong Class:

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Gọi trong Suite file XML:

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


An thiết lặp cả class Test case như này. Các bạn theo dõi các bài trước là hiểu ngay. Từ bài Page Object á.

import anhtester.com.projects.crm.pages.DashboardPage;
import anhtester.com.projects.crm.pages.SignInPage;
import anhtester.com.utils.listeners.ReportListener;
import anhtester.com.utils.helpers.WebUI;
import anhtester.com.projects.crm.pages.AddProjectPage;
import anhtester.com.projects.crm.pages.ProjectPage;

import anhtester.com.browsers.BaseSetup;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.*;

@Listeners(ReportListener.class)
public class ProjectTest {

    private WebDriver driver;
    private SignInPage signInPage;
    private DashboardPage dashboardPage;
    private ProjectPage projectPage;
    private AddProjectPage addProjectPage;
    private WebUI webUI;

    @BeforeClass
    public void setupBrowser() {
        //driver = getDriver();  //extends BaseSetup
        driver = new BaseSetup().setupDriver("chrome");
        webUI = new WebUI(driver);
    }

    @Test(priority = 1, description = "Sign in page to CRM system")
    public void signInPage(){

        signInPage = new SignInPage(driver);
        driver.get("https://crm.anhtester.com");

        dashboardPage = signInPage.signIn("tld01@mailinator.com", "123456");
        webUI.waitForPageLoaded();
    }

    @Test(priority = 2, description = "Click Project menu to open Project page")
    public void openProjectPage() {

        webUI.waitForPageLoaded();
        projectPage = dashboardPage.openProjectsPage();
    }

    @Test(priority = 3)
    public void openAddProjectPage(){
        webUI.waitForPageLoaded();
        addProjectPage = projectPage.addProject();
    }

    @Test(priority = 4)
    public void addProject() throws InterruptedException {
        // Kiểm tra Text tồn tại trên trang
        // Hoặc đã dùng verifyElementText để kiểm tra trong hàm saveProduct
        // webUI.verifyPageLoaded("Add project");
        addProjectPage.saveProduct();
    }

    @Test(priority = 5, description = "Tìm kiếm Project sau khi Add")
    public void searchProject() throws InterruptedException {
        webUI.waitForPageLoaded();
        projectPage.enterSearchValue("PD2012");
        Thread.sleep(2000);
        projectPage.checkSearchTableByColumn(2, "PD2013"); //Fail
    }

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

}


Yeah vậy xong rồi đó. Chạy test case thôi nào.

Report sẽ xuất ra tại thư mục đường dẫn như mình chỉ định trên: "./ExtentReports/ExtentReport.html

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Chúng ta mở file report html lên bằng cách click chuột phải chọn Open In -> Browser -> "Chrome hoặc Edge...tùy ý"

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Report dạng Step kèm description nếu chúng ta có điền thuộc dính description vào @Test. Không có thì nso sẽ để trống. Bạn có thể custom nó ở class "ReportListener" á.

[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Và như trong ReportListener thì mình setup là test case nào Fail sẽ có Screenshot đi kèm á. Các bạn click chọn "base64 img" màu tím tím á nó sẽ hiển thị ngay.

[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Report dạng Chart khi click chọn option chart icon thứ 2 á.

[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Song song nó cũng ghi Log vào file cho mình luôn

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Chúng ta có thể thêm các step auto vào report thông qua WebUI keyword hoặc một class nào đó bất kỳ chứa các action xử lý về auto cho test case.

WebUI class:

package anhtester.com.utils;

import anhtester.com.driver.DriverManager;
import anhtester.com.reports.ExtentTestManager;
import com.aventstack.extentreports.Status;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.time.Duration;
import java.util.List;

public class WebUI {

    private final static int TIMEOUT = 10;
    private final static double STEP_TIME = 0;
    private final static int PAGE_LOAD_TIMEOUT = 20;

    public static void sleep(double second) {
        try {
            Thread.sleep((long) (1000 * second));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static void logConsole(Object message) {
        System.out.println(message);
    }

    public static WebElement getWebElement(By by) {
        return DriverManager.getDriver().findElement(by);
    }

    public static List<WebElement> getWebElements(By by) {
        return DriverManager.getDriver().findElements(by);
    }

    public static void verifyEquals(Object actual, Object expected) {
        waitForPageLoaded();
        sleep(STEP_TIME);
        Log.info("Verify equals: " + actual + " and " + expected);
        ExtentTestManager.logMessage(Status.PASS, "Verify equals: " + actual + " and " + expected);
        Assert.assertEquals(actual, expected, "Fail. Not match. '" + actual.toString() + "' != '" + expected.toString() + "'");
    }

    public static void verifyEquals(Object actual, Object expected, String message) {
        waitForPageLoaded();
        sleep(STEP_TIME);
        Log.info("Verify equals: " + actual + " and " + expected);
        ExtentTestManager.logMessage(Status.PASS, "Verify equals: " + actual + " and " + expected);
        Assert.assertEquals(actual, expected, message);
    }

    public static Boolean checkElementExist(By by) {
        waitForPageLoaded();
        waitForElementVisible(by);
        sleep(2);
        List<WebElement> listElement = getWebElements(by);

        if (listElement.size() > 0) {
            System.out.println("checkElementExist: " + true + " --- " + by);
            return true;
        } else {
            System.out.println("checkElementExist: " + false + " --- " + by);
            return false;
        }
    }

    public static void openURL(String url) {
        DriverManager.getDriver().get(url);
        sleep(STEP_TIME);
        Log.info("Open: " + url);
        ExtentTestManager.logMessage(Status.PASS, "Open URL: " + url);
        waitForPageLoaded();
    }

    public static void clickElement(By by) {
        waitForPageLoaded();
        waitForElementVisible(by);
        sleep(STEP_TIME);
        getWebElement(by).click();
        Log.info("Click element: " + by);
        ExtentTestManager.logMessage(Status.PASS, "Click element: " + by);
    }

    public static void clickElement(By by, long timeout) {
        waitForPageLoaded();
        waitForElementVisible(by);
        sleep(STEP_TIME);
        getWebElement(by).click();
        Log.info("Click element: " + by);
        ExtentTestManager.logMessage(Status.PASS, "Click element: " + by);
    }

    public static void setText(By by, String value) {
        waitForPageLoaded();
        waitForElementVisible(by);
        sleep(STEP_TIME);
        getWebElement(by).sendKeys(value);
        Log.info("Set text: " + value + " on element " + by);
        ExtentTestManager.logMessage(Status.PASS, "Set text: " + value + " on element " + by);
    }

    public static String getElementText(By by) {
        waitForPageLoaded();
        waitForElementVisible(by);
        sleep(STEP_TIME);
        String text = getWebElement(by).getText();
        Log.info("Get text: " + text);
        ExtentTestManager.logMessage(Status.PASS, "Get text: " + text);
        return text; //Trả về một giá trị kiểu String
    }

    //Wait for Element

    public static void waitForElementVisible(By by) {
        try {
            WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(TIMEOUT), Duration.ofMillis(500));
            wait.until(ExpectedConditions.visibilityOfElementLocated(by));
        } catch (Throwable error) {
            Log.error("Timeout waiting for the element Visible. " + by.toString());
            Assert.fail("Timeout waiting for the element Visible. " + by.toString());
        }
    }

    public static void waitForElementVisible(By by, int timeOut) {
        try {
            WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(timeOut), Duration.ofMillis(500));
            wait.until(ExpectedConditions.visibilityOfElementLocated(by));
        } catch (Throwable error) {
            Log.error("Timeout waiting for the element Visible. " + by.toString());
            Assert.fail("Timeout waiting for the element Visible. " + by.toString());
        }
    }

    public static void waitForElementPresent(By by) {
        try {
            WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(TIMEOUT), Duration.ofMillis(500));
            wait.until(ExpectedConditions.presenceOfElementLocated(by));
        } catch (Throwable error) {
            Log.error("Element not exist. " + by.toString());
            Assert.fail("Element not exist. " + by.toString());
        }
    }

    public static void waitForElementPresent(By by, int timeOut) {
        try {
            WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(timeOut), Duration.ofMillis(500));
            wait.until(ExpectedConditions.presenceOfElementLocated(by));
        } catch (Throwable error) {
            Log.error("Element not exist. " + by.toString());
            Assert.fail("Element not exist. " + by.toString());

        }
    }

    public static void waitForElementClickable(By by) {
        try {
            WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(TIMEOUT), Duration.ofMillis(500));
            wait.until(ExpectedConditions.elementToBeClickable(getWebElement(by)));
        } catch (Throwable error) {
            Assert.fail("Timeout waiting for the element ready to click. " + by.toString());
            Log.info("Timeout waiting for the element ready to click. " + by.toString());
        }
    }

    public static void waitForElementClickable(By by, int timeOut) {
        try {
            WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(timeOut), Duration.ofMillis(500));
            wait.until(ExpectedConditions.elementToBeClickable(getWebElement(by)));
        } catch (Throwable error) {
            Assert.fail("Timeout waiting for the element ready to click. " + by.toString());
            Log.info("Timeout waiting for the element ready to click. " + by.toString());
        }
    }

    //Vài hàm bổ trợ nâng cao hơn

    public static void scrollToElement(By element) {
        JavascriptExecutor js = (JavascriptExecutor) DriverManager.getDriver();
        js.executeScript("arguments[0].scrollIntoView(true);", getWebElement(element));
    }

    public static void scrollToElement(WebElement element) {
        JavascriptExecutor js = (JavascriptExecutor) DriverManager.getDriver();
        js.executeScript("arguments[0].scrollIntoView(true);", element);
    }

    public static void scrollToPosition(int X, int Y) {
        JavascriptExecutor js = (JavascriptExecutor) DriverManager.getDriver();
        js.executeScript("window.scrollTo(" + X + "," + Y + ");");
    }

    public static boolean moveToElement(By toElement) {
        try {
            Actions action = new Actions(DriverManager.getDriver());
            action.moveToElement(getWebElement(toElement)).release(getWebElement(toElement)).build().perform();
            return true;
        } catch (Exception e) {
            Log.info(e.getMessage());
            return false;
        }
    }

    public static boolean moveToOffset(int X, int Y) {
        try {
            Actions action = new Actions(DriverManager.getDriver());
            action.moveByOffset(X, Y).build().perform();
            return true;
        } catch (Exception e) {
            Log.info(e.getMessage());
            return false;
        }
    }

    public static boolean hoverElement(By by) {
        try {
            Actions action = new Actions(DriverManager.getDriver());
            action.moveToElement(getWebElement(by)).perform();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean mouseHover(By by) {
        try {
            Actions action = new Actions(DriverManager.getDriver());
            action.moveToElement(getWebElement(by)).perform();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean dragAndDrop(By fromElement, By toElement) {
        try {
            Actions action = new Actions(DriverManager.getDriver());
            action.dragAndDrop(getWebElement(fromElement), getWebElement(toElement)).perform();
            //action.clickAndHold(getWebElement(fromElement)).moveToElement(getWebElement(toElement)).release(getWebElement(toElement)).build().perform();
            return true;
        } catch (Exception e) {
            Log.info(e.getMessage());
            return false;
        }
    }

    public static boolean dragAndDropElement(By fromElement, By toElement) {
        try {
            Actions action = new Actions(DriverManager.getDriver());
            action.clickAndHold(getWebElement(fromElement)).moveToElement(getWebElement(toElement)).release(getWebElement(toElement)).build().perform();
            return true;
        } catch (Exception e) {
            Log.info(e.getMessage());
            return false;
        }
    }

    public static boolean dragAndDropOffset(By fromElement, int X, int Y) {
        try {
            Actions action = new Actions(DriverManager.getDriver());
            //Tính từ vị trí click chuột đầu tiên (clickAndHold)
            action.clickAndHold(getWebElement(fromElement)).pause(1).moveByOffset(X, Y).release().build().perform();
            return true;
        } catch (Exception e) {
            Log.info(e.getMessage());
            return false;
        }
    }

    public static boolean pressENTER() {
        try {
            Robot robot = new Robot();
            robot.keyPress(KeyEvent.VK_ENTER);
            robot.keyRelease(KeyEvent.VK_ENTER);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean pressESC() {
        try {
            Robot robot = new Robot();
            robot.keyPress(KeyEvent.VK_ESCAPE);
            robot.keyRelease(KeyEvent.VK_ESCAPE);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean pressF11() {
        try {
            Robot robot = new Robot();
            robot.keyPress(KeyEvent.VK_F11);
            robot.keyRelease(KeyEvent.VK_F11);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * @param by truyền vào đối tượng element dạng By
     * @return Tô màu viền đỏ cho Element trên website
     */
    public static WebElement highLightElement(By by) {
        // Tô màu border ngoài chính element chỉ định - màu đỏ (có thể đổi màu khác)
        if (DriverManager.getDriver() instanceof JavascriptExecutor) {
            ((JavascriptExecutor) DriverManager.getDriver()).executeScript("arguments[0].style.border='3px solid red'", getWebElement(by));
            sleep(1);
        }
        return getWebElement(by);
    }

    /**
     * Wait for Page
     * Chờ đợi trang tải xong (Javascript) với thời gian thiết lập sẵn
     */
    public static void waitForPageLoaded() {
        WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(PAGE_LOAD_TIMEOUT), Duration.ofMillis(500));
        JavascriptExecutor js = (JavascriptExecutor) DriverManager.getDriver();

        // wait for Javascript to loaded
        ExpectedCondition<Boolean> jsLoad = driver -> ((JavascriptExecutor) DriverManager.getDriver()).executeScript("return document.readyState").toString().equals("complete");

        //Get JS is Ready
        boolean jsReady = js.executeScript("return document.readyState").toString().equals("complete");

        //Wait Javascript until it is Ready!
        if (!jsReady) {
            Log.info("Javascript in NOT Ready!");
            //Wait for Javascript to load
            try {
                wait.until(jsLoad);
            } catch (Throwable error) {
                error.printStackTrace();
                Assert.fail("Timeout waiting for page load (Javascript). (" + PAGE_LOAD_TIMEOUT + "s)");
            }
        }
    }

    /**
     * Chờ đợi JQuery tải xong với thời gian thiết lập sẵn
     */
    public static void waitForJQueryLoad() {
        WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(PAGE_LOAD_TIMEOUT), Duration.ofMillis(500));
        JavascriptExecutor js = (JavascriptExecutor) DriverManager.getDriver();

        //Wait for jQuery to load
        ExpectedCondition<Boolean> jQueryLoad = driver -> {
            assert driver != null;
            return ((Long) ((JavascriptExecutor) DriverManager.getDriver()).executeScript("return jQuery.active") == 0);
        };

        //Get JQuery is Ready
        boolean jqueryReady = (Boolean) js.executeScript("return jQuery.active==0");

        //Wait JQuery until it is Ready!
        if (!jqueryReady) {
            Log.info("JQuery is NOT Ready!");
            try {
                //Wait for jQuery to load
                wait.until(jQueryLoad);
            } catch (Throwable error) {
                Assert.fail("Timeout waiting for JQuery load. (" + PAGE_LOAD_TIMEOUT + "s)");
            }
        }
    }

    //Wait for Angular Load

    /**
     * Chờ đợi Angular tải xong với thời gian thiết lập sẵn
     */
    public static void waitForAngularLoad() {
        WebDriverWait wait = new WebDriverWait(DriverManager.getDriver(), Duration.ofSeconds(PAGE_LOAD_TIMEOUT), Duration.ofMillis(500));
        JavascriptExecutor js = (JavascriptExecutor) DriverManager.getDriver();
        final String angularReadyScript = "return angular.element(document).injector().get('$http').pendingRequests.length === 0";

        //Wait for ANGULAR to load
        ExpectedCondition<Boolean> angularLoad = driver -> {
            assert driver != null;
            return Boolean.valueOf(((JavascriptExecutor) DriverManager.getDriver()).executeScript(angularReadyScript).toString());
        };

        //Get Angular is Ready
        boolean angularReady = Boolean.parseBoolean(js.executeScript(angularReadyScript).toString());

        //Wait ANGULAR until it is Ready!
        if (!angularReady) {
            Log.info("Angular is NOT Ready!");
            //Wait for Angular to load
            try {
                //Wait for jQuery to load
                wait.until(angularLoad);
            } catch (Throwable error) {
                Assert.fail("Timeout waiting for Angular load. (" + PAGE_LOAD_TIMEOUT + "s)");
            }
        }

    }

}


Trên là An thêm vào 5 hàm cơ bản: Open URL, clickElement, setText, getElementText, verifyEquals

Các bạn có thể thêm nữa nhen.

Khi chạy sẽ có kết quả như sau:

[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

 

2. Cài đặt Allure Report trong Selenium Java


Trước tiên, mình sẽ thêm biến môi trường Allure-2.14.0 vào máy tính mình như cài đặt biến môi trường Java JDK dị á.

Tải gói cho Window tại đây

Vì An chỉ dạy trên môi trường máy window nên có gì các bạn kiếm bản cho MacOS hoặc Linux như hình hướng dẫn bên dưới:

Link download theo phiên bản: https://mvnrepository.com/artifact/io.qameta.allure/allure-testng

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Tiếp theo thì các bạn giải nén ra để nó vào ổ C (ổ chứa hệ điều hành) để tạo biến môi trường trong máy ổn định.

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Nó giống với setup biến môi trường Java JDK á. Các bạn xem video An hướng dẫn luôn phần này cho nhé. Ghi blog dài dòng khó hiểu nữa =))


Tiếp theo là dô vấn đề cấu hình Allure Report nào !!!

Bước 1: Thêm thư viện Allure Reports vào pom.xml trong Maven Project

<!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-testng -->
<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-testng</artifactId>
    <version>2.19.0</version>
</dependency>

(Cập nhật ngày 27/09/2022)

Hoặc vào link này để download bản tùy ý:

https://mvnrepository.com/artifact/io.qameta.allure/allure-testng


Đây là tất cả các thư viện AN đã add vào pom.xml của cả project đây:

<?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>com.anhtester</groupId>
    <artifactId>ProjectWithMaven</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>15</maven.compiler.source>
        <maven.compiler.target>15</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.testng/testng -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.4.0</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.3.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.31</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.0.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.4.0</version>
            <scope>compile</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.github.stephenc.monte/monte-screen-recorder -->
        <dependency>
            <groupId>com.github.stephenc.monte</groupId>
            <artifactId>monte-screen-recorder</artifactId>
            <version>0.7.7.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.19.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.aventstack/extentreports -->
        <dependency>
            <groupId>com.aventstack</groupId>
            <artifactId>extentreports</artifactId>
            <version>5.0.9</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-testng -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <version>2.19.0</version>
        </dependency>

    </dependencies>

</project>



Bước 2: Thêm tùy chỉnh Allure Reports vào ReportListener class

 

package anhtester.com.utils.listeners;

import anhtester.com.browsers.BaseSetup;
import anhtester.com.utils.extentreports.ExtentTestManager;
import anhtester.com.utils.helpers.CaptureHelpers;
import anhtester.com.utils.logs.Log;
import com.aventstack.extentreports.Status;
import io.qameta.allure.Attachment;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

import static anhtester.com.utils.extentreports.ExtentManager.getExtentReports;

public class ReportListener implements ITestListener {

    WebDriver driver;

    public String getTestName(ITestResult result) {
        return result.getTestName() != null ? result.getTestName()
                : result.getMethod().getConstructorOrMethod().getName();
    }

    public String getTestDescription(ITestResult result) {
        return result.getMethod().getDescription() != null ? result.getMethod().getDescription() : getTestName(result);
    }

    //Text attachments for Allure
    @Attachment(value = "{0}", type = "text/plain")
    public static String saveTextLog(String message) {
        return message;
    }

    //HTML attachments for Allure
    @Attachment(value = "{0}", type = "text/html")
    public static String attachHtml(String html) {
        return html;
    }

    //Text attachments for Allure
    @Attachment(value = "Page screenshot", type = "image/png")
    public byte[] saveScreenshotPNG(WebDriver driver) {
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
    }

    @Override
    public void onStart(ITestContext iTestContext) {
        driver = BaseSetup.getDriver();
        Log.info("Start testing " + iTestContext.getName());
        iTestContext.setAttribute("WebDriver", driver);
        //Gọi hàm startRecord video trong CaptureHelpers class
        try {
            CaptureHelpers.startRecord(iTestContext.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFinish(ITestContext iTestContext) {
        Log.info("End testing " + iTestContext.getName());
        //Kết thúc và thực thi Extents Report
        getExtentReports().flush();
        //Gọi hàm stopRecord video trong CaptureHelpers class
        CaptureHelpers.stopRecord();
    }

    @Override
    public void onTestStart(ITestResult iTestResult) {
        Log.info(getTestName(iTestResult) + " test is starting...");
        ExtentTestManager.saveToReport(iTestResult.getName(), iTestResult.getTestName());
    }

    @Override
    public void onTestSuccess(ITestResult iTestResult) {
        Log.info(getTestName(iTestResult) + " test is passed.");
        //ExtentReports log operation for passed tests.
        ExtentTestManager.logMessage(Status.PASS, getTestDescription(iTestResult));
    }

    @Override
    public void onTestFailure(ITestResult iTestResult) {
        driver = BaseSetup.getDriver();

        Log.error(getTestName(iTestResult) + " test is failed.");

        ExtentTestManager.addScreenShot(Status.FAIL, getTestName(iTestResult));
        ExtentTestManager.logMessage(Status.FAIL, getTestDescription(iTestResult));

        //Allure Screenshot custom
        Log.error("Screenshot captured for test case: " + getTestName(iTestResult));
        saveScreenshotPNG(driver);
        //Save a log on Allure report.
        saveTextLog(getTestName(iTestResult) + " failed and screenshot taken!");
    }

    @Override
    public void onTestSkipped(ITestResult iTestResult) {
        Log.warn(getTestName(iTestResult) + " test is skipped.");
        ExtentTestManager.logMessage(Status.SKIP, getTestName(iTestResult) + " test is skipped.");
    }

    @Override
    public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) {
        Log.error("Test failed but it is in defined success ratio " + getTestName(iTestResult));
        ExtentTestManager.logMessage("Test failed but it is in defined success ratio " + getTestName(iTestResult));
    }
}


Bước 3: Thêm ghi chú của thư viện Allure vào test case class

package anhtester.com.utils.listeners;

import anhtester.com.browsers.BaseSetup;
import anhtester.com.utils.extentreports.ExtentTestManager;
import anhtester.com.utils.helpers.CaptureHelpers;
import anhtester.com.utils.logs.Log;
import com.aventstack.extentreports.Status;
import io.qameta.allure.Attachment;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

import static anhtester.com.utils.extentreports.ExtentManager.getExtentReports;

public class ReportListener implements ITestListener {

    WebDriver driver;

    public String getTestName(ITestResult result) {
        return result.getTestName() != null ? result.getTestName()
                : result.getMethod().getConstructorOrMethod().getName();
    }

    public String getTestDescription(ITestResult result) {
        return result.getMethod().getDescription() != null ? result.getMethod().getDescription() : getTestName(result);
    }

    //Text attachments for Allure
    @Attachment(value = "{0}", type = "text/plain")
    public static String saveTextLog(String message) {
        return message;
    }

    //HTML attachments for Allure
    @Attachment(value = "{0}", type = "text/html")
    public static String attachHtml(String html) {
        return html;
    }

    //Text attachments for Allure
    @Attachment(value = "Page screenshot", type = "image/png")
    public byte[] saveScreenshotPNG(WebDriver driver) {
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
    }

    @Override
    public void onStart(ITestContext iTestContext) {
        driver = BaseSetup.getDriver();
        Log.info("Start testing " + iTestContext.getName());
        iTestContext.setAttribute("WebDriver", driver);
        //Gọi hàm startRecord video trong CaptureHelpers class
        try {
            CaptureHelpers.startRecord(iTestContext.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFinish(ITestContext iTestContext) {
        Log.info("End testing " + iTestContext.getName());
        //Kết thúc và thực thi Extents Report
        getExtentReports().flush();
        //Gọi hàm stopRecord video trong CaptureHelpers class
        CaptureHelpers.stopRecord();
    }

    @Override
    public void onTestStart(ITestResult iTestResult) {
        Log.info(getTestName(iTestResult) + " test is starting...");
        ExtentTestManager.saveToReport(iTestResult.getName(), iTestResult.getTestName());
    }

    @Override
    public void onTestSuccess(ITestResult iTestResult) {
        Log.info(getTestName(iTestResult) + " test is passed.");
        //ExtentReports log operation for passed tests.
        ExtentTestManager.logMessage(Status.PASS, getTestDescription(iTestResult));
    }

    @Override
    public void onTestFailure(ITestResult iTestResult) {
        driver = BaseSetup.getDriver();

        Log.error(getTestName(iTestResult) + " test is failed.");

        ExtentTestManager.addScreenShot(Status.FAIL, getTestName(iTestResult));
        ExtentTestManager.logMessage(Status.FAIL, getTestDescription(iTestResult));

        //Allure Screenshot custom
        Log.error("Screenshot captured for test case: " + getTestName(iTestResult));
        saveScreenshotPNG(driver);
        //Save a log on Allure report.
        saveTextLog(getTestName(iTestResult) + " failed and screenshot taken!");
    }

    @Override
    public void onTestSkipped(ITestResult iTestResult) {
        Log.warn(getTestName(iTestResult) + " test is skipped.");
        ExtentTestManager.logMessage(Status.SKIP, getTestName(iTestResult) + " test is skipped.");
    }

    @Override
    public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) {
        Log.error("Test failed but it is in defined success ratio " + getTestName(iTestResult));
        ExtentTestManager.logMessage("Test failed but it is in defined success ratio " + getTestName(iTestResult));
    }
}


Các ghi chú trong Allure Report:

@Epic
@Features
@Stories/@Story
@Severity(SeverityLevel.BLOCKER)
@Description("In this cool test we will check cool thing")
@Step
@Attachment
@Link



Cái ghi chú quan trọng của mình là @Step. Nó đại diện cho từng @Test. Còn cái Ghi chú còn lại thì bổ trợ làm rõ ràng hơn cho Suite test case.

Các bạn nghiên cứu thêm tại đây: https://docs.qameta.io/allure-report/frameworks/java/testng#features

Mô tả chi tiết hơn tại đây: https://www.seleniumeasy.com/selenium-tutorials/allure-report-example-with-annotations


Demo: https://demo.qameta.io/allure/#behaviors

 

Bước 4: Mở Allure Reports

Sau khi chạy test case các bạn thấy là nó sẽ tự sinh ra cho mình folder "allure-results" nó chứa các file json. Đó cũng là data của report.

Từ giao diện IntelliJ sau khi các bạn chạy test case trên xong thì mở "Terminal" lên để chạy lệnh.

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester
Hoặc

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Hoặc  dùng phím tắt Alt + F12


Tiếp theo là chạy lệnh trong Terminal:  allure serve allure-results

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Sau khi chạy nó sẽ sinh ra cho mình folder tạm và host tạm để display Report.

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Đợi tầm 5s nó sinh ra cho mình 1 đường link tự động mở trên Browser luôn. Không thì các bạn click link trong vùng Terminal như hình trên cũng được.

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Giao diện từng Step

[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Khi không cần xem nữa thì tắt Terminal đi với phím tắt Ctrl +C sau đó chọn Y Enter


Đính kèm hình ảnh vào Allure Report khi Test case Fail


Các bạn chú ý: dùng bản TestNG 7.4.0 thì Allure report nó mới hiểu Attachment cái file hình vào khi test cases Fail

Thêm thư viện sau vào pom.xml: Allure Attachments, Aspectjweaver Project Lombok

Chổ này Allure Report các bạn cập nhật lên phiên bản mới nhất là 2.19.0  (cập nhật ngày 27/09/2022)

        <!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-testng -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <version>2.19.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-attachments -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-attachments</artifactId>
            <version>2.19.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.9.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>


Tiếp theo là tạo thẻ build trong maven của file pom.xml như mẫu:

Chú ý: đặt ngoài thẻ dependencies

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M7</version>
                    <configuration>
                        <suiteXmlFiles>
                            <!-- Call Suite name -->
                            <suiteXmlFile>suites/ParallelLoginTest.xml</suiteXmlFile>
                        </suiteXmlFiles>
                        <argLine>
                            -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.9.1/aspectjweaver-1.9.9.1.jar"
                        </argLine>
                        <testFailureIgnore>true</testFailureIgnore>
                        <systemPropertyVariables>
                            <allure.results.directory>target/allure-results</allure.results.directory>
                        </systemPropertyVariables>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>


File pom.xml full lúc này sẽ là:

<?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>anhtester.com</groupId>
    <artifactId>SeleniumMavenParallel42022</artifactId>
    <version>1.0.0</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.5.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.3.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.testng/testng -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.4.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.36</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.github.stephenc.monte/monte-screen-recorder -->
        <dependency>
            <groupId>com.github.stephenc.monte</groupId>
            <artifactId>monte-screen-recorder</artifactId>
            <version>0.7.7.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.19.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.aventstack/extentreports -->
        <dependency>
            <groupId>com.aventstack</groupId>
            <artifactId>extentreports</artifactId>
            <version>5.0.9</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-testng -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <version>2.19.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-attachments -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-attachments</artifactId>
            <version>2.19.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.9.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>
        
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M7</version>
                    <configuration>
                        <suiteXmlFiles>
                            <!-- Call Suite name -->
                            <suiteXmlFile>suites/ParallelLoginTest.xml</suiteXmlFile>
                        </suiteXmlFiles>
                        <argLine>
                            -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.9.1/aspectjweaver-1.9.9.1.jar"
                        </argLine>
                        <testFailureIgnore>true</testFailureIgnore>
                        <systemPropertyVariables>
                            <allure.results.directory>target/allure-results</allure.results.directory>
                        </systemPropertyVariables>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>


- Chổ <suiteXmlFile>suites/ParallelLoginTest.xml</suiteXmlFile>  chỉ đường dẫn đến file XML khi chạy trực tiếp từ pom.xml

- Chổ <allure.results.directory>target/allure-results</allure.results.directory>  đoạn này chỉ đường dẫn xuất report. Nằm trong folder target. Nếu muốn mang ra ngoài thì sửa lại là allure-results thôi là xong.

Để thực thi code trong pom.xml thì chúng ta mở Maven lên và dùng lệnh: mvn clean test

[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester
[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester


Chạy xong chúng ta gõ lệnh trong Terminal: allure serve target/allure-results


[Selenium Java] Bài 31: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

🔆 Add step detail vào từng bước của test cases thì các bạn cũng làm tương tự như Extent Report bên trên là gọi nó vào trong WebUI keyword

Ví dụ hàm openURL trong WebUI keyword

    @Step("Open URL: {0}")
    public static void openURL(String url) {
        DriverManager.getDriver().get(url);
        sleep(STEP_TIME);
        Log.info("Open: " + url);
        ExtentTestManager.logMessage(Status.PASS, "Open URL: " + url);

        waitForPageLoaded();
        if (PropertiesHelpers.getValue("screenshot_step").equals("yes")) {
            CaptureHelpers.takeScreenshot("openURL_" + Helpers.makeSlug(url));
        }
    }

Mình thêm cái @Step là để gắn step detail vào report

Hoặc các bạn có thể thêm description hơn bằng cách gọi hàm saveTextLog dưới chổ logMessage như của Extent Report

    @Step("Open URL: {0}")
    public static void openURL(String url) {
        DriverManager.getDriver().get(url);
        sleep(STEP_TIME);
        Log.info("Open: " + url);
        ExtentTestManager.logMessage(Status.PASS, "Open URL: " + url);
        AllureManager.saveTextLog("Open URL: " + url);
        waitForPageLoaded();
        if (PropertiesHelpers.getValue("screenshot_step").equals("yes")) {
            CaptureHelpers.takeScreenshot("openURL_" + Helpers.makeSlug(url));
        }
    }


Cái AllureManager là cái hàm ghi log và screenshot từ trong TestListener lấy ra class riêng để gọi lại dùng cho tiện ở nhiều nơi.

package anhtester.com.reports;

import anhtester.com.driver.DriverManager;
import io.qameta.allure.Attachment;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;

public class AllureManager {

    //Text attachments for Allure
    @Attachment(value = "{0}", type = "text/plain")
    public static String saveTextLog(String message) {
        return message;
    }

    //HTML attachments for Allure
    @Attachment(value = "{0}", type = "text/html")
    public static String attachHtml(String html) {
        return html;
    }

    //Text attachments for Allure
    @Attachment(value = "Page screenshot", type = "image/png")
    public static byte[] saveScreenshotPNG() {
        return ((TakesScreenshot) DriverManager.getDriver()).getScreenshotAs(OutputType.BYTES);
    }
    
}


Sau khi chạy thì nó sẽ như này

[Selenium Java] Bài 33: Cài đặt và sử dụng Extent Report Allure Report | Anh Tester

Chắc nhiều bạn cần mức độ như thế đúng không 😜

Source code tham khảo từ khoá học 04/2022: https://github.com/anhtester/SeleniumMaven42022Parallel

Teacher

Teacher

Anh Tester

Software Tester

Đường dẫu khó chân vẫn cần bước đi
Đời dẫu khổ tâm vẫn cần nghĩ thấu

Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

Chia sẻ khóa học lên trang

Bạn có thể đăng khóa học của chính bạn lên trang Anh Tester để kiếm tiền

Danh sách bài học