Ask
124
@thriftedtweed ·

new to playwright: how do people actually reset the db between specs Playwright

First real e2e suite I have written. Every tutorial says reset the database between tests and then shows a beforeEach that truncates everything, which obviously explodes the moment I run more than one worker.

40 specs, 4 workers, one Postgres. I have tried running serially and it takes 11 minutes, which is not a life.

What do people do in actual projects? I feel like I am missing something obvious.

9 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @r2_bucketeer · 6mo ago · 3 replies

    You are not missing anything. The tutorials are describing a serial suite and nobody updated them.

    The pattern that survives parallelism is: do not reset, isolate. Every test creates its own tenant/org/user with a unique id and only ever touches rows under it. Truncate once at the start of the run and never again.

    Two things fall out of this for free:

    • your app gets a genuine multi-tenancy test on every run, because a test that can see another test's data has found a real bug in your scoping
    • adding workers costs nothing, because there is no shared mutable state to fight over

    The version that scales further is a worker-scoped fixture: one seeded org per worker, created once, reused by every spec in that worker.

    178
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @stropping_sal · 6mo ago

      Worker-scoped is the ergonomic sweet spot. Per-test creation is purest but you pay a signup round trip 40 times; per-worker you pay it four times and tests still cannot collide across workers.

      45
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @fg_stall · 6mo ago

      Name the tenant after the parallel index plus a timestamp and put it in a header. When something fails at 2am you can grep the server logs for exactly that test's requests.

      18
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @compost_turner · 6mo ago

    Do not spend a week on transaction-per-test. It does not work for e2e and lots of people lose time to it before working out why.

    Your test's transaction lives in the test process on one connection. The app's queries run in the server process on a different connection. The server cannot see your uncommitted rows, so either your setup is invisible or you commit and you are back where you started. It is a great pattern for integration tests inside a single process, and only there.

    95
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @thermal_theo · 6mo ago

    Also: log in once, not forty times. Do the login in global setup, save storageState per role, and load it in the specs. On most suites the UI login is a bigger chunk of runtime than anything database related, and it is the flakiest step you own.

    61
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @adjunct_life · 6mo ago

    The truncate-between-tests advice is not stupid, it is just old. It comes from single-threaded suites where it was correct and cheap. It got repeated for fifteen years without the assumption attached.

    16
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @overlap_owen · 6mo ago · 2 replies

    Seed through your own API rather than raw SQL. Insert rows directly and you will eventually create a state your application cannot produce, then spend a day chasing a bug that only exists in the fixture.

    29
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @blown_cap · 6mo ago

      Mild disagreement. API seeding is three or four times slower and on a 40 spec suite that is minutes. Direct SQL for the boring background furniture, API for whatever the test is actually about. Best of both and the invalid-state risk stays small.

      13
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @sawdust_pete · 6mo ago

    Whatever you build, guard the reset behind a check that the database name ends in _test. Do not ask how I know.

    6
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report