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

Headless & parallel — speed

Real-world engineering14 min
as a manual tester

Regression takes you two days because you're one person doing one thing at a time.

in automation

Machines aren't. Headless removes the rendering cost; parallel runs your tests four at a time. A 20-minute suite becomes 5.

Headless Chrome + the DriverFactory

Headless Chrome is the same browser without a window — needed for CI, faster everywhere. This finishes the DriverFactory promised in the framework lesson, honoring the -Dheadless=true flag your workflow already passes:

utils/DriverFactory.java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.*;

public class DriverFactory {
    public static WebDriver create() {
        ChromeOptions options = new ChromeOptions();
        if (Boolean.parseBoolean(ConfigReader.get("headless"))) {
            options.addArguments("--headless=new");        // modern headless mode
            options.addArguments("--window-size=1920,1080"); // or responsive layouts differ!
        }
        return new ChromeDriver(options);
    }
}

// BaseTest setUp() becomes one line:
//   driver = DriverFactory.create();
PowerShell
mvn test "-Dheadless=true"
predict: what does this print? think it through, then reveal
output
[INFO] Tests run: 14, Failures: 0, Errors: 0, Skipped: 0
[INFO] Total time:  01:57 min        ← was 03:10 with windows drawn
Set the window size in headless. Headless defaults to a small viewport; responsive sites render their mobile layout and your locators miss elements that are "there" on your machine. This is the #1 "passes locally, fails in CI" mystery — now pre-solved for you.

Parallel: JUnit does it natively

One properties file turns it on — no pom changes:

src/test/resources/junit-platform.properties
junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=same_thread
junit.jupiter.execution.parallel.mode.classes.default=concurrent
predict: what does this print? think it through, then reveal
output
[INFO] Tests run: 14, Failures: 0, Errors: 0, Skipped: 0
[INFO] Total time:  38.4 s           ← classes ran side by side

The chosen mode — classes in parallel, methods within a class sequential — is the safe default for UI suites: each class's tests share nothing, and each test still gets its own browser from @BeforeEach.

The catch that separates juniors from seniors

Parallel tests must be independent: no shared static driver, no test relying on another's leftovers, no two tests editing the same user's data. Every discipline this course insisted on — fresh browser per test, no ordering, API-created test data — was quietly preparing your suite to parallelize safely. If a suite fails only in parallel, one of those rules is being broken somewhere; that diagnosis skill is interview gold.

⚠ when it breaks — the classics
Green locally, red only in headless/CI
org.openqa.selenium.NoSuchElementException … (only with -Dheadless=true)

Fix: Headless Chrome defaults to a small viewport, so responsive sites render their mobile layout and elements move or hide. The fix is already in DriverFactory: --window-size=1920,1080 whenever headless is on.

Green serial, red only in parallel
(random failures that vanish when parallelism is off)

Fix: Shared state. The usual suspect is something static — a shared driver, a shared page object, shared test data. Every test must own its world; hunt the static.

My parallel config does nothing
(timings identical with and without it)

Fix: The file must be named exactly junit-platform.properties and live in src/test/resources. A typo in either means JUnit silently ignores it.

⚡ exercise · measure your speedup
  1. Add DriverFactory + the headless flag; run timed: normal vs -Dheadless=true.
  2. Add junit-platform.properties; run timed again.
  3. Record the three times. If parallel produced new failures, find the shared state (the usual suspect: something static).
  4. Push — your CI just got faster too.
key takeaways
  • --headless=new + explicit window size = CI-ready and faster everywhere.
  • junit-platform.properties enables parallel classes with zero pom changes.
  • Parallel safety = test independence — which your habits already guarantee.
← CI — tests on every push Suite test →