assert_
glossary ↓ downloads
track: java · selenium
suite 07 · real-world engineering

Designing a framework

Real-world engineering15 min
as a manual tester

You keep a well-organized test repository: naming conventions, folders per module, a data section.

in automation

A framework is that organization for code — plus config so one switch changes environment or browser for every test at once.

"Framework" sounds grand; it's mostly agreed structure. Here's the layout your capstone will use — and a close cousin of what you'll meet in real jobs:

the framework layout
src
├─ main/java
│   ├─ pages/            LoginPage, ProductsPage, CartPage...
│   └─ utils/            ConfigReader, DriverFactory
├─ test/java
│   ├─ tests/            LoginTest, CheckoutTest, ApiTests...
│   └─ BaseTest.java
└─ test/resources
    ├─ config.properties  base URL, browser, timeouts
    └─ testdata/          CSVs for data-driven tests

Configuration — stop hardcoding

Your tests currently hardcode https://www.saucedemo.com. Real teams run the same tests against dev, staging, and prod. Externalize it (a ready sample file is in the downloads):

src/test/resources/config.properties
baseUrl=https://www.saucedemo.com
browser=chrome
timeoutSeconds=10
utils/ConfigReader.java
import java.util.Properties;
import java.io.InputStream;

public class ConfigReader {
    private static final Properties props = new Properties();

    static {
        try (InputStream in = ConfigReader.class
                .getResourceAsStream("/config.properties")) {
            props.load(in);
        } catch (Exception e) { throw new RuntimeException("config.properties missing", e); }
    }

    public static String get(String key) {
        // -Dkey=value on the command line overrides the file — CI will use this
        return System.getProperty(key, props.getProperty(key));
    }
}
PowerShell — same tests, different target
mvn test                                          # uses config.properties
mvn test "-DbaseUrl=https://staging.example.com"  # override for one run

That System.getProperty fallback line is quietly the most professional line in this course: it's how CI pipelines point the same suite at any environment without touching code.

The other pillar: DriverFactory

Browser creation moves out of BaseTest into one place that reads config — so browser=firefox or a -Dheadless=true flag changes every test at once. You'll finish this in the headless lesson. The principle in both pillars is the same one that gave you POM: every decision lives in exactly one place.

⚠ when it breaks — the classics
ConfigReader can't find the file
java.lang.RuntimeException: config.properties missing

Fix: The file must live in src/test/resources (create the folder if needed) and the resource path starts with a slash: getResourceAsStream("/config.properties"). In IntelliJ, the folder should show the resources icon.

My -DbaseUrl override is silently ignored
(tests keep hitting the old URL)

Fix: Two culprits: property keys are case-sensitive (-DbaseURLbaseUrl), and PowerShell eats the flag unless quoted: mvn test "-DbaseUrl=https://staging.example.com".

⚡ exercise · de-hardcode your suite
  1. Add config.properties and ConfigReader to your project.
  2. Change LoginPage's open() to use ConfigReader.get("baseUrl").
  3. Run normally, then run with -DbaseUrl=https://www.saucedemo.com/ (trailing slash) to prove the override works.
  4. Sweep your code for any remaining hardcoded URLs, timeouts, or credentials; move them to config.
key takeaways
  • A framework = agreed structure: pages/, tests/, utils/, resources/.
  • Config externalizes URLs, browsers, timeouts; -D overrides enable CI.
  • Every decision in exactly one place — the theme behind POM, config, and DriverFactory.
← Back to roadmap CI — tests on every push →