This guide walks you through setting up automated testing for an existing web project from scratch. By the end, you will have unit tests that run in seconds, browser tests that verify your pages actually work, and a CI pipeline that runs everything automatically on every push to GitHub. You will see pass/fail results directly in your pull requests.
Get business pricing on monitors, keyboards and dev gear
- Business-only prices and quantity discounts
- Tax-exempt purchasing
- Multiple users, one account, clear invoices

Hands-On Automated Testing with Playwright: Create Fast, Reliable, and Scalable Tests for Modern Web Apps with Microsoft’s Automa…
- ✔ Format: Book
- ✔ Topic: Automated web testing with Playwright
- ✔ Framework: Microsoft Playwright

Software Testing with Selenium: Automated Testing Tool Book for Beginners
- ✔ Format: Book
- ✔ Topic: Selenium automated testing
- ✔ Framework: Selenium

Automated Testing Unleashed: Automated Testing Engineering Fundamentals — The Complete Handbook, Volume 1
- ✔ Format: Book
- ✔ Topic: Automated testing engineering fundamentals
- ✔ Series: Automated Testing Unleashed: The Complete Handbook
This guide is written for developers who already have a working web project (React, Vue, plain JavaScript, or similar) and basic comfort with the command line and npm. No prior testing experience is required — every command and config file is provided.
Expected time is 2-4 hours: roughly 1 hour for unit tests, 1 hour for browser tests, and 30-60 minutes for CI setup and debugging. The scope covers a JavaScript/TypeScript project. If you work in Python, Java, or another stack, the workflow is the same but you will swap in pytest, JUnit, or the equivalent.
Difficulty: Intermediate | Time: 2-4 hours
What You’ll Need
Tools & Materials:
- Node.js 18 or later installed (check with node –version)
- npm or another package manager (this guide uses npm)
- A code editor such as VS Code
- Git installed and a GitHub repository containing your project
- An existing web project with at least one page or component to test
Knowledge:
- Comfort running commands in a terminal
- Basic JavaScript or TypeScript syntax
- Familiarity with npm install and npm scripts
- Basic Git workflow: commit, push, pull request
Before starting, commit any uncommitted work and create a branch called setup-tests so your main branch stays stable: git checkout -b setup-tests. If your project has no package.json yet, run npm init -y first. Close other dev servers running on port 3000 or 5173 to avoid port conflicts during browser tests.
Hands-On Automated Testing with Playwright: Create Fast, Reliable, and Scalable Tests for Modern Web Apps with Microsoft’s Automa…

This Playwright-focused guide earns our top spot because of what the framework itself represents in 2026: a generation of test automation built around speed, reliability, and cross-browser coverage from a single API. Compared with the Selenium book in our lineup, this option teaches a tool that was designed to solve Selenium’s most persistent pain points — flaky tests caused by timing issues, complicated wait strategies, and fragmented browser support. For teams that maintain large test suites, that difference translates directly into fewer false failures and less time debugging tests instead of bugs.The hands-on approach is another reason this pick leads the ranking. Where Automated Testing Unleashed builds conceptual foundations, this book gets you writing runnable tests early, which matters because automation is a skill learned by doing. The stated focus on scalable and reliable test creation also suggests coverage of the architecture questions — test structure, maintainability, CI integration — that separate hobby scripts from production suites. The tradeoff is real, though: Playwright evolves quickly, and specific API details in any printed book will eventually drift from the current release. Compared with Selenium’s decades of stability, you’re accepting a faster obsolescence curve in exchange for a more modern toolkit.
Pros:
- Teaches a modern, in-demand automation framework backed by Microsoft
- Hands-on, practical structure that gets you writing real tests quickly
- Explicit focus on scalable and reliable test design, not just syntax
- Covers the tool that solves common pain points of older frameworks like Selenium
Cons:
- Playwright evolves rapidly, so printed material can become outdated
- Assumes some developer background — steeper on-ramp than a beginner Selenium guide
- Framework-specific skills don’t transfer automatically to other tools
Best for: Developers and QA engineers who want to build modern, maintainable web test automation and future-proof their skills
Not ideal for: Absolute beginners with no programming background, or readers in organizations locked into legacy Selenium suites
Bottom line: The strongest overall choice for anyone serious about web test automation in 2026, provided you’re comfortable keeping pace with a fast-moving framework.
“The strongest overall choice for anyone serious about web test automation in 2026, provided you’re comfortable keeping pace with a fast-moving framework.”
Software Testing with Selenium: Automated Testing Tool Book for Beginners

