You've spent eight chapters building skills. This chapter is where you put them all to work on one realistic project. The capstone is a complete Selenium + TestNG test framework for FlyRight — a flight booking web application. Every concept from chapters 1–8 lands here: Maven project structure, Page Object Model, fluent design, BasePage inheritance, TestNG groups and dependencies, @DataProvider from Excel and JSON, ThreadLocal driver management, parallel cross-browser execution, screenshot listeners, CI/CD pipelines. By the end you'll have a portfolio-grade GitHub repository that demonstrates end-to-end QA automation skills — the exact thing recruiters ask to see when "Selenium + Java" is on your CV.
The application
FlyRight is a typical airline booking site. You can use any real one (Skyscanner, Kayak, an airline's own site like easyJet or Lufthansa) as your target, or use a public test sandbox like PHPTRAVELS or a similar fake-flight-booking demo. The exact site doesn't matter — what matters is that the test surface is realistic.
The user flow you're automating:
- Home page — a search form: origin, destination, departure date, return date (one-way vs round-trip toggle), passenger count, cabin class.
- Search results — list of flights with sort and filter controls (price, duration, airline).
- Flight selection — pick outbound (and inbound for round-trips); see a fare breakdown.
- Passenger details — names, dates of birth, contact info, seat selection.
- Payment — card details, billing address; success and failure paths.
- Confirmation — booking reference, itinerary summary, "send confirmation email" toggle.
- Manage bookings — login → booking history → modify/cancel.
This is intentionally varied: search forms, results lists, multi-step booking, payment flows, authenticated areas, table-of-bookings UI. Almost every Selenium pattern in this course gets exercised.
What you're building
Your final repository should have these ten deliverables, each tied to a chapter you've already worked through:
- Maven project (chapter 1).
pom.xmlwithselenium-java,testng,webdrivermanager,poi-ooxml,jackson-databind, plusmaven-surefire-plugin. Standardsrc/test/java/src/test/resourceslayout. - BaseTest with ThreadLocal driver (chapters 6, 8). A
DriverManagerholdingThreadLocal<WebDriver>,BaseTestwired to it via@BeforeMethod/@AfterMethod, browser-aware via@Parameters("browser")with CLI override. - BasePage with reusable helpers (chapter 6).
click(By),type(By, String),getText(By),isDisplayed(By),waitForInvisibility(By). Every concrete page extends it. - Page Objects (chapter 6).
HomePage,SearchResultsPage,FlightDetailsPage,PassengerDetailsPage,PaymentPage,ConfirmationPage,MyBookingsPage. Fluent style — same-page methods returnthis; navigation methods return the next page object. - TestNG suites (chapter 5).
smoke.xml(the must-pass-on-every-commit subset, ~5 tests),regression.xml(full coverage),cross-browser.xml(parallel Chrome + Firefox). Smoke and regression groups tagged on each@Test. - DataProvider tests (chapters 5, 7). Search routes from
routes.xlsx(Apache POI), login credentials fromusers.json(Jackson). Both feed parameterised tests that produce one TestNG result per data row. - At least 25 test methods, distributed roughly:
- Search (5): valid one-way; valid round-trip; past-dated departure rejected; no results message; result-list sorting.
- Booking flow (5): end-to-end happy path; passenger-form validation; payment success; payment decline; confirmation page contents.
- User account (5): login; registration; booking history list; profile update; logout.
- Cross-browser (5): the 5 most user-visible flows on Chrome + Firefox.
- Data-driven (5): parameterised search across five route combinations.
- TestNG listeners (chapter 5). Screenshot-on-failure (writes to
target/screenshots/), a console listener for live test progress, and aRetryAnalyzerapplied to a small set of historically-flaky tests. - Reporting (chapter 5). TestNG default reports (free), plus either Allure or ExtentReports for the rich HTML view. CI uploads the report as an artefact.
- CI pipeline (chapter 8). Either a
Jenkinsfileor.github/workflows/selenium.yml(or both). Triggers on push and PR, runs smoke; nightly cron runs cross-browser regression.
Build all ten and you've shipped a real Selenium framework. Recruiters and tech leads will recognise it instantly.
Stretch goals
If the core ten go faster than you expect, take on any of these:
- Selenium Grid in Docker (chapter 7). A
docker-compose.ymlwith hub + 3 Chrome nodes + 2 Firefox nodes. Tests run viaRemoteWebDriveragainstlocalhost:4444. - Cloud cross-browser via BrowserStack/Sauce Labs (chapter 7).
RemoteWebDriverpointed at a cloud hub with credentials insecrets. Run one or two tests against Safari on macOS — proof your framework is cloud-ready. - API-side test data setup. Before each test, hit a
POST /api/test-usersendpoint to seed a fresh user — eliminates inter-test data pollution. Adds a smallTestDataApihelper class that@BeforeMethodcalls. - Performance gating. Use
JavascriptExecutorto readperformance.timingand assert thatdomContentLoadedis under 2s. A test that fails on perf regressions is the kind of thing senior QA engineers build. - Visual regression. A small library like Applitools or your own pixel-diff utility, called from the listener on key screens. Catches CSS regressions that functional tests miss.
Don't try to do all of these — pick one or two that interest you. Done is better than impressive.
Mapping deliverables to chapters
- – Maven pom.xml + dependencies
- – WebDriverManager / Selenium Manager
- – Locator strategy (data-testid first)
- – By + WebElement interaction methods
- – WebDriverWait + ExpectedConditions
- – Sync issue patterns (stale, intercepted)
- – Actions class for hover, drag-drop
- – Iframe & multi-window flows for payment
- – TestNG annotations + lifecycle
- – Suites, groups, dependencies
- – @DataProvider for parameterised tests
- – POM, fluent style, BasePage inheritance
- – Listeners, screenshot-on-failure, retry
- Excel + JSON test data –
- Cross-browser via @Parameters –
- Selenium Grid (Docker) –
- ThreadLocal<WebDriver> for parallel –
- Jenkins / GitHub Actions pipelines –
Acceptance criteria — how you'll know it's done
The capstone is complete when, in a single command, you can:
git clone <your-repo>
cd flyright-tests
mvn clean test -DsuiteFile=smoke.xml…and on a fresh laptop with Java 21 and Maven installed, the smoke suite runs green in headless Chrome. No manual setup, no "you also need to install ChromeDriver", no environment-specific tweaks. The README documents how to run regression and cross-browser, and the GitHub Actions / Jenkins pipeline runs every push.
That's the bar. It's the same bar professional QA frameworks meet, and it's what you'll show in interviews. The next two lessons are the guided walkthrough — you'll see complete code for the BaseTest, BasePage, the first three page objects, the DataProvider tests, the listener, and the GitHub Actions workflow. Lesson 3 is the self-assessment and the stretch goals.
Project work
Set up the project shell. 30–45 minutes.
- Create a new GitHub repo named
flyright-selenium-tests. Public is fine — this becomes a portfolio piece. - Locally, scaffold the Maven project (chapter 1's pattern):
flyright-tests/ ├── pom.xml ├── README.md ← will fill out at the end ├── .gitignore ← include target/, .idea/, *.iml, /screenshots/ ├── src/test/java/com/flyright/ │ ├── base/ ← BaseTest, BasePage, DriverManager │ ├── pages/ ← HomePage, SearchResultsPage, ... │ ├── tests/ ← LoginTest, SearchTest, BookingTest, ... │ ├── listeners/ ← ScreenshotListener, ConsoleListener, RetryAnalyzer │ ├── utils/ ← ExcelReader, JsonReader, TestDataApi │ └── data/ ← LoginScenario, TestUser POJOs └── src/test/resources/ ├── smoke.xml ├── regression.xml ├── cross-browser.xml ├── testdata/ │ ├── routes.xlsx │ ├── users.json │ └── ... └── environments.json ← baseUrl per env - Pick your target site. Either a real airline (use a sandbox account if booking flows would charge real money) or a public test demo. Note the base URL.
- Decide on selectors. Open DevTools on the home page; if the dev team uses
data-testid, great. If not, plan to fall back toid/name/aria-labeland only use class-based selectors when nothing better exists. - Create the GitHub repo, push the empty scaffold, and verify it clones cleanly on another machine. The first thing to test is the project structure itself.
You're ready to start coding. The next lesson walks the build with complete code for every key class.