Self-healing test automation framework with Healenium integration. Demonstrates AI-powered locator healing to reduce test maintenance.
flowchart TD
A[TestRunner] -->|Runs| B[TestNG_Tests]
B --> C[PageObjects]
C --> D[WebDriver_Selenium]
D --> E[WebApp_Under_Test]
D --> F[Healenium_Proxy]
F -->|Heals_Locators| D
F --> G[Healenium_Backend]
G --> H[DockerCompose]
- What is Test Automation?
- Prerequisites
- Project Setup
- Understanding the Project Structure
- Key Concepts Explained
- Running Your First Test
- Understanding the Code
- Creating Your Own Tests
- Best Practices
- Troubleshooting
Manual Testing: You manually open the browser, navigate to the website, click buttons, enter text, and verify results.
Automated Testing: You write code (scripts) that automatically opens the browser, performs actions, and verifies results without your intervention.
Why Automate?
- Save time on repetitive tests
- Run tests overnight or on multiple browsers
- Consistent test execution
- Quick feedback on code changes
-
Java JDK 11 or higher
- Download from: https://www.oracle.com/java/technologies/downloads/
- Verify installation: Open terminal and type
java -version
-
Maven (Build Tool)
- Download from: https://maven.apache.org/download.cgi
- Follow installation guide for macOS
- Verify installation:
mvn -version
-
IDE (Integrated Development Environment)
- IntelliJ IDEA Community Edition (Recommended): https://www.jetbrains.com/idea/download/
- OR Eclipse: https://www.eclipse.org/downloads/
-
Google Chrome Browser
- Most tests use Chrome (already installed on most systems)
For IntelliJ IDEA:
- Open IntelliJ IDEA
- Click "Open"
- Navigate to
selenium-testng-automation-frameworkfolder - Click "Open"
- Wait for Maven to download dependencies (check progress bar at bottom)
For Eclipse:
- Open Eclipse
- File → Import → Maven → Existing Maven Projects
- Browse to
selenium-testng-automation-frameworkfolder - Click "Finish"
Maven will automatically download all required libraries (Selenium, TestNG, etc.) based on the pom.xml file.
To manually trigger download:
- IntelliJ: Right-click
pom.xml→ Maven → Reload Project - Eclipse: Right-click project → Maven → Update Project
selenium-testng-automation-framework/
│
├── src/
│ ├── main/java/
│ │ ├── pages/ # Page Object Model classes
│ │ │ ├── LoginPage.java # Login page elements & actions
│ │ │ ├── HomePage.java # Home page elements & actions
│ │ │ └── ProductPage.java # Product page elements & actions
│ │ │
│ │ └── utils/ # Utility/Helper classes
│ │ ├── DriverManager.java # Browser setup & management
│ │ ├── WaitHelper.java # Waiting mechanisms
│ │ └── ConfigReader.java # Read configuration files
│ │
│ └── test/
│ ├── java/
│ │ ├── base/
│ │ │ └── BaseTest.java # Parent class for all tests
│ │ │
│ │ └── tests/ # Test classes
│ │ ├── LoginTest.java
│ │ ├── HomePageTest.java
│ │ └── DataDrivenLoginTest.java
│ │
│ └── resources/
│ └── config.properties # Configuration settings
│
├── pom.xml # Maven dependencies & build config
├── testng.xml # TestNG suite configuration
└── screenshots/ # Auto-generated test screenshots
- pages/: Represents web pages. Each class contains elements and actions for one page.
- utils/: Helper classes used across the project.
- base/: Common setup code that all tests inherit.
- tests/: Your actual test cases.
- resources/: Configuration files (URLs, credentials, browser settings).
Think of it like this:
- Each web page in your application = One Java class
- Each element on the page (button, textbox) = One variable in the class
- Each action on the page (click, type) = One method in the class
Example:
// LoginPage.java
@FindBy(id = "username")
WebElement usernameField; // This finds the username textbox
public void enterUsername(String username) {
usernameField.sendKeys(username); // This types into it
}Benefits:
- If a button ID changes, you only update it in ONE place
- Tests remain clean and readable
- Easy to maintain
Annotations are special markers that tell TestNG what to do with your methods.
@BeforeMethod // Runs BEFORE each test (setup)
@Test // This is a test case
@AfterMethod // Runs AFTER each test (cleanup)
@DataProvider // Provides multiple test dataExecution Order:
- @BeforeMethod → Setup (open browser, navigate to site)
- @Test → Your actual test
- @AfterMethod → Cleanup (close browser, save screenshot)
WebDriver is the "robot" that controls the browser.
WebDriver driver = new ChromeDriver(); // Creates Chrome browser instance
driver.get("https://example.com"); // Opens website
driver.findElement(By.id("login")).click(); // Clicks element
driver.quit(); // Closes browser| Locator | Example | Use Case |
|---|---|---|
| id | @FindBy(id = "username") |
Fastest, most reliable (if available) |
| name | @FindBy(name = "email") |
Good alternative to id |
| className | @FindBy(className = "btn-primary") |
For elements with specific CSS class |
| linkText | @FindBy(linkText = "Forgot Password?") |
For links with exact text |
| xpath | @FindBy(xpath = "//button[@type='submit']") |
Most flexible, can find anything |
| cssSelector | @FindBy(css = ".login-button") |
Faster than xpath |
Assertions check if expected result matches actual result.
// Check if login was successful
Assert.assertTrue(homePage.isUserLoggedIn(), "Login failed!");
// Check if URL contains "dashboard"
Assert.assertTrue(driver.getCurrentUrl().contains("dashboard"));
// Check if text matches
Assert.assertEquals(actualText, "Welcome", "Text doesn't match!");If assertion fails → Test fails → Screenshot is captured
IntelliJ IDEA:
- Open
LoginTest.java - Right-click on class name or green arrow next to class
- Click "Run 'LoginTest'"
To run single test method:
- Right-click on specific
@Testmethod → Run
- Right-click on
testng.xml - Click "Run 'testng.xml'"
- This runs ALL tests in the suite
Open terminal in project folder and run:
mvn clean test- Chrome browser will open automatically
- Browser navigates to the test website
- Actions happen automatically (typing, clicking)
- Browser closes
- See results in console or TestNG report
@Test(priority = 1, description = "Verify login with valid credentials")
public void testValidLogin() {
// 1. Create page object instance
LoginPage loginPage = new LoginPage(driver);
// 2. Perform actions
loginPage.login(config.getUsername(), config.getPassword());
// 3. Verify result
String currentUrl = driver.getCurrentUrl();
Assert.assertTrue(currentUrl.contains("secure"),
"Login failed - User not redirected to secure page");
}Breaking it down:
-
@Test: Marks this as a test casepriority = 1: Run this test firstdescription: Explains what test does
-
Create Page Object:
LoginPage loginPage = new LoginPage(driver);
- Creates instance of LoginPage
- Passes
driverso it knows which browser to control
-
Perform Action:
loginPage.login(username, password);
- Calls the login method from LoginPage class
- Enters username & password, clicks login button
-
Verify Result:
Assert.assertTrue(currentUrl.contains("secure"), "Error message");
- Checks if URL contains "secure" (meaning login succeeded)
- If not, test fails with error message
- Right-click on
testsfolder - New → Java Class
- Name it:
YourFeatureTest.java
package tests;
import base.BaseTest;
import org.testng.Assert;
import org.testng.annotations.Test;
import pages.LoginPage;
public class MyFirstTest extends BaseTest {
@Test
public void testLogin() {
// Your test code here
}
}Important:
- Always extend
BaseTest(gives you browser setup) - Use
@Testannotation - Write descriptive method names
Think about your manual test steps, then convert to code:
Manual Steps:
- Go to login page
- Enter username: "tomsmith"
- Enter password: "SuperSecretPassword!"
- Click Login button
- Verify user reaches home page
Automated Steps:
@Test
public void testSuccessfulLogin() {
// Step 1: Browser already opens via BaseTest
// Step 2-4: Use page object
LoginPage loginPage = new LoginPage(driver);
loginPage.enterUsername("tomsmith");
loginPage.enterPassword("SuperSecretPassword!");
loginPage.clickLoginButton();
// Step 5: Verify
String url = driver.getCurrentUrl();
Assert.assertTrue(url.contains("secure"), "Login failed");
}Open testng.xml and add your test:
<test name="My New Tests">
<classes>
<class name="tests.MyFirstTest"/>
</classes>
</test>✅ Good: testLoginWithValidCredentials()
❌ Bad: test1()Don't try to test everything in one test. Keep tests focused.
✅ Good: Separate tests for valid login, invalid login, empty fields
❌ Bad: One giant test that tests all login scenariosAlways verify your test results.
@Test
public void testLogin() {
loginPage.login("user", "pass");
// Missing assertion - How do you know it worked?
}
// Better:
@Test
public void testLogin() {
loginPage.login("user", "pass");
Assert.assertTrue(homePage.isDisplayed(), "Login failed");
}If elements aren't found, add wait time:
Thread.sleep(2000); // Wait 2 seconds (simple but not recommended)
// Better: Use WaitHelper
WaitHelper wait = new WaitHelper(driver);
wait.waitForElementVisible(element);Don't hardcode URLs or credentials in tests. Use config.properties:
// ❌ Bad
driver.get("https://example.com");
// ✅ Good
driver.get(config.getUrl());// ❌ Bad
Assert.assertTrue(result);
// ✅ Good
Assert.assertTrue(result, "Login button is not clickable");Solution: WebDriverManager should handle this automatically. If not:
- Make sure Chrome is installed
- Check internet connection (downloads driver)
Causes:
- Element hasn't loaded yet → Add wait
- Wrong locator → Use browser DevTools to find correct locator
- Element is in iframe → Switch to iframe first
Solution:
// Add wait before finding element
Thread.sleep(2000);
// Or use explicit wait
WaitHelper wait = new WaitHelper(driver);
wait.waitForElementVisible(element);Cause: Timing issues (elements not loaded)
Solution:
- Add implicit wait in BaseTest
- Use explicit waits for critical elements
- Avoid using fixed Thread.sleep()
Solution:
- Check Java version:
java -version - Make sure JDK 11+ is installed
- Update
pom.xmlif using different Java version
Solution:
- Check internet connection
- Right-click
pom.xml→ Maven → Reload Project - Delete
.m2folder and rebuild
-
Beginner:
- Modify
testng.xmlto run only LoginTest - Change browser from Chrome to Firefox in
config.properties - Add a new assertion to existing test
- Modify
-
Intermediate:
- Create a new Page Object for "Product Page"
- Write 3 new test cases for product search
- Implement data-driven testing with 5 test data sets
-
Advanced:
- Add Excel file reading for test data
- Implement TestNG listeners for custom reporting
- Integrate with CI/CD (GitHub Actions)
- Add parallel test execution
Don't worry! This is normal and part of learning automation.
📖 See DEBUGGING_GUIDE.md for a complete step-by-step tutorial on:
- How to read error messages
- How to inspect elements with browser DevTools
- How to find correct locators
- How to fix failing tests
- Hands-on exercises
The debugging guide teaches you the most important skill in automation: troubleshooting!
Production-grade resilience pattern!
This project uses Healenium for automatic locator healing when web elements change.
Benefits:
- ✅ Tests auto-recover when locators change
- ✅ Reduces test maintenance
- ✅ Shows advanced Selenium skills
- ✅ Industry best practice
How it works:
// Healenium automatically finds alternative locators when original fails
@FindBy(id = "login")
WebElement loginButton; // If ID changes, Healenium finds it by other attributesSetup: See infra/docker-compose.yml to run Healenium backend services.
📚 EXERCISES.md - Learn by doing!
- 20+ hands-on exercises from beginner to expert
- Complete solutions with explanations
- Gradually detailed hints (3 levels)
- Exercise 6: Implement self-healing locators!
- Progress tracking checklist
- Challenge projects for mastery
- DEBUGGING_GUIDE.md - Fix failing tests
- CLEAN_CODE_GUIDE.md - Write maintainable code
- EXERCISES.md - 20+ practice exercises
- BUG_REPORTS.md - Intentional bugs + solutions
- TEST_PLAN.md - Complete test planning
- TEST_CASES.md - Test case specifications
- TRACEABILITY_MATRIX.md - Requirements traceability
- Selenium Documentation: https://www.selenium.dev/documentation/
- TestNG Documentation: https://testng.org/doc/documentation-main.html
- Maven Guide: https://maven.apache.org/guides/
- Java Basics: https://docs.oracle.com/javase/tutorial/
- Check browser console for JavaScript errors
- Use browser DevTools (F12) to inspect elements
- Read error messages carefully - they often tell you what's wrong
- Google the error message - others have likely faced same issue
What You've Learned:
- ✅ How to set up a Selenium project
- ✅ Page Object Model pattern
- ✅ Writing TestNG tests
- ✅ Running automated tests
- ✅ Best practices for maintainable tests
Remember:
- Start small - automate simple scenarios first
- Practice regularly - automation is a skill that improves with practice
- Don't try to automate everything - focus on stable, repetitive tests
- Keep learning - automation tools evolve constantly
Welcome to Test Automation! 🎉
This project follows clean code principles to ensure maintainable, readable test automation code.
- ✅ Meaningful Names: All classes, methods, and variables have descriptive names
- ✅ Single Responsibility: Each class/method does one thing well
- ✅ DRY (Don't Repeat Yourself): Reusable page objects and utilities
- ✅ Small Functions: Methods are short and focused
- ✅ No Magic Numbers: Constants used for timeouts and waits
- ✅ Clear Assertions: Every assertion has a descriptive failure message
- ✅ Consistent Formatting: Uniform code style throughout
📖 See CLEAN_CODE_GUIDE.md for a comprehensive guide on:
- What is clean code and why it matters
- 10 essential clean code principles with examples
- Before/after code comparisons
- Common code smells and how to fix them
- Practical refactoring exercises
- Clean code checklist
Good code is like a good joke - it needs no explanation!
Carolina Steadham
- GitHub: @steadhac
- LinkedIn: Carolina Steadham
⭐ Star this repo if you find it helpful!
Made with ❤️ and Python