Not everyone needs the newest framework on the block, and that’s exactly the gap this Selenium beginner guide fills. Selenium has been the backbone of web test automation for roughly two decades, which means an enormous share of existing enterprise test suites — and the jobs that maintain them — still run on it. Compared with our Playwright pick, this book trades modern conveniences for market reach and accessibility: if you’re applying for QA roles at companies with established automation, Selenium fluency remains a baseline expectation rather than a bonus.The explicitly beginner-level positioning is what sets this option apart from the other two in our lineup. The Playwright book assumes developer experience, and Automated Testing Unleashed is an engineering handbook aimed at readers who want depth — this one is built for people starting from zero. That gentler on-ramp comes with genuine limitations, however. Beginner Selenium material tends to stop at the fundamentals of locating elements and scripting basic flows, leaving larger questions of test architecture unaddressed. And Selenium itself demands more manual effort around waits and browser management than Playwright does, so you’ll feel more of the framework’s rough edges as you progress. Still, as a first step into automation, it’s hard to argue with a tool this widely deployed.
Pros:
- Focused specifically on Selenium, the most widely deployed testing framework
- Explicitly designed for beginners with no prior automation experience
- Skills map directly to a huge number of existing QA job requirements
- Simpler entry point than framework-agnostic engineering handbooks
Cons:
- Limited public detail about the book’s actual content and depth
- Selenium lacks modern conveniences like Playwright’s auto-waiting, leading to more brittle tests
- Beginner scope won’t carry you into advanced test architecture
Best for: Career-switchers and junior testers who need marketable automation skills with the gentlest possible learning curve
Not ideal for: Experienced developers who want a modern framework, or readers seeking deep automation engineering theory
Bottom line: A sensible, low-friction starting point for newcomers, as long as you understand you may outgrow it — and Selenium’s quirks — fairly quickly.
“A sensible, low-friction starting point for newcomers, as long as you understand you may outgrow it — and Selenium’s quirks — fairly quickly.”
Automated Testing Unleashed: Automated Testing Engineering Fundamentals — The Complete Handbook, Volume 1

The first volume of the Automated Testing Unleashed handbook series takes the opposite approach from our other two picks: instead of teaching you a tool, it teaches you the discipline. Where the Playwright and Selenium books are bound to specific frameworks, this one covers automated testing engineering fundamentals — the concepts, practices, and design principles that stay useful whether you end up working in Playwright, Selenium, Cypress, or whatever comes next. For engineers who expect to change tools several times over a career, that durability is the entire value proposition.The handbook series format is also a meaningful differentiator. Volume 1 implies a structured, progressive curriculum rather than a one-off reference, which suits readers who want a systematic path through the subject. Compared with the beginner Selenium guide, this is a more demanding read — you’re studying engineering, not following tutorials — and compared with the Playwright book, you sacrifice immediacy: you won’t finish a chapter with a running test suite the way a hands-on guide allows. The honest caveat is that detailed content information is scarce, so depth and quality are harder to verify than we’d like. Treat this as the pick for building lasting judgment about test automation, and accept that you’ll still need a tool-specific resource to write actual code.
Pros:
- Teaches framework-agnostic fundamentals that outlast any single tool
- Structured as a handbook series, supporting long-term progressive learning
- Covers the engineering side — strategy, design, practices — that tool tutorials skip
- Complements either of the framework-specific books in this roundup
Cons:
- Very limited public information makes depth and quality difficult to verify
- Won’t teach you to write working tests in any specific tool
- Volume 1 of a series means an ongoing commitment to get full coverage
Best for: Engineers and technical leads who want durable, framework-agnostic knowledge of test automation principles
Not ideal for: Readers who want to start writing automated tests this week, or anyone on a tight learning budget that only allows one book
Bottom line: A worthwhile investment in career-long fundamentals, best paired with — not substituted for — a hands-on framework guide.
“A worthwhile investment in career-long fundamentals, best paired with — not substituted for — a hands-on framework guide.”
As an Amazon Associate we earn from qualifying purchases.
Before You Start
Decide what deserves a test now. You do not need full coverage on day one. Pick one pure function (a formatter, calculator, or validator) for your first unit test and one critical page (login, homepage, or checkout) for your first browser test. Starting small means you will finish the setup with a working pipeline instead of a half-finished test suite.
Also note: Playwright downloads browser binaries (roughly 300-400 MB) on first install. Run the install on a stable connection and allow time for it to complete.
Step-by-Step Instructions
Step 1: Install Jest and write your first unit test
Run npm install –save-dev jest in your project root. Then open package.json and add a test script so the scripts section reads:
“scripts”: { “test”: “jest” }
Now create a folder called __tests__ in your project root. Inside it, create a file named format.test.js. Write a test for one real function from your project. If you do not have an obvious candidate, use this example, which tests a price formatter:
function formatPrice(cents) { return (cents / 100).toFixed(2); }
module.exports = formatPrice;
Put that function in src/format.js, then in __tests__/format.test.js write:
const formatPrice = require(‘../src/format’);
test(‘formats cents as dollars’, () => {
expect(formatPrice(199)).toBe(‘1.99’);
expect(formatPrice(0)).toBe(‘0.00’);
});
Run npm test in your terminal.
Tip: Jest automatically picks up any file ending in .test.js or .test.ts inside __tests__ folders. You never need to register tests manually.
Check: The terminal prints ‘1 passed, 1 total’ in green. If you see ‘No tests found’, check the filename ends in .test.js and that you ran npm test from the project root.
Step 2: Add tests for the code most likely to break
Open the files that contain your validation, data transformation, or business logic. Add one test file per module inside __tests__, and write 3-5 tests per file covering: the normal case, edge cases (empty input, zero, very large values), and known error cases. For each test, follow the same pattern: import the function, call it with a specific input, and assert the output with expect(…).toBe(…) or toEqual(…).
For UI framework code, install the matching adapter so Jest can render components: npm install –save-dev @testing-library/react for React (plus jest-environment-jsdom and a docblock @jest-environment jsdom at the top of component test files), or @vue/test-utils for Vue.
Run npm test again after every few tests rather than writing them all at once.
Tip: Use toEqual for objects and arrays and toBe for primitives. A common beginner error is using toBe on an object, which compares references and always fails.
Check: npm test reports all tests passed. If a test fails, the output shows the expected versus received value for that exact test, which tells you whether the code or the test is wrong.
Step 3: Install Playwright and generate a browser test
Run npm install –save-dev @playwright/test, then run npx playwright install chromium to download the browser. Next, create a file playwright.config.js in the project root:
const { defineConfig } = require(‘@playwright/test’);
module.exports = defineConfig({
testDir: ‘./e2e’,
use: { baseURL: ‘http://localhost:3000’ },
webServer: { command: ‘npm run dev’, url: ‘http://localhost:3000’, reuseExistingServer: true }
});
Adjust the port to match your dev server (Vite defaults to 5173; check the output when you run npm run dev). Create a folder e2e and a file e2e/home.spec.js:
const { test, expect } = require(‘@playwright/test’);
test(‘homepage loads and shows heading’, async ({ page }) => {
await page.goto(‘/’);
await expect(page.locator(‘h1’)).toBeVisible();
});
Run npx playwright test.
Tip: The webServer config starts your dev server automatically before tests and stops it after, so you never need a second terminal. The reuseExistingServer flag prevents conflicts if your dev server is already running.
Check: Playwright prints ‘1 passed’ and reports the total run time (usually under 10 seconds for one test).
Step 4: Add a browser test for your critical user flow
In the e2e folder, create a second spec file for your most important flow, such as login. Write the test as a sequence of user actions:
test(‘user can log in’, async ({ page }) => {
await page.goto(‘/login’);
await page.fill(‘[data-testid=email]’, ‘test@example.com’);
await page.fill(‘[data-testid=password]’, ‘password123’);
await page.click(‘[data-testid=submit]’);
await expect(page.locator(‘[data-testid=welcome]’)).toBeVisible();
});
If your markup does not have data-testid attributes, add them to the relevant elements — this is the most reliable way to select elements in tests and keeps tests working when styling changes.
Run npx playwright test again. If a test fails, run npx playwright test –headed to watch the browser perform the steps and see exactly where it breaks, then open the trace with npx playwright show-trace trace.zip if the config has traces enabled.
Tip: Prefer data-testid selectors over CSS classes. Class names change during redesigns and will silently break your tests.
Check: Both spec files pass. The –headed run visibly performs the login flow in a browser window.
Step 5: Create the GitHub Actions workflow
In your repository, create the file .github/workflows/tests.yml (create the folders if they do not exist — the leading dot in .github is required). Add:
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-node@v4
with: { node-version: 20 }
– run: npm ci
– run: npm test
– run: npx playwright install –with-deps chromium
– run: npx playwright test
Commit and push the branch: git add . && git commit -m “Add automated tests and CI” && git push -u origin setup-tests.
Tip: Use npm ci instead of npm install in CI. It installs exactly what package-lock.json specifies and fails loudly if the lockfile is out of date.
Check: On github.com, open your repository, click the Actions tab, and watch a workflow named ‘Tests’ start running for your pushed branch.
Step 6: Open a pull request and verify the pipeline end to end
On GitHub, open a pull request from setup-tests into your main branch. Wait for the checks to finish (the first run takes 3-6 minutes because browsers must download). When the checks pass, merge the pull request. Then make any small change on main, push it, and confirm the workflow runs again automatically.
Finally, verify failure detection works: temporarily break a unit test (change an expected value), push to a branch, and confirm the GitHub check reports red. Revert the change and push again to see it return to green.
Tip: Testing the failure path once now means you will trust the green checkmarks later. A pipeline you have never seen fail is a pipeline you cannot fully trust.
Check: Your pull request shows a passing ‘Tests’ check, merging triggers a run on main, and a deliberately broken test produces a red X with a clickable failure log.
Common Mistakes to Avoid
- Testing implementation details instead of behavior, such as asserting a component’s internal state or a function’s call count. — Write tests against what the code outputs or what the user sees. If a refactor that keeps behavior identical breaks your tests, the tests were testing the wrong thing.
- Using fragile selectors like CSS classes or dynamic generated IDs in browser tests. — Add stable data-testid attributes to interactive and asserted elements, and select with page.locator(‘[data-testid=…]’).
- Forgetting to commit the package-lock.json, causing npm ci to fail in CI with a lockfile mismatch. — After any npm install, always commit package.json and package-lock.json together in the same commit.
- Pointing Playwright’s webServer config at the wrong port, so tests time out waiting for the dev server. — Run npm run dev once locally, note the URL it prints, and copy that port into both baseURL and webServer.url in playwright.config.js.
Troubleshooting
Problem: Playwright tests pass locally but time out or fail in GitHub Actions.
Solution: Confirm the workflow includes the npx playwright install –with-deps chromium step before running tests, and that webServer.url matches the port your app actually starts on. For React apps, also verify npm run dev (not npm start) is the command that serves the app on that port.
Problem: Jest fails with ‘Cannot use import statement outside a module’ or JSX syntax errors.
Solution: Your project uses ESM or JSX that Jest cannot parse by default. Run npm install –save-dev babel-jest @babel/preset-env @babel/preset-react, create a .babelrc with those presets, or switch your config to ts-jest if the project is TypeScript.
Problem: Browser tests are flaky — they pass and fail randomly on the same code.
Solution: Replace fixed waits like page.waitForTimeout(3000) with condition-based waits: await expect(locator).toBeVisible() or page.waitForSelector. Also run npx playwright test –repeat-each=3 locally to confirm stability before pushing.
Problem: The GitHub Actions workflow never appears in the Actions tab after pushing.
Solution: Check the exact file path: .github/workflows/tests.yml, with .github lowercase and no extra extensions like .yml.txt. YAML indentation must be spaces only — a single tab character invalidates the whole file.
What Success Looks Like
Your setup is complete and working when all of the following are true:
- npm test runs all unit tests locally and finishes in under a few seconds with everything passing.
- npx playwright test starts your dev server automatically, runs browser tests, and shuts the server down afterward.
- Every push and pull request on GitHub triggers the ‘Tests’ workflow automatically.
- A deliberately broken test produces a red check on the pull request, and fixing it restores the green check.
- You have at least one unit test per core logic module and at least one browser test covering your critical user flow.
Next Steps
With the pipeline running, grow it deliberately rather than all at once:
- Add a unit test every time you fix a bug — the test documents the bug and prevents its return.
- Set up npx playwright test –update-snapshots workflows if you adopt visual regression testing.
- Add coverage reporting with jest –coverage and a minimum threshold so coverage cannot silently drop.
- Once tests exceed five minutes in CI, run unit tests and browser tests as parallel jobs to keep feedback fast.
- Run security updates monthly with npm audit fix and keep Playwright browsers current via npx playwright install.
If your team grows past a few developers, add branch protection rules on GitHub so merges are blocked when checks fail — that turns your pipeline from a convenience into a guarantee.
Frequently Asked Questions
Do I need both unit tests and browser tests?
They cover different risks. Unit tests catch logic errors fast and cheaply; browser tests catch integration failures like broken routing, dead buttons, or rendering bugs. A practical split is many unit tests for logic and a small set of browser tests for critical flows, because browser tests are slower and cost more to maintain.
How long should the whole test suite take to run?
Keep unit tests under 10 seconds so developers run them constantly, and keep browser tests under 5 minutes in CI so feedback arrives before context is lost. If you exceed these times, parallelize jobs or trim browser tests that duplicate unit-test coverage.
Should browser tests run against my dev server or a production build?
Start with the dev server — it matches local development and makes debugging simpler. Once the suite is stable, switch the webServer command to a production build (for example, npm run build && npm run preview) for more realistic results.
Can I use this setup for a TypeScript project?
Yes. Install ts-jest or configure Jest with @babel/preset-typescript, keep test files as .test.ts, and Playwright works with TypeScript out of the box with no extra configuration.
What if my app requires a login for every page I want to test?
Use Playwright’s storageState feature: write one test that logs in, save the authenticated session with page.context().storageState(), and configure storageState in playwright.config.js so every test starts already logged in. This avoids repeating slow login steps in every spec file.
Fall Picks
fall essentials
As an affiliate, we earn on qualifying purchases.
