├── .gitignore
├── README.md
├── TestNG.xml
├── pom.xml
└── src
├── main
└── java
│ ├── page
│ ├── BasePage.java
│ ├── HomePage.java
│ ├── LoginPage.java
│ └── SearchResultPage.java
│ └── util
│ ├── AllureReportListener.java
│ ├── PropertyFileReader.java
│ └── driver
│ ├── DriverFactory.java
│ └── DriverHolder.java
└── test
├── java
└── test
│ ├── BaseTest.java
│ ├── LoginTest.java
│ └── SearchTest.java
└── resources
└── config.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /target
3 | /test-output
4 | /allure-results
5 | /selenium-testng-allure-report-demo.iml
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Selenium TestNG Project with Allure Reporting
2 |
3 | This is a demo project for Selenium Page Object Model with Allure reporting.
4 |
5 | ### Pre-requisites
6 | * Java
7 | * Maven
8 | * [Allure](https://docs.qameta.io/allure/#_installing_a_commandline)
9 | * IntelliJ IDEA
10 |
11 | ### Steps
12 | 1. Clone this project
13 | 2. Open the project in Intellij IDEA
14 | 3. Run TestNG.XML
15 | 4. Open the terminal in Intellij IDEA
16 | 5. Execute **`allure serve allure-results`**
17 |
--------------------------------------------------------------------------------
/TestNG.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.selenium.demo
8 | selenium-testng-allure-report-demo
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 1.8.13
13 | UTF-8
14 |
15 |
16 |
17 |
18 | org.seleniumhq.selenium
19 | selenium-java
20 | 3.141.59
21 |
22 |
23 | io.github.bonigarcia
24 | webdrivermanager
25 | 3.6.1
26 |
27 |
28 | org.testng
29 | testng
30 | 6.14.3
31 |
32 |
33 | io.qameta.allure
34 | allure-testng
35 | 2.12.0
36 |
37 |
38 |
39 |
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-compiler-plugin
44 |
45 | 1.8
46 | 1.8
47 |
48 |
49 |
50 | org.apache.maven.plugins
51 | maven-surefire-plugin
52 | 2.20
53 |
54 |
55 | TestNG.xml
56 |
57 |
58 | -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
59 |
60 |
61 |
62 |
63 | org.aspectj
64 | aspectjweaver
65 | ${aspectj.version}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/main/java/page/BasePage.java:
--------------------------------------------------------------------------------
1 | package page;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.WebDriver;
5 | import org.openqa.selenium.WebElement;
6 | import org.openqa.selenium.support.ui.ExpectedConditions;
7 | import org.openqa.selenium.support.ui.WebDriverWait;
8 |
9 | import java.util.List;
10 |
11 | public class BasePage {
12 |
13 | public static WebDriver driver;
14 |
15 | public BasePage(WebDriver driver) {
16 | BasePage.driver = driver;
17 | }
18 |
19 | public void waitUntilElementVisible(By by) {
20 | WebDriverWait wait = new WebDriverWait(driver, 60);
21 | wait.until(ExpectedConditions.visibilityOfElementLocated(by));
22 | }
23 |
24 | public void waitUntilElementClickable(By by) {
25 | WebDriverWait wait = new WebDriverWait(driver, 60);
26 | wait.until(ExpectedConditions.elementToBeClickable(by));
27 | }
28 |
29 | public void click(By by) {
30 | waitUntilElementClickable(by);
31 | driver.findElement(by).click();
32 | }
33 |
34 | public WebElement getElement(By by) {
35 | waitUntilElementVisible(by);
36 | return driver.findElement(by);
37 | }
38 |
39 | public List getElements(By by) {
40 | waitUntilElementVisible(by);
41 | return driver.findElements(by);
42 | }
43 |
44 | public void sendKeys(By by, String text) {
45 | waitUntilElementVisible(by);
46 | driver.findElement(by).sendKeys(text);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/page/HomePage.java:
--------------------------------------------------------------------------------
1 | package page;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.WebDriver;
5 |
6 | public class HomePage extends BasePage {
7 |
8 | private final By usernameLabel = By.xpath("//div[@class='header_user_info']//span");
9 | private final By searchTextBox = By.id("search_query_top");
10 | private final By searchButton = By.cssSelector("button[name='submit_search']");
11 |
12 | public HomePage(WebDriver driver) {
13 | super(driver);
14 | }
15 |
16 | public String getLoggedInUsername() {
17 | return getElement(usernameLabel).getText();
18 | }
19 |
20 | public void enterSearchItem(String itemName) {
21 | sendKeys(searchTextBox, itemName);
22 | }
23 |
24 | public void enterSearchButton() {
25 | click(searchButton);
26 | }
27 |
28 | public void searchItem(String itemName) {
29 | enterSearchItem(itemName);
30 | enterSearchButton();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/page/LoginPage.java:
--------------------------------------------------------------------------------
1 | package page;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.WebDriver;
5 |
6 | public class LoginPage extends BasePage {
7 |
8 | private final By emailTextBox = By.id("email");
9 | private final By passwordTextBox = By.id("passwd");
10 | private final By signInButton = By.id("SubmitLogin");
11 |
12 | public LoginPage(WebDriver driver) {
13 | super(driver);
14 | }
15 |
16 | public void setEmail(String email) {
17 | sendKeys(emailTextBox, email);
18 | }
19 |
20 | public void setPassword(String password) {
21 | sendKeys(passwordTextBox, password);
22 | }
23 |
24 | public void clickSignIn() {
25 | click(signInButton);
26 | }
27 |
28 | public void login(String email, String password) {
29 | setEmail(email);
30 | setPassword(password);
31 | clickSignIn();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/page/SearchResultPage.java:
--------------------------------------------------------------------------------
1 | package page;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.WebDriver;
5 |
6 | public class SearchResultPage extends BasePage{
7 |
8 | private final By searchResultsList = By.xpath("//div[@class='left-block']//div[@class='product-image-container']");
9 | private final By firstSearchResultName = By.xpath("//div[@class='right-block']//h5//a");
10 | private final By firstSearchResultPrice = By.xpath("//div[@class='right-block']//span[@itemprop='price']");
11 |
12 | public SearchResultPage(WebDriver driver) {
13 | super(driver);
14 | }
15 |
16 | public int getSearchResultCount() {
17 | return getElements(searchResultsList).size();
18 | }
19 |
20 | public String getFirstSearchResultName() {
21 | return getElement(firstSearchResultName).getText();
22 | }
23 |
24 | public String getFirstSearchResultPrice() {
25 | return getElement(firstSearchResultPrice).getText();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/util/AllureReportListener.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import io.qameta.allure.Attachment;
4 | import org.openqa.selenium.OutputType;
5 | import org.openqa.selenium.TakesScreenshot;
6 | import org.openqa.selenium.WebDriver;
7 | import org.testng.ITestContext;
8 | import org.testng.ITestListener;
9 | import org.testng.ITestResult;
10 |
11 | import static util.driver.DriverHolder.getDriver;
12 |
13 | public class AllureReportListener implements ITestListener {
14 |
15 | @Attachment(value = "Page screenshot", type = "image/png")
16 | public byte[] saveScreenshotPNG (WebDriver driver) {
17 | return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
18 | }
19 |
20 | @Override
21 | public void onStart(ITestContext iTestContext) {
22 | System.out.println("Starting Test Suite '" + iTestContext.getName() + "'.......");
23 | iTestContext.setAttribute("WebDriver", getDriver());
24 | }
25 |
26 | @Override
27 | public void onFinish(ITestContext iTestContext) {
28 | System.out.println("Finished Test Suite '" + iTestContext.getName() + "'");
29 | }
30 |
31 | @Override
32 | public void onTestStart(ITestResult iTestResult) {
33 | System.out.println("Starting Test Method '" + getTestMethodName(iTestResult) + "'");
34 | }
35 |
36 | @Override
37 | public void onTestSuccess(ITestResult iTestResult) {
38 | System.out.println("Test Method '" + getTestMethodName(iTestResult) + "' is Passed");
39 | }
40 |
41 | @Override
42 | public void onTestFailure(ITestResult iTestResult) {
43 | System.out.println("Test Method '" + getTestMethodName(iTestResult) + "' is Failed");
44 | if (getDriver() != null) {
45 | System.out.println("Screenshot has captured for the Test Method '" + getTestMethodName(iTestResult) + "'");
46 | saveScreenshotPNG(getDriver());
47 | }
48 | }
49 |
50 | @Override
51 | public void onTestSkipped(ITestResult iTestResult) {
52 | System.out.println("Test Method '" + getTestMethodName(iTestResult) + "' is Skipped");
53 | }
54 |
55 | @Override
56 | public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) {
57 | }
58 |
59 | private static String getTestMethodName(ITestResult iTestResult) {
60 | return iTestResult.getMethod().getConstructorOrMethod().getName();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/util/PropertyFileReader.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.util.Properties;
7 |
8 | public class PropertyFileReader {
9 |
10 | public static String getProperty(String propertyName) {
11 | String propertyValue = null;
12 |
13 | try (InputStream input = new FileInputStream("./src/test/resources/config.properties")) {
14 | Properties prop = new Properties();
15 | prop.load(input);
16 | propertyValue = prop.getProperty(propertyName);
17 | } catch (IOException ex) {
18 | ex.printStackTrace();
19 | }
20 | return propertyValue;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/util/driver/DriverFactory.java:
--------------------------------------------------------------------------------
1 | package util.driver;
2 |
3 | import io.github.bonigarcia.wdm.WebDriverManager;
4 | import org.openqa.selenium.WebDriver;
5 | import org.openqa.selenium.chrome.ChromeDriver;
6 | import org.openqa.selenium.chrome.ChromeOptions;
7 | import org.openqa.selenium.edge.EdgeDriver;
8 | import org.openqa.selenium.firefox.FirefoxBinary;
9 | import org.openqa.selenium.firefox.FirefoxDriver;
10 | import org.openqa.selenium.firefox.FirefoxOptions;
11 |
12 | public class DriverFactory {
13 |
14 | public static WebDriver getNewDriverInstance(String browserName) {
15 | switch (browserName.toLowerCase()) {
16 | case "chrome-headless":
17 | ChromeOptions chromeOptions = new ChromeOptions();
18 | chromeOptions.addArguments("--headless");
19 | chromeOptions.addArguments("start-maximized");
20 | WebDriverManager.chromedriver().setup();
21 | return new ChromeDriver(chromeOptions);
22 | case "firefox":
23 | WebDriverManager.firefoxdriver().setup();
24 | return new FirefoxDriver();
25 | case "firefox-headless":
26 | FirefoxBinary firefoxBinary = new FirefoxBinary();
27 | firefoxBinary.addCommandLineOptions("--headless");
28 | firefoxBinary.addCommandLineOptions("--window-size=1280x720");
29 | FirefoxOptions firefoxOptions = new FirefoxOptions();
30 | firefoxOptions.setBinary(firefoxBinary);
31 | WebDriverManager.firefoxdriver().setup();
32 | return new FirefoxDriver(firefoxOptions);
33 | case "edge":
34 | WebDriverManager.edgedriver().setup();
35 | return new EdgeDriver();
36 | default:
37 | WebDriverManager.chromedriver().setup();
38 | return new ChromeDriver();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/util/driver/DriverHolder.java:
--------------------------------------------------------------------------------
1 | package util.driver;
2 |
3 | import org.openqa.selenium.WebDriver;
4 |
5 | public class DriverHolder {
6 |
7 | private static final ThreadLocal driver = new ThreadLocal<>();
8 |
9 | public static WebDriver getDriver() {
10 | return driver.get();
11 | }
12 |
13 | public static void setDriver(WebDriver driver) {
14 | DriverHolder.driver.set(driver);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/test/BaseTest.java:
--------------------------------------------------------------------------------
1 | package test;
2 |
3 | import org.testng.annotations.AfterMethod;
4 | import org.testng.annotations.BeforeMethod;
5 | import util.driver.DriverFactory;
6 |
7 | import static util.PropertyFileReader.getProperty;
8 | import static util.driver.DriverHolder.getDriver;
9 | import static util.driver.DriverHolder.setDriver;
10 |
11 | public class BaseTest {
12 |
13 | @BeforeMethod
14 | public void before() {
15 | setDriver(DriverFactory.getNewDriverInstance(getProperty("browser")));
16 | getDriver().manage().window().maximize();
17 | getDriver().get(getProperty("application_url"));
18 | }
19 |
20 | @AfterMethod
21 | public void after() {
22 | if (getDriver() != null) {
23 | getDriver().quit();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/test/LoginTest.java:
--------------------------------------------------------------------------------
1 | package test;
2 |
3 | import io.qameta.allure.*;
4 | import org.testng.annotations.BeforeMethod;
5 | import org.testng.annotations.Test;
6 | import page.HomePage;
7 | import page.LoginPage;
8 |
9 | import static io.qameta.allure.SeverityLevel.BLOCKER;
10 | import static io.qameta.allure.SeverityLevel.CRITICAL;
11 | import static org.testng.Assert.assertEquals;
12 | import static util.driver.DriverHolder.getDriver;
13 |
14 | @Epic("User Management")
15 | @Feature("Login")
16 | public class LoginTest extends BaseTest {
17 |
18 | private LoginPage loginPage;
19 |
20 | @BeforeMethod
21 | public void loginBeforeMethod() {
22 | loginPage = new LoginPage(getDriver());
23 | }
24 |
25 | @Test(description = "Verify that a valid user can login to the application")
26 | @Severity(BLOCKER)
27 | @Description("Verify that a valid user can login to the application")
28 | @Story("As a user I should be able to login to the application")
29 | public void testValidLogin() {
30 | loginPage.login("osanda@mailinator.com","1qaz2wsx@");
31 | assertEquals(new HomePage(getDriver()).getLoggedInUsername(), "Osanda Nimalarathna");
32 | }
33 |
34 | @Test(description = "Verify that an invalid user cannot login to the application")
35 | @Severity(CRITICAL)
36 | @Description("Verify that an invalid user cannot login to the application")
37 | @Story("As a user I should be able to login to the application")
38 | public void testInvalidLogin() {
39 | loginPage.login("osanda@mailinator.com","abc12");
40 | assertEquals(getDriver().getTitle(), "Login - My Store");
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/test/SearchTest.java:
--------------------------------------------------------------------------------
1 | package test;
2 |
3 | import io.qameta.allure.*;
4 | import org.testng.annotations.BeforeMethod;
5 | import org.testng.annotations.Test;
6 | import page.HomePage;
7 | import page.LoginPage;
8 | import page.SearchResultPage;
9 |
10 | import static io.qameta.allure.SeverityLevel.CRITICAL;
11 | import static org.testng.Assert.assertEquals;
12 | import static org.testng.Assert.assertTrue;
13 | import static util.driver.DriverHolder.getDriver;
14 |
15 | @Epic("Order Placing")
16 | @Feature("Search")
17 | public class SearchTest extends BaseTest {
18 |
19 | private SearchResultPage searchResultPage;
20 |
21 | @BeforeMethod
22 | public void searchBeforeMethod() {
23 | new LoginPage(getDriver()).login("osanda@mailinator.com","1qaz2wsx@");
24 | searchResultPage = new SearchResultPage(getDriver());
25 | new HomePage(getDriver()).searchItem("T-shirt");
26 | }
27 |
28 | @Test(description = "Verify that the search results are not empty for the keyword 'T-shirt'")
29 | @Severity(CRITICAL)
30 | @Description("Verify that the search results are not empty for the keyword 'T-shirt'")
31 | @Story("As a user I should be able to search items")
32 | public void testSearchResultCount() {
33 | int actualSearchResultCount = searchResultPage.getSearchResultCount();
34 | assertTrue(actualSearchResultCount > 0);
35 | assertEquals(actualSearchResultCount,1);
36 | }
37 |
38 | @Test(description = "Verify the search result name and price for the keyword 'T-shirt'")
39 | @Severity(CRITICAL)
40 | @Description("Verify the search result name and price for the keyword 'T-shirt'")
41 | @Story("As a user I should be able to search items")
42 | public void testSearchResult() {
43 | assertTrue(searchResultPage.getFirstSearchResultName().contains("Faded Short Sleeve T-shirts"));
44 | assertEquals(searchResultPage.getFirstSearchResultPrice(), "$16.51");
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/resources/config.properties:
--------------------------------------------------------------------------------
1 | # Test Configs
2 | application_url=http://automationpractice.com/index.php?controller=authentication&back=my-account
3 | browser=Chrome
--------------------------------------------------------------------------------