├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── test
├── java
├── pages
│ ├── BasePage.java
│ ├── HomePage.java
│ ├── LoginPage.java
│ └── PageGenerator.java
├── tests
│ ├── BaseTest.java
│ ├── CopyOfLoginTest.java
│ └── LoginTest.java
└── utils
│ ├── ChromeOps.java
│ └── LogUtil.java
└── resources
└── junit-platform.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | # Intellij
26 | .idea/
27 | *.iml
28 |
29 | # Maven output
30 | target/
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 SW Test Academy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # junit5-parallel-testing
2 | Junit 5 parallel test execution
3 | Here is the detailed article link for JUnit 5 Parallel Test Execution:
4 |
5 | https://www.swtestacademy.com/junit5-parallel-test-execution/
6 |
7 | To run the tests with maven please use this command: mvn clean -Dtest=tests.** test
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | junit5-parallel
8 | junit5-parallel
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | org.seleniumhq.selenium
14 | selenium-java
15 | 4.0.0-beta-3
16 |
17 |
18 |
19 | org.junit.jupiter
20 | junit-jupiter-api
21 | 5.8.0-M1
22 | test
23 |
24 |
25 |
26 | org.junit.jupiter
27 | junit-jupiter-engine
28 | 5.8.0-M1
29 |
30 |
31 |
32 | org.junit.platform
33 | junit-platform-launcher
34 | 1.8.0-M1
35 | test
36 |
37 |
38 |
39 |
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-surefire-plugin
44 | 2.22.2
45 |
46 | plain
47 |
48 |
49 |
50 | org.apache.maven.plugins
51 | maven-compiler-plugin
52 |
53 | 11
54 | 11
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/test/java/pages/BasePage.java:
--------------------------------------------------------------------------------
1 | package pages;
2 |
3 | import java.time.Duration;
4 | import java.util.List;
5 | import org.openqa.selenium.By;
6 | import org.openqa.selenium.JavascriptExecutor;
7 | import org.openqa.selenium.WebDriver;
8 | import org.openqa.selenium.WebElement;
9 | import org.openqa.selenium.support.ui.ExpectedConditions;
10 | import org.openqa.selenium.support.ui.WebDriverWait;
11 |
12 | public class BasePage extends PageGenerator {
13 | WebDriverWait wait;
14 | JavascriptExecutor js;
15 |
16 | public BasePage(WebDriver driver) {
17 | super(driver);
18 | wait = new WebDriverWait(driver, Duration.ofSeconds(10));
19 | js = (JavascriptExecutor) driver;
20 | }
21 |
22 | //Click Method by using JAVA Generics (You can use both By or Webelement)
23 | public void click(T elementAttr) {
24 | if (elementAttr.getClass().getName().contains("By")) {
25 | driver.findElement((By) elementAttr).click();
26 | } else {
27 | ((WebElement) elementAttr).click();
28 | }
29 | }
30 |
31 | public void jsClick(By by) {
32 | js.executeScript("arguments[0].click();", wait.until(ExpectedConditions.visibilityOfElementLocated(by)));
33 | }
34 |
35 | //Write Text by using JAVA Generics (You can use both By or Webelement)
36 | public void writeText(T elementAttr, String text) {
37 | if (elementAttr.getClass().getName().contains("By")) {
38 | driver.findElement((By) elementAttr).sendKeys(text);
39 | } else {
40 | ((WebElement) elementAttr).sendKeys(text);
41 | }
42 | }
43 |
44 | //Read Text by using JAVA Generics (You can use both By or Webelement)
45 | public String readText(T elementAttr) {
46 | if (elementAttr.getClass().getName().contains("By")) {
47 | return driver.findElement((By) elementAttr).getText();
48 | } else {
49 | return ((WebElement) elementAttr).getText();
50 | }
51 | }
52 |
53 | //Close popup if exists
54 | public void handlePopup(By by) throws InterruptedException {
55 | List popup = driver.findElements(by);
56 | if (!popup.isEmpty()) {
57 | popup.get(0).click();
58 | Thread.sleep(200);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/test/java/pages/HomePage.java:
--------------------------------------------------------------------------------
1 | package pages;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.WebElement;
5 | import org.openqa.selenium.support.FindBy;
6 | import org.openqa.selenium.support.How;
7 | import org.openqa.selenium.support.PageFactory;
8 |
9 | public class HomePage extends BasePage {
10 |
11 | //*********Constructor*********
12 | public HomePage(WebDriver driver) {
13 | super(driver);
14 | }
15 |
16 | //*********Page Variables*********
17 | String baseURL = "http://www.n11.com/";
18 |
19 | //*********Web Elements By Using Page Factory*********
20 | @FindBy(how = How.CLASS_NAME, using = "btnSignIn")
21 | public WebElement signInButton;
22 |
23 | //*********Page Methods*********
24 | //Go to Homepage
25 | public HomePage givenIAmAtHomePage() {
26 | driver.get(baseURL);
27 | return this;
28 | }
29 |
30 | //Go to LoginPage
31 | public LoginPage whenIGoToLoginPage() {
32 | click(signInButton);
33 | return new PageFactory().initElements(driver, LoginPage.class);
34 | }
35 | }
--------------------------------------------------------------------------------
/src/test/java/pages/LoginPage.java:
--------------------------------------------------------------------------------
1 | package pages;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 | import static org.junit.jupiter.api.Assertions.assertTrue;
5 |
6 | import org.openqa.selenium.By;
7 | import org.openqa.selenium.WebDriver;
8 | import org.openqa.selenium.WebElement;
9 | import org.openqa.selenium.support.FindBy;
10 | import org.openqa.selenium.support.How;
11 | import utils.LogUtil;
12 |
13 | public class LoginPage extends BasePage {
14 |
15 | //*********Constructor*********
16 | public LoginPage(WebDriver driver) {
17 | super(driver);
18 | }
19 |
20 | //*********Web Elements by using Page Factory*********
21 | @FindBy(how = How.ID, using = "email")
22 | public WebElement userName;
23 |
24 | @FindBy(how = How.ID, using = "password")
25 | public WebElement password;
26 |
27 | By loginButton = By.id("loginButton");
28 | By errorMessageUsernameBy = By.xpath("//*[@id=\"loginForm\"]/div[1]/div/div");
29 | By errorMessagePasswordBy = By.xpath("//*[@id=\"loginForm\"]/div[2]/div/div");
30 |
31 | //*********Page Methods*********
32 | public LoginPage andILoginToN11(String userName, String password) {
33 | writeText(this.userName, userName);
34 | writeText(this.password, password);
35 | jsClick(loginButton);
36 | return this;
37 | }
38 |
39 | public LoginPage thenIVerifyLoginUserNameErrorMessage(String expectedText) {
40 | assertEquals(expectedText, readText(errorMessageUsernameBy));
41 | return this;
42 | }
43 |
44 | public LoginPage thenIVerifyPasswordErrorMessage(String expectedText) {
45 | assertEquals(expectedText, readText(errorMessagePasswordBy));
46 | return this;
47 | }
48 |
49 | public LoginPage thenIVerifyLogEntryFailMessage() {
50 | assertTrue(LogUtil.isLoginErrorLog(driver));
51 | return this;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/java/pages/PageGenerator.java:
--------------------------------------------------------------------------------
1 | package pages;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.support.PageFactory;
5 |
6 | public class PageGenerator {
7 | public WebDriver driver;
8 |
9 | public PageGenerator(WebDriver driver) {
10 | this.driver = driver;
11 | }
12 |
13 | //JAVA Generics to Create and return a New Page
14 | public TPage getPage(Class pageClass) {
15 | //Initialize the Page with its elements and return it.
16 | return PageFactory.initElements(driver, pageClass);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/tests/BaseTest.java:
--------------------------------------------------------------------------------
1 | package tests;
2 |
3 | import java.time.Duration;
4 | import org.junit.jupiter.api.AfterEach;
5 | import org.junit.jupiter.api.BeforeEach;
6 | import org.openqa.selenium.WebDriver;
7 | import org.openqa.selenium.chrome.ChromeDriver;
8 | import org.openqa.selenium.support.ui.WebDriverWait;
9 | import pages.PageGenerator;
10 |
11 | public class BaseTest {
12 | public WebDriver driver;
13 | public WebDriverWait wait;
14 | public PageGenerator page;
15 |
16 | @BeforeEach
17 | public void classLevelSetup() {
18 | driver = new ChromeDriver();
19 | wait = new WebDriverWait(driver, Duration.ofSeconds(10));
20 | page = new PageGenerator(driver);
21 | }
22 |
23 | @AfterEach
24 | public void teardown() {
25 | driver.quit();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/tests/CopyOfLoginTest.java:
--------------------------------------------------------------------------------
1 | package tests;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.junit.jupiter.api.parallel.Execution;
5 | import org.junit.jupiter.api.parallel.ExecutionMode;
6 | import pages.HomePage;
7 |
8 | @Execution(ExecutionMode.CONCURRENT)
9 | public class CopyOfLoginTest extends BaseTest {
10 | @Test
11 | public void invalidLoginTest_InvalidUserNameInvalidPassword2() {
12 | page.getPage(HomePage.class)
13 | .givenIAmAtHomePage()
14 | .whenIGoToLoginPage()
15 | .andILoginToN11("onur@swtestacademy.com", "11223344")
16 | .thenIVerifyLogEntryFailMessage();
17 | }
18 |
19 | @Test
20 | public void invalidLoginTest_EmptyUserEmptyPassword2() {
21 | page.getPage(HomePage.class)
22 | .givenIAmAtHomePage()
23 | .whenIGoToLoginPage()
24 | .andILoginToN11("", "")
25 | .thenIVerifyLoginUserNameErrorMessage("Lütfen e-posta adresinizi girin.")
26 | .thenIVerifyPasswordErrorMessage("Bu alanın doldurulması zorunludur.");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/tests/LoginTest.java:
--------------------------------------------------------------------------------
1 | package tests;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.junit.jupiter.api.parallel.Execution;
5 | import org.junit.jupiter.api.parallel.ExecutionMode;
6 | import pages.HomePage;
7 |
8 | @Execution(ExecutionMode.CONCURRENT)
9 | public class LoginTest extends BaseTest {
10 | @Test
11 | public void invalidLoginTest_InvalidUserNameInvalidPassword() {
12 | page.getPage(HomePage.class)
13 | .givenIAmAtHomePage()
14 | .whenIGoToLoginPage()
15 | .andILoginToN11("onur@swtestacademy.com", "11223344")
16 | .thenIVerifyLogEntryFailMessage();
17 | }
18 |
19 | @Test
20 | public void invalidLoginTest_EmptyUserEmptyPassword() {
21 | page.getPage(HomePage.class)
22 | .givenIAmAtHomePage()
23 | .whenIGoToLoginPage()
24 | .andILoginToN11("", "")
25 | .thenIVerifyLoginUserNameErrorMessage("Lütfen e-posta adresinizi girin.")
26 | .thenIVerifyPasswordErrorMessage("Bu alanın doldurulması zorunludur.");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/utils/ChromeOps.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import java.util.logging.Level;
4 | import org.openqa.selenium.chrome.ChromeOptions;
5 | import org.openqa.selenium.logging.LogType;
6 | import org.openqa.selenium.logging.LoggingPreferences;
7 | import org.openqa.selenium.remote.CapabilityType;
8 | import org.openqa.selenium.remote.DesiredCapabilities;
9 |
10 | public class ChromeOps {
11 | public static ChromeOptions getChromeOptions() {
12 | DesiredCapabilities caps = new DesiredCapabilities();
13 | LoggingPreferences logPrefs = new LoggingPreferences();
14 | logPrefs.enable(LogType.BROWSER, Level.ALL);
15 | caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
16 | ChromeOptions options = new ChromeOptions();
17 | return options.merge(caps);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/utils/LogUtil.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.logging.LogEntries;
5 | import org.openqa.selenium.logging.LogType;
6 |
7 | public class LogUtil {
8 | public static LogEntries getLogs(WebDriver driver) {
9 | return driver.manage().logs().get(LogType.BROWSER);
10 | }
11 |
12 | public static Boolean isLoginErrorLog(WebDriver driver) {
13 | LogEntries logEntries = driver.manage().logs().get(LogType.BROWSER);
14 | return logEntries.getAll().stream()
15 | .anyMatch(logEntry -> logEntry.getMessage().contains("An invalid email address was specified"));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/resources/junit-platform.properties:
--------------------------------------------------------------------------------
1 | junit.jupiter.execution.parallel.enabled=true
2 | junit.jupiter.execution.parallel.config.strategy=dynamic
--------------------------------------------------------------------------------