This repository is a Selenium WebDriver automation project using Java and Maven. It is structured as a starter framework for browser automation practice and Selenium Java portfolio development.
The current project includes:
- Java 21 Maven configuration
- Selenium WebDriver dependency
- WebDriverManager dependency
- JUnit 5 dependency
- Logback dependency
- A starter Java setup class for WebDriver-related imports
- A README foundation for Selenium automation documentation
The repository currently appears to be a starter scaffold. At the time this README was updated, the indexed project files did not contain completed JUnit @Test test classes. This README therefore documents:
- What currently exists in the repository.
- How the current code works.
- Recommended Selenium Java tests to add next.
- Full Selenium Java tutorial, examples, tips, methodologies, and framework guidance.
Repository:
Selenium-Test-Automation-w-Java
- Project Summary
- Languages Used
- Tools and Frameworks
- Project File Links
- File Structure
- Current Project Inventory
- Detailed Test Inventory
- How the Current Code Works
- Selenium Java Methodologies Used
- Recommended Test Suite to Add
- Code Examples
- Tutorial and Setup Guide
- Selenium Java Automation Tips
- Recommended Framework Improvements
- Author
| Language / Format | Purpose |
|---|---|
| Java | Main automation programming language |
| XML | Maven pom.xml project configuration |
| Markdown | Project documentation |
| Tool / Framework | Purpose |
|---|---|
| Java 21 | Main language/runtime for the automation project |
| Selenium WebDriver | Browser automation library |
| Maven | Build tool and dependency manager |
| JUnit 5 | Test runner and assertion framework |
| WebDriverManager | Automatic browser driver management |
| ChromeDriver | Browser driver for Chrome automation |
| Logback | Logging support |
| GitHub Codespaces | Cloud development environment option |
| File / Folder | Description |
|---|---|
| ReadMe.md | Main GitHub README documentation |
| pom.xml | Maven build file with Java, Selenium, WebDriverManager, JUnit, and Logback dependencies |
| src/main/java/setup/Main.java | Starter Java setup class with Selenium and ChromeDriver imports |
Selenium-Test-Automation-w-Java/
|
|-- pom.xml
|-- ReadMe.md
`-- src/
`-- main/
`-- java/
`-- setup/
`-- Main.java
Recommended future structure:
Selenium-Test-Automation-w-Java/
|
|-- pom.xml
|-- ReadMe.md
|
|-- src/
| |-- main/
| | `-- java/
| | |-- base/
| | | `-- BasePage.java
| | |-- pages/
| | | |-- HomePage.java
| | | |-- LoginPage.java
| | | |-- ProductPage.java
| | | |-- CartPage.java
| | | `-- CheckoutPage.java
| | `-- setup/
| | `-- Main.java
| |
| `-- test/
| `-- java/
| |-- base/
| | `-- BaseTest.java
| |-- tests/
| | |-- HomePageTest.java
| | |-- LoginTest.java
| | |-- ProductSearchTest.java
| | |-- CartTest.java
| | `-- CheckoutTest.java
| `-- utilities/
| |-- ConfigReader.java
| `-- ScreenshotUtil.java
|
`-- src/test/resources/
|-- config.properties
`-- testdata/
`-- users.properties
The project uses Maven through pom.xml.
Important configured dependencies include:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>Current file:
packagesetup;
importorg.openqa.selenium.WebDriver;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.chrome.ChromeOptions;
importstaticio.github.bonigarcia.wdm.WebDriverManager.chromedriver;
publicclassMain {
static {
}
publicstaticvoidmain(String[] args) {
}
}The repository has the core dependencies and imports needed to begin Selenium WebDriver automation, but the current Main.java class does not yet initialize a browser or run browser actions.
The next recommended step is to add JUnit test classes under:
src/test/java/tests/
At the time this README was updated, no completed JUnit @Test classes were found in the indexed repository code.
Current test inventory:
| Test Area | Current Status | Notes |
|---|---|---|
| Browser launch test | Not yet implemented | Selenium imports exist in Main.java |
| Homepage title test | Not yet implemented | Recommended first smoke test |
| Element interaction test | Not yet implemented | Recommended after browser setup |
| Login test | Not yet implemented | Recommended Page Object Model example |
| Search test | Not yet implemented | Recommended product/search workflow |
| Cart test | Not yet implemented | Recommended e-commerce workflow |
| Checkout test | Not yet implemented | Recommended end-to-end workflow |
| Screenshot-on-failure | Not yet implemented | Recommended framework utility |
The sections below provide detailed recommended tests that can be added to turn the scaffold into a complete Selenium Java automation portfolio.
The pom.xml file defines the Maven project identity:
<groupId>org.linkedin.learning</groupId>
<artifactId>selenium4</artifactId>
<version>1.0-SNAPSHOT</version>It also sets Java compilation to Java 21:
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>Selenium WebDriver is included through:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>RELEASE</version>
</dependency>This dependency gives the project access to:
WebDriverChromeDriverByWebElementWebDriverWaitExpectedConditionsActions- browser window controls
- element interactions
WebDriverManager is included through:
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>RELEASE</version>
</dependency>This avoids manually downloading and configuring ChromeDriver.
Example usage:
chromedriver().setup();
WebDriverdriver = newChromeDriver();JUnit 5 dependencies are included for writing test methods with annotations such as:
@Test@BeforeEach@AfterEach@DisplayNameLogback is included for logging automation events, debug information, and execution flow.
The current project is a starter framework, but it is aligned with the following Selenium Java methodologies.
Maven keeps Selenium, JUnit, WebDriverManager, and logging dependencies centralized in pom.xml.
WebDriverManager reduces local setup issues by automatically managing browser driver binaries.
JUnit provides a standard Java test structure using setup, test, and teardown annotations.
Recommended for future expansion. Page classes should store selectors and page actions, while test classes should focus on test intent.
Explicit waits should be used instead of fixed sleeps.
Preferred:
WebDriverWaitwait = newWebDriverWait(driver, Duration.ofSeconds(10));
WebElementelement = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username")));Avoid:
Thread.sleep(5000);Each test should be able to run alone without depending on another test.
Each test should verify the expected result using JUnit assertions.
Example:
assertEquals("Expected Title", driver.getTitle());
assertTrue(driver.findElement(By.id("success-message")).isDisplayed());Below is a detailed list of recommended tests to add to this project.
Recommended file:src/test/java/tests/HomePageTest.java
Purpose: Confirms that Chrome launches successfully and loads the target application.
@Test@DisplayName("Home page title should be displayed")
voidhomePageTitleShouldBeDisplayed() {
driver.get("https://practicesoftwaretesting.com/");
StringactualTitle = driver.getTitle();
assertTrue(actualTitle.contains("Practice Software Testing"));
}How it works:
- Opens the browser.
- Navigates to the application URL.
- Reads the page title.
- Verifies that the title contains the expected application name.
Methodologies demonstrated: Smoke testing, browser startup validation, title assertion.
Recommended file:src/test/java/tests/HomePageTest.java
Purpose: Confirms unauthenticated users can see the sign-in link.
@Test@DisplayName("Sign in link should be visible on home page")
voidsignInLinkShouldBeVisible() {
driver.get("https://practicesoftwaretesting.com/");
WebElementsignInLink = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("[data-test='nav-sign-in']"))
);
assertEquals("Sign in", signInLink.getText());
}How it works:
- Opens the homepage.
- Waits for the sign-in link.
- Checks the displayed text.
Methodologies demonstrated: Explicit waits, CSS selector usage, guest-state UI validation.
Recommended file:src/test/java/tests/ProductSearchTest.java
Purpose: Validates product search behavior.
@Test@DisplayName("User can search for Thor Hammer")
voiduserCanSearchForThorHammer() {
driver.get("https://practicesoftwaretesting.com/");
WebElementsearchBox = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("[data-test='search-query']"))
);
searchBox.sendKeys("Thor Hammer");
driver.findElement(By.cssSelector("[data-test='search-submit']")).click();
WebElementproductImage = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("img[alt='Thor Hammer']"))
);
assertTrue(productImage.isDisplayed());
}How it works:
- Opens the homepage.
- Enters a product name into the search field.
- Clicks search.
- Waits for the product image to appear.
- Verifies the result is displayed.
Methodologies demonstrated: Input automation, button click automation, search workflow validation, explicit waits.
Recommended file:src/test/java/tests/LoginTest.java
Purpose: Validates a successful login flow.
@Test@DisplayName("Customer can log in with valid credentials")
voidcustomerCanLoginWithValidCredentials() {
driver.get("https://practicesoftwaretesting.com/auth/login");
driver.findElement(By.cssSelector("[data-test='email']")).sendKeys(System.getenv("CUSTOMER_EMAIL"));
driver.findElement(By.cssSelector("[data-test='password']")).sendKeys(System.getenv("CUSTOMER_PASSWORD"));
driver.findElement(By.cssSelector("[data-test='login-submit']")).click();
WebElementnavMenu = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("[data-test='nav-menu']"))
);
assertTrue(navMenu.getText().contains("Jane Doe"));
}How it works:
- Opens the login page.
- Enters credentials from environment variables.
- Submits the login form.
- Waits for the authenticated navigation menu.
- Verifies the expected customer name appears.
Methodologies demonstrated: Secure credential handling, login automation, post-login assertion, explicit wait strategy.
Recommended file:src/test/java/tests/LoginTest.java
Purpose: Validates negative login behavior.
@Test@DisplayName("Invalid login should display an error")
voidinvalidLoginShouldDisplayError() {
driver.get("https://practicesoftwaretesting.com/auth/login");
driver.findElement(By.cssSelector("[data-test='email']")).sendKeys("invalid@example.com");
driver.findElement(By.cssSelector("[data-test='password']")).sendKeys("wrong-password");
driver.findElement(By.cssSelector("[data-test='login-submit']")).click();
WebElementerrorMessage = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".alert-danger"))
);
assertTrue(errorMessage.isDisplayed());
}How it works:
- Opens login page.
- Enters invalid credentials.
- Clicks login.
- Waits for an error message.
- Confirms the error message appears.
Methodologies demonstrated: Negative testing, validation-message testing, error handling coverage.
Recommended file:src/test/java/tests/CartTest.java
Purpose: Validates that a product can be added to the cart.
@Test@DisplayName("User can add product to cart")
voiduserCanAddProductToCart() {
driver.get("https://practicesoftwaretesting.com/");
WebElementproduct = wait.until(
ExpectedConditions.elementToBeClickable(By.linkText("Claw Hammer with Shock Reduction Grip"))
);
product.click();
WebElementaddToCartButton = wait.until(
ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='add-to-cart']"))
);
addToCartButton.click();
WebElementcartQuantity = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("[data-test='cart-quantity']"))
);
assertEquals("1", cartQuantity.getText());
}How it works:
- Opens the homepage.
- Clicks a product.
- Clicks add to cart.
- Waits for the cart quantity indicator.
- Verifies the cart quantity is
1.
Methodologies demonstrated: Product selection, cart validation, click automation, state assertion.
Recommended file:src/test/java/tests/CheckoutTest.java
Purpose: Confirms the finish button remains disabled before payment details are selected.
@Test@DisplayName("Checkout finish button should be disabled before payment method is selected")
voidfinishButtonShouldBeDisabledBeforePaymentMethod() {
driver.get("https://practicesoftwaretesting.com/");
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Claw Hammer with Shock Reduction Grip"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='add-to-cart']"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='nav-cart']"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='proceed-1']"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='proceed-2']"))).click();
driver.findElement(By.cssSelector("[data-test='address']")).sendKeys("123 Testing Way");
driver.findElement(By.cssSelector("[data-test='city']")).sendKeys("Sacramento");
driver.findElement(By.cssSelector("[data-test='state']")).sendKeys("California");
driver.findElement(By.cssSelector("[data-test='country']")).sendKeys("USA");
driver.findElement(By.cssSelector("[data-test='postcode']")).sendKeys("98765");
driver.findElement(By.cssSelector("[data-test='proceed-3']")).click();
WebElementfinishButton = wait.until(
ExpectedConditions.presenceOfElementLocated(By.cssSelector("[data-test='finish']"))
);
assertFalse(finishButton.isEnabled());
}How it works:
- Adds a product to the cart.
- Moves through checkout steps.
- Enters address information.
- Proceeds to payment.
- Confirms the finish button is disabled before payment method selection.
Methodologies demonstrated: End-to-end workflow validation, checkout form automation, disabled-state assertion.
Recommended file:src/test/java/tests/CheckoutTest.java
Purpose: Validates a full checkout path using a payment method and installment selection.
@Test@DisplayName("Customer can complete checkout with Buy Now Pay Later")
voidcustomerCanCompleteCheckoutWithBuyNowPayLater() {
driver.get("https://practicesoftwaretesting.com/");
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Claw Hammer with Shock Reduction Grip"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='add-to-cart']"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='nav-cart']"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='proceed-1']"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("[data-test='proceed-2']"))).click();
driver.findElement(By.cssSelector("[data-test='address']")).sendKeys("123 Testing Way");
driver.findElement(By.cssSelector("[data-test='city']")).sendKeys("Sacramento");
driver.findElement(By.cssSelector("[data-test='state']")).sendKeys("California");
driver.findElement(By.cssSelector("[data-test='country']")).sendKeys("USA");
driver.findElement(By.cssSelector("[data-test='postcode']")).sendKeys("98765");
driver.findElement(By.cssSelector("[data-test='proceed-3']")).click();
SelectpaymentMethod = newSelect(driver.findElement(By.cssSelector("[data-test='payment-method']")));
paymentMethod.selectByVisibleText("Buy Now Pay Later");
Selectinstallments = newSelect(driver.findElement(By.cssSelector("[data-test='monthly_installments']")));
installments.selectByVisibleText("6 Monthly Installments");
driver.findElement(By.cssSelector("[data-test='finish']")).click();
WebElementsuccessMessage = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".help-block"))
);
assertEquals("Payment was successful", successMessage.getText());
}How it works:
- Selects a product.
- Adds it to the cart.
- Opens the cart.
- Completes address details.
- Selects a payment method.
- Selects installment terms.
- Submits checkout.
- Verifies payment success.
Methodologies demonstrated: Full business workflow automation, dropdown handling, success-message validation, e-commerce checkout testing.
Recommended file:
src/test/java/base/BaseTest.java
packagebase;
importio.github.bonigarcia.wdm.WebDriverManager;
importorg.junit.jupiter.api.AfterEach;
importorg.junit.jupiter.api.BeforeEach;
importorg.openqa.selenium.WebDriver;
importorg.openqa.selenium.chrome.ChromeDriver;
importorg.openqa.selenium.chrome.ChromeOptions;
importorg.openqa.selenium.support.ui.WebDriverWait;
importjava.time.Duration;
publicclassBaseTest {
protectedWebDriverdriver;
protectedWebDriverWaitwait;
@BeforeEachvoidsetUp() {
WebDriverManager.chromedriver().setup();
ChromeOptionsoptions = newChromeOptions();
options.addArguments("--start-maximized");
options.addArguments("--disable-notifications");
driver = newChromeDriver(options);
wait = newWebDriverWait(driver, Duration.ofSeconds(10));
}
@AfterEachvoidtearDown() {
if (driver != null) {
driver.quit();
}
}
}Recommended file:
src/main/java/pages/LoginPage.java
packagepages;
importorg.openqa.selenium.By;
importorg.openqa.selenium.WebDriver;
importorg.openqa.selenium.WebElement;
importorg.openqa.selenium.support.ui.ExpectedConditions;
importorg.openqa.selenium.support.ui.WebDriverWait;
publicclassLoginPage {
privatefinalWebDriverdriver;
privatefinalWebDriverWaitwait;
privatefinalByemailInput = By.cssSelector("[data-test='email']");
privatefinalBypasswordInput = By.cssSelector("[data-test='password']");
privatefinalByloginButton = By.cssSelector("[data-test='login-submit']");
privatefinalBynavMenu = By.cssSelector("[data-test='nav-menu']");
publicLoginPage(WebDriverdriver, WebDriverWaitwait) {
this.driver = driver;
this.wait = wait;
}
publicvoidopen() {
driver.get("https://practicesoftwaretesting.com/auth/login");
}
publicvoidlogin(Stringemail, Stringpassword) {
wait.until(ExpectedConditions.visibilityOfElementLocated(emailInput)).sendKeys(email);
driver.findElement(passwordInput).sendKeys(password);
driver.findElement(loginButton).click();
}
publicStringgetNavigationText() {
WebElementmenu = wait.until(ExpectedConditions.visibilityOfElementLocated(navMenu));
returnmenu.getText();
}
}Recommended file:
src/test/java/tests/LoginPageObjectTest.java
packagetests;
importbase.BaseTest;
importorg.junit.jupiter.api.DisplayName;
importorg.junit.jupiter.api.Test;
importpages.LoginPage;
importstaticorg.junit.jupiter.api.Assertions.assertTrue;
publicclassLoginPageObjectTestextendsBaseTest {
@Test@DisplayName("Customer can log in using LoginPage object")
voidcustomerCanLoginUsingPageObject() {
LoginPageloginPage = newLoginPage(driver, wait);
loginPage.open();
loginPage.login(System.getenv("CUSTOMER_EMAIL"), System.getenv("CUSTOMER_PASSWORD"));
assertTrue(loginPage.getNavigationText().contains("Jane Doe"));
}
}Recommended file:
src/test/java/utilities/ScreenshotUtil.java
packageutilities;
importorg.openqa.selenium.OutputType;
importorg.openqa.selenium.TakesScreenshot;
importorg.openqa.selenium.WebDriver;
importjava.io.File;
importjava.io.IOException;
importjava.nio.file.Files;
importjava.nio.file.Path;
publicclassScreenshotUtil {
publicstaticvoidtakeScreenshot(WebDriverdriver, StringfileName) throwsIOException {
Filescreenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
Pathdestination = Path.of("target", "screenshots", fileName + ".png");
Files.createDirectories(destination.getParent());
Files.copy(screenshot.toPath(), destination);
}
}git clone https://github.com/BrianGator/Selenium-Test-Automation-w-Java.git
cd Selenium-Test-Automation-w-Javajava -versionThe current pom.xml is configured for Java 21.
mvn -versionmvn clean installAfter test classes are added under src/test/java, run:
mvn testmvn -Dtest=LoginTest testmvn -Dtest=LoginTest#customerCanLoginWithValidCredentials testUse environment variables for test credentials.
macOS/Linux:
export CUSTOMER_EMAIL="your-demo-customer-email"export CUSTOMER_PASSWORD="your-demo-customer-password"Windows PowerShell:
$env:CUSTOMER_EMAIL="your-demo-customer-email"$env:CUSTOMER_PASSWORD="your-demo-customer-password"Do not commit real passwords, API keys, or personal credentials to GitHub.
Use:
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("email")));Avoid:
Thread.sleep(5000);Good selector examples:
By.cssSelector("[data-test='email']")
By.cssSelector("[data-test='login-submit']")
By.linkText("Claw Hammer with Shock Reduction Grip")Avoid brittle selectors:
By.xpath("/html/body/div[1]/div[2]/div[3]/button")Use @AfterEach to close the browser after every test.
@AfterEachvoidtearDown() {
if (driver != null) {
driver.quit();
}
}Each test should open the application, create its own test state, validate one clear behavior, and clean up after itself.
Move repeated selectors and page actions into page classes.
Example:
loginPage.open();
loginPage.login(email, password);Weak test:
driver.findElement(By.cssSelector("[data-test='add-to-cart']")).click();Better test:
driver.findElement(By.cssSelector("[data-test='add-to-cart']")).click();
assertEquals("1", driver.findElement(By.cssSelector("[data-test='cart-quantity']")).getText());Good:
voidcustomerCanLoginWithValidCredentials()Avoid:
voidtest1()Use environment variables, system properties, or a config.properties file for values such as:
- base URL
- browser type
- headless mode
- test usernames
- timeout values
Screenshots make debugging easier and improve portfolio evidence.
After tests are implemented, add a GitHub Actions workflow to run:
mvn teston every push or pull request.
Add tests under:
src/test/java/tests/
Centralize WebDriver setup and teardown.
Recommended page classes:
HomePage.java
LoginPage.java
ProductPage.java
CartPage.java
CheckoutPage.java
Recommended files:
src/test/resources/config.properties
src/test/resources/testdata/users.properties
Store screenshots under:
target/screenshots/
Recommended workflow path:
.github/workflows/selenium-tests.yml
Example workflow:
name: Selenium Java Testson:
push:
branches: [main]pull_request:
branches: [main]jobs:
test:
runs-on: ubuntu-lateststeps:
- name: Checkout codeuses: actions/checkout@v4
- name: Set up Javauses: actions/setup-java@v4with:
distribution: temurinjava-version: 21
- name: Run Maven testsrun: mvn testThe current pom.xml uses RELEASE for several dependencies. For repeatable builds, pin exact versions.
Example:
<selenium.version>4.25.0</selenium.version>
<junit.jupiter.version>5.11.0</junit.jupiter.version>
<webdrivermanager.version>5.9.2</webdrivermanager.version>Written by Brian McCarthy
Project repository:
https://github.com/BrianGator/Selenium-Test-Automation-w-Java