How to Set Up Integration Testing in Playwright
Integration tests verify that your application works as a whole — not just that individual functions return the right values, but that a user can actually sign up, navigate to a page, perform an action, and see the expected result. Playwright is the modern standard for browser-based integration testing because it supports Chromium, Firefox, and WebKit, runs headlessly in CI, and provides an API that makes complex user interactions straightforward to script.
The biggest challenge with integration testing is not writing the first test — it is building a test suite that is reliable, fast, and maintainable as the product grows. Flaky tests erode trust. Slow test suites get skipped. This guide covers setting up Playwright with patterns that keep your tests stable and your CI pipeline fast.
Step-by-step guide
Install Playwright and initialize the project
Run npm init playwright@latest in your project root. The initializer creates a playwright.config.ts file, a tests/ directory with an example test, and installs browser binaries. Choose to install all three browsers (Chromium, Firefox, WebKit) for cross-browser coverage or just Chromium if you want to start fast. The config file is where you will configure base URL, timeouts, retries, and parallel execution.
- Run the init command and accept defaults for the test directory
- Verify browser installation with npx playwright install --with-deps
- Open the example test to confirm the setup works with npx playwright test
Configure the test environment with a base URL and global setup
In playwright.config.ts, set the baseURL to your local development server (e.g., http://localhost:3000). Add a webServer configuration that starts your dev server before tests run and waits for it to be ready. This ensures tests run against a consistent environment. Set the global timeout to 30 seconds for each test and the expect timeout to 5 seconds so tests fail fast when assertions do not match.
Write your first critical user flow test
Start with the most important user flow in your product — typically signup or login followed by a core action. Use Playwright's page object: navigate with page.goto(), interact with page.click() and page.fill(), and assert with expect(page.locator()). Use semantic locators (getByRole, getByText, getByLabel) instead of CSS selectors so tests are resilient to markup changes. One well-written critical path test catches more regressions than 20 shallow unit tests.
- Navigate to the login page and authenticate
- Perform the core user action (create, edit, or submit something)
- Assert that the expected outcome is visible in the UI
Implement the page object pattern for maintainability
Create a pages/ directory alongside your tests/ directory. For each major page in your application, create a class that encapsulates the locators and common actions. For example, a LoginPage class exposes login(email, password) and a DashboardPage class exposes createProject(name). Tests read like user narratives (loginPage.login(); dashboardPage.createProject()) instead of raw selector chains. When UI changes, you update one page object instead of 50 tests.
Set up test fixtures for authentication and data seeding
Use Playwright's fixture system to create reusable setup functions. Create an authenticated fixture that logs in once, saves the browser storage state to a file, and reuses it across tests. Create a data seeding fixture that calls your API to create test data before each test and cleans it up after. Fixtures eliminate duplicate setup code and make tests independent — each test starts from a known state.
Configure CI integration with GitHub Actions
Add a workflow file at .github/workflows/playwright.yml that installs dependencies, installs Playwright browsers with caching, starts your application, and runs the test suite. Use Playwright's sharding feature to split tests across multiple CI jobs for faster execution. Upload the Playwright HTML report as a GitHub Actions artifact so failing tests include screenshots, traces, and video for debugging.
- Cache Playwright browser binaries to speed up CI runs
- Configure test sharding for parallel execution across jobs
- Upload the HTML test report as an artifact for debugging failures
Common mistakes
Using CSS selectors instead of semantic locators
Selectors like .btn-primary or div > span:nth-child(2) break whenever the markup changes. Playwright's getByRole, getByText, and getByLabel locators are resilient to CSS and DOM changes because they match by user-visible attributes. This single change eliminates the most common source of test flakiness.
Not waiting for elements properly
Using hardcoded sleep() calls instead of Playwright's built-in auto-waiting causes both flakiness (sleep too short) and slowness (sleep too long). Playwright automatically waits for elements to be visible and actionable before interacting. Trust the auto-waiting and use expect(locator).toBeVisible() for explicit waits when needed.
Writing tests that depend on other tests
If test B depends on data created by test A, a failure in A cascades to B, C, and everything downstream. Each test should be independent: seed its own data, perform its own actions, and clean up after itself. Use fixtures to make independent setup easy.
Running all tests in a single browser only
A test that passes in Chromium might fail in Firefox or WebKit due to rendering or API differences. Configure Playwright to run against at least Chromium and one other browser. Cross-browser issues caught in CI are much cheaper to fix than cross-browser issues found by users.
Tips
Use Playwright's codegen tool (npx playwright codegen) to record user interactions and generate test code as a starting point — then refactor to use page objects and semantic locators.
Enable trace-on-first-retry in your config so that when a test fails and retries, the retry captures a full trace with screenshots, network requests, and console logs for debugging.
Tag tests with @smoke for your most critical 10-15 tests and run only those on every PR, with the full suite running nightly, to keep CI fast without sacrificing coverage.
Use Playwright's API testing features (request.newContext()) to seed test data via your API instead of navigating through the UI, making setup faster and more reliable.
How Vantage helps
Vantage generates tickets with testable acceptance criteria that map directly to integration test scenarios. When engineering implements a Vantage-generated ticket, the acceptance criteria can be translated into Playwright test cases, creating a direct line from product requirement to verified behavior.