skip to content

How do you make `npx playwright codegen` emit pytest code instead of TypeScript?

level: middleimportance: should knowfreq 44%

answer

  1. One flag, many bindings
  2. The dropdown does the same thing
  3. Default emits a test block
  4. Runner targets versus library targets
  5. Language, not browser engine

basics

~10 s

Pass --target python-pytest, or switch the language dropdown in the recorder window. The default target is playwright-test, and --target only changes the binding the same recorded actions are printed in.

solid answer

~30 s

`npx playwright codegen --target python-pytest -o test_track_order.py https://tracker.example.com` records the same session but prints it as pytest code; the recorder window's language dropdown does the same thing live. As of Playwright 1.63 the values include `playwright-test` (the default), `javascript`, `python`, `python-async`, `python-pytest`, `java`, `java-junit`, `csharp`, `csharp-mstest` and `csharp-nunit`. The split that matters is runner targets versus library targets: `playwright-test`, `python-pytest`, `java-junit` and `csharp-nunit` emit a test function that receives a ready `page`, while `javascript`, `python`, `java` and `csharp` emit a standalone script that launches a browser, does the work and closes it. The recorded actions and locators are identical either way.

code

bash · 5 lines
bash
# pytest output, saved to a file
npx playwright codegen --target python-pytest -o tests/test_track_order.py https://tracker.example.com

# a standalone Node script that launches and closes its own browser
npx playwright codegen --target javascript -o scripts/track-order.js https://tracker.example.com

go deeper

for a junior

Know that the output language is a choice, set with --target or the recorder's dropdown, and that the default gives you a Playwright test block rather than a standalone script.

for a middle

Explain the runner-versus-library split: one target family produces a test function handed a ready page, the other a program that launches and closes its own browser.

for a senior

Recognise that only the binding changes. If a recording is wrong, switching targets will not fix it, because the actions and locators were decided during recording.

for a principal

Consider the polyglot case: teams on Python, Java or .NET get the same recorder, so codegen is a shared onboarding tool rather than something only the Node-based suite benefits from.

`--target` chooses which language and which harness the recorded actions are printed in. It changes nothing about the recording itself. ## Setting it Two equivalent routes: 1. on the command line — `npx playwright codegen --target python-pytest https://tracker.example.com`; 2. in the recorder window — the language dropdown at the top, switchable mid-session, which re-renders everything recorded so far in the new binding. Combine with `-o` to write straight to a file: `-o tests/test_track_order.py`. Pick an extension that matches the target; the flag does not rename the file for you. ## The values, and the split that matters As of Playwright 1.63 the accepted values are `playwright-test` (the default), `javascript`, `python`, `python-async`, `python-pytest`, `java`, `java-junit`, `csharp`, `csharp-mstest` and `csharp-nunit`. They fall into two families: | family | example values | what comes out | | --- | --- | --- | | runner targets | `playwright-test`, `python-pytest`, `java-junit`, `csharp-nunit`, `csharp-mstest` | a test function that receives a ready-made `page`, with no launch or teardown code | | library targets | `javascript`, `python`, `python-async`, `java`, `csharp` | a standalone program that launches a browser, opens a context and page, runs the steps, then closes both | That is the distinction interviewers are usually probing. A library target's output is runnable on its own — useful for a scraping script or a one-off reproduction of an order-tracker bug — while a runner target's output drops into an existing suite, because setup and teardown are the runner's job. ## What does not change - the actions recorded and their order; - which element each step targets — the same locator preferences apply in every language, so a click recorded as `getByRole('button', { name: 'Refresh status' })` appears as `get_by_role("button", name="Refresh status")` in Python and the equivalent in Java or C#; - the assertions you inserted from the toolbar, rendered in the target's assertion style. ## Practical notes - The default is `playwright-test`, so a Node user who never passes the flag gets a `test('test', async ({ page }) => { ... })` block using the `page` fixture. - Switching the dropdown mid-recording is the quickest way to see the same flow in two bindings side by side — handy when a team runs its suite in Python but you are more fluent in TypeScript. - The Python and Java CLIs expose the same recorder through their own entry points, so a team that does not have Node in the loop still gets codegen. - `--target` is unrelated to `-b` / `--browser`: one picks the output language, the other the engine doing the recording. Mixing them up is a common slip.

  • What is different about the code produced by `--target javascript` versus the default?
    `--target javascript` emits a standalone program: it launches a browser, creates a context and page, runs the steps and closes everything, so you can execute the file directly. The default `playwright-test` emits a `test()` block that takes the `page` fixture and leaves lifecycle to the runner, which is what you want when the code is joining an existing suite.

saying these in an interview costs you the question

  • Assumes codegen can only emit JavaScript or TypeScript
  • Thinks --target selects which browser records
  • Believes the library targets emit a test function
  • Cannot name the default target
  • Expects -o to rename the file for the target