The Testing Academy · Class Notes Tuesday, 8 September (IST)
Live class · study guide

Why Playwright, what npm init gives you, and a test you recorded instead of wrote

The JavaScript and TypeScript groundwork is done, so this session opens the Playwright track: why the industry moved, what a rendering engine is and why Playwright can drive real browsers too, the honest list of things it cannot do, one command that scaffolds a project, and Codegen, which records a flow and hands you the code. Ends with a recorded test you can run before the next class.

By Pramod Dutta, The Testing Academy. Study notes from the live Playwright 3x class, rebuilt from the session recording, the new batch repository pushed during the session and the Eraser deck on screen. The project files, config and recorded spec are quoted from the repository. Both specs were run before publishing on the installed Playwright 1.63.0 and every CLI command shown in class was checked to exist. The README's architecture section was written after the class and is covered here only as a pointer, because the architecture itself was deferred to the next session.

01

Where this sits

The batch has spent its opening weeks on JavaScript and TypeScript, roughly 220 exercises across the two, and that was the point: loops, callbacks, async and await, and how a test file is structured are already familiar. Playwright on top of that is a smaller step than it looks.

Three standing reminders came first, and they were not optional:

  • The coding exercises continue. Five problems a week, released by Meeti and Deepak. Finish every easy challenge, then move to medium.
  • The live coding tests continue. An extra test is coming, probably on a Sunday. Attend on time.
  • The interview question bank has more than 1,500 Playwright questions collected from real interviews. Work through them and mark them done; there are points for it.

The new work lives in a new repository, separate from the JS and TS one.

02

Why Playwright

The room's answers came first: recording, auto-waiting, speed, AI features, less configuration. Then the two that actually matter.

Auto-waiting. Modern front ends (React, Vue, Angular) render dynamically, and Selenium's answer was a family of waits, implicit, explicit, fluent, that confuses beginners and intermediates alike. Playwright waits for an element to be ready before acting on it. There is nothing to configure.

One persistent connection. Selenium's WebDriver protocol sends an HTTP request per command. Playwright keeps a single connection open to the browser for the whole session, so commands and events flow both ways without that overhead, which is why it feels fast.

The architecture behind that second point, the driver, the WebSocket and the protocols, was explicitly deferred to the next class. If you want it now, the Playwright overview on the practice site walks it step by step.

The npm download trend was shown live: Playwright climbing steeply over the last year, Cypress and Selenium flat. The nuance, in the instructor's own words, is that Selenium is optional now, not dead.

A real migration, told as a case study. At TechCon, 50 QAs took about five years to build roughly 12,000 Selenium tests. Migrating them to Playwright by hand in six months was impossible. With AI (rules written once, Claude and Copilot doing the rewriting) about 97 percent moved in around a year. Two lessons: legacy suites do not vanish overnight, and the migration itself is now an AI job.

03

Rendering engine versus real browser

The most-asked interview question from this session, and the one the room got wrong first.

RENDERING ENGINE (about 80% of a browser) Chromiumopen source, by Google GeckoMozilla's engine WebKitApple's engine REAL BROWSER (engine plus UI, settings, extras) Chrome, Edge, Opera, BraveGemini is Google's addition, not Chromium's Firefox, Tor BrowserTor ships on Gecko too Safarithe finished product on WebKit Playwright drives the engines it ships(npx playwright install) and the real browsers,through channel Chromium-only configis what this batch uses,the other projects weredeleted from the file
An engine renders pages. A browser is an engine plus everything a user touches. Playwright handles both.

The analogy from the session: Chromium is a car with the engine, tyres and chassis complete and the outer body missing. Google finishes it into Chrome, Microsoft into Edge, Opera into Opera, which is why the three look alike. Firefox is Gecko finished; Safari is WebKit finished.

Two corrections to common beliefs:

  • Playwright does not only drive rendering engines. It drives real browsers too, through a setting called channel. The batch's config keeps Chromium only, and that is a choice, not a limit.
  • "Real browser" means what a user gets: tabs, settings, sign-in, extras. Chromium is a complete browser minus that layer.
04

What it is good at, and what it is not

The advantages list, from the deck: every major browser and engine, mobile browser emulation, reusable login state across tests, contexts, multiple domains, headed and headless, auto-wait, network mocking and capture, CSS and XPath and Playwright's own locators, file upload and download.

Reusing a login. Log in once, then use that state in the next test to go straight to the dashboard or the support page. This was the feature that got the loudest reaction, and it is the one Selenium suites spend the most effort faking.

The disadvantages list was given the same weight, and it is worth keeping:

Limitation What it means for you
No native mobile apps Mobile web yes, iOS and Android apps no. Use WebdriverIO or a mobile-specific tool for those
No desktop applications Same answer
A learning curve You need JavaScript and TypeScript first, which is why this batch did them first
Vendor lock-in risk Open source, but maintained by Microsoft. The Cypress story, free for years then priced, is the cautionary tale
Not a W3C protocol Selenium's WebDriver is a standard every browser must support. Playwright's protocol is its own. A future browser could support one and not the other
No legacy browsers IE11 and old Edge are out. Banks, mainframes and long-lived enterprise apps still run on them, which is why some large services firms cannot switch

Asked in class: does Playwright support mobile? Split the question. Mobile browsers: yes, with device emulation. Native mobile applications: no. The two kinds of app are different things, and the answer depends on which one you meant.

05

One command to set up a project

Prerequisite: Node.js, which everyone already has from the JavaScript weeks. Check it, then scaffold:

Terminal
node -v
npm -v
npm init playwright@latest

The older route, npm install piece by piece, still works and was shown as history. The init command asks four questions, and these were the answers used:

Prompt Answer
TypeScript or JavaScript? TypeScript
Where to put the tests? tests
Add a GitHub Actions workflow? No, later
Install the Playwright browsers? Yes

The last answer downloads the engines: Chromium, Firefox and WebKit, latest versions.

AFTER npm init playwright@latest playwright.config.tswhere tests live, workers, retries, reporter, browsers tests/example.spec.tsthe folder that matters: every test is a .spec.ts here package.jsonyour project's identity and its dependencies package-lock.jsonexact versions and download links, used by CI, not by you .gitignorewhat never reaches GitHub: node_modules, reports, .env node_modules/the installed libraries; nobody edits this npx playwright testruns everything under tests/npx playwright show-reportopens the HTML report on a local port(the built-in report is plain; better ones come later)
Six things, two of which you will actually open every day: the config and the tests folder.

A few details from walking the files:

  • package.json lists @playwright/test under devDependencies with a caret, ^1.63.0, which means "this version or newer within the major". The dev part means installed on your machine; CI installs its own copy.
  • The lock file pins exact versions and where they came from. It exists for CI. You will not edit it.
  • .gitignore was demonstrated with a made-up .env holding a password. Add the file name here and it never gets pushed. The init command does not create a .env; that one was typed live to make the point.
  • playwright.config.ts carries the test directory, fullyParallel, CI-only retries and workers, the HTML reporter, and the browser projects. The Firefox and WebKit projects were deleted so the batch runs Chromium only.

The config as pushed, comments removed:

TypeScript
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    trace: 'on-first-retry',
    headless: false
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
  ],
});
06

The first run, and headless

Install the Playwright Test for VSCode extension from Microsoft, then restart VS Code. A run button appears beside every test; right-click gives run, debug and reveal.

The generated sample test asserts the page title of playwright.dev. It failed on the first run because the expected text did not match the real title, and passed once the expectation was corrected to the actual title. That is a useful first failure: it shows the report, the diff, and that assertions are exact.

TypeScript
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await expect(page).toHaveTitle("Fast and reliable end-to-end testing for modern web apps | Playwright");
});

Headless means no window. The browser is real, screenshots and video still work, you just do not see it, and it is faster because nothing is painted. The rule given for this batch:

headless: false while you are building. true only when you are 100 percent done. It lives in the use block of the config, and the default is headless, so if nothing appears on screen that is why.

07

The CLI does more than run tests

npx playwright is a command with subcommands, and three were shown:

Terminal
npx playwright --version
npx playwright open https://sdet.live
npx playwright screenshot https://sdet.live abc.png

open launches a browser at the URL from the terminal. screenshot navigates and saves an image; the abc.png in the repository is that exact capture, 1280 by 720. There are more (install, install-deps, and the AI-facing ones for later), but one matters most.

08

Codegen: record it, then read it

npx playwright codegen opens two windows: a browser and a recorder. Everything you do in the browser becomes code in the recorder as you do it. Type a username, and a fill() appears. Click a button, and a click() appears.

You acttype, click, navigatein the real browser Recorder writesgetByRole().fill()getByTestId().click() Copy into a spectests/tta-check.spec.tstarget: Test Runner, TS Run itheadless: falsewatch it replay TWO MORE BUTTONS ON THE RECORDER Pick locator: hover any element and Playwright tells you the locator it would use. No more hunting. Target: switch the output to Python (pytest), Java (JUnit), C# (NUnit) or plain JavaScript from the dropdown.
Record and playback, like Selenium IDE, plus the two things Selenium IDE never had: a locator picker and multi-language output.

The recording made in class, exactly as it landed in the repository:

TypeScript
import { test, expect } from '@playwright/test';

test('test', async ({ page }) => {
  await page.goto('https://app.thetestingacademy.com/playwright/multiple_element_filter');
  await page.getByRole('textbox', { name: 'Email Address' }).click();
  await page.getByRole('textbox', { name: 'Email Address' }).fill('pramod');
  await page.getByRole('textbox', { name: 'Password' }).click();
  await page.getByRole('textbox', { name: 'Password' }).fill('123');
  await page.getByTestId('login-button').click();
//   await page.waitForTimeout(50000);
});

Two things about that file:

  • The locators, getByRole and getByTestId, were chosen by Codegen, not typed. What they mean is next week's topic; for now, notice that neither is a CSS selector.
  • The commented-out last line is the trick used in class to stop the browser closing so you can see what happened. It is a fake wait, not test code, and it stays commented for that reason. Without it the run finishes in a blink, which is what several people said.

Asked in class: instead of writing code, can I record and then copy? Yes, that is the workflow. The output is a starting point, not a finished test: remove stray clicks before fills, add assertions, rename the test. Codegen also exports to other languages, which is how a Python or Java team gets the same locators.

09

Tasks and announcements

Before the next class

  • Record one scenario with Codegen on a page of your choice: enter a username and password, click the button. Copy it into a spec file, run it with headless: false, and share a screenshot.
  • Do this with the VS Code extension installed, so the run button works for you the way it did on screen.
  • Post questions in the SDET club thread.

Continuing

  • Five coding exercises this week from Meeti and Deepak. Complete the easy challenges, then medium.
  • Do not miss the live coding tests.
  • Work through the interview question bank.

Next class: the Playwright architecture (what a WebSocket is, what CDP is, how the pieces talk), then the anatomy of the test you just recorded: page, async, await, test. Next week: the CLI, MCP and the AI agent features.

Announcements: the evening masterclass was to be confirmed within the hour, today or tomorrow depending on travel. The starter repository was pushed at the end of the session with a README covering install, setup and Codegen; its architecture section was added after class and goes deeper than this session did.