Your test cases reference shared modules: 'see Login procedure' instead of copy-pasting steps into all 40 cases.
The Page Object Model is that, for code: one class per page owns its locators and actions. The OOP lesson's promise, delivered.
Your tests so far mix three concerns in one method: locators, actions, and assertions. Fine for two tests; a disaster for two hundred. When the login page changes, you'd edit every test that logs in. The industry's answer is the Page Object Model (POM):
public class LoginPage { private WebDriver driver; // locators live here — and ONLY here private By usernameField = By.id("user-name"); private By passwordField = By.id("password"); private By loginButton = By.id("login-button"); private By errorMessage = By.cssSelector("[data-test='error']"); public LoginPage(WebDriver driver) { this.driver = driver; } public void open() { driver.get("https://www.saucedemo.com"); } public void loginAs(String user, String pass) { driver.findElement(usernameField).sendKeys(user); driver.findElement(passwordField).sendKeys(pass); driver.findElement(loginButton).click(); } public String getErrorMessage() { // questions return values... return driver.findElement(errorMessage).getText(); } }
@Test void lockedOutUserSeesError() { LoginPage loginPage = new LoginPage(driver); loginPage.open(); loginPage.loginAs("locked_out_user", "secret_sauce"); System.out.println("Error shown: " + loginPage.getErrorMessage()); assertTrue(loginPage.getErrorMessage().contains("locked out")); }
[INFO] Running LoginTest Error shown: Epic sadface: Sorry, this user has been locked out. [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] BUILD SUCCESS
Read the test aloud — it's plain English. That's the POM payoff #1. Payoff #2: when the login page's ids change, you edit four lines in one file and every test heals.
getErrorMessage()); tests judge it. Mixing them makes pages unreusable.src/main/java/pages, tests in src/test/java/tests. Your capstone will follow it.return new ProductsPage(driver);) enabling chained, fluent tests. Nice pattern — adopt it when the basics feel comfortable, not before.Fix: The page object never received the driver — either the constructor doesn't assign it (this.driver = driver;) or you created the page before @BeforeEach ran. Create pages inside the test method.
Fix: Folder and import mismatch: pages live under src/main/java/pages, so the test needs import pages.LoginPage;. If IntelliJ underlines the folder, right-click src/main/java → Mark Directory as → Sources Root.
Using your Suite 03 locator inventory:
ProductsPage with: getTitle(), addBackpackToCart(), getCartCount().By. references.public class ProductsPage { private WebDriver driver; private By title = By.className("title"); private By addBackpack = By.id("add-to-cart-sauce-labs-backpack"); private By cartBadge = By.className("shopping_cart_badge"); public ProductsPage(WebDriver d) { driver = d; } public String getTitle() { return driver.findElement(title).getText(); } public void addBackpackToCart() { driver.findElement(addBackpack).click(); } public String getCartCount() { return driver.findElement(cartBadge).getText(); } }