Personally I see playwright as a tool that goes into the direction of system/end-to-end tests. So I used playwright + jest to build-up user journeys and integrated them in a CI/CD process.
Since playwright created it's own test runner with useful features like taking videos and trace on failures, it would make sense to switch from jest to @playwright/test. On their home page playwright recommends to use test fixtures so I definitly want to include them in the switch.
In the following I will take amazon as an example.
With playwright + jest the first thing that I did was to create a function for generic setup of the environment:
function setupSuite({ browserOptions, userConfig }){
// create playwright browser and use browserOptions as overrides
// create page from browser
// register self-implemented trace and screenshot reporters to page
// go to baseUrl of current environment (e.g. local, branch etc..)
// click on cookie banner, since it's blocking the UI
// create a user based on userConfig (e.g. user has amazon prime user? payment options? etc.)
// return { browser, page, user, ... }
}
And of course a function to clean up everything again:
function teardownSuite(suite){
// close browser
// delete user
// etc..
}
Then I would use a file for each user journey. In case of amazon a user journey could be the successful processing of an order:
describe("Successful Order", () => {
let suite
beforeAll(async () => {
const userConfig = { isPrime: false, paymentOptions: [ "paypal", "visa" ] }
suite = await setupBrowser({ userConfig })
// I actually extracted that logic in a function to be able to use it in other tests too,
// but just want to make clear whats happening here
const { page, user } = suite
await page.fill(".login-username-input", user.username)
await page.fill(".login-password-input", user.password)
await page.click(".login-submit-button")
})
afterAll(() => teardownSuite(suite))
test("search for toothbrush with suggestions", async () => {
const { page } = suite
await page.fill(".search-input", "tooth")
await page.click("text='toothbrush")
// hit enter
// do some assertions to check if the search was really successful
})
test("click on first item and add to chart", async () => {
// page actions and assertions
})
test("go back, click on second item and add to chart", async () => {
// page actions and assertions
})
test("go to chart and pay", async () => {
// page actions and assertions
})
test("check order confirmation mail", async () => {
// page actions and assertions
})
})
As you can see I split up my test in logical parts to make it more readable and also to see at which step (test block) it failed.
What would be the best way to migrate this to @playwright/test + fixtures?
- How would you migrate
setupSuite/teardownSuite? Yes you could use a fixture, butsetupSuiteexpects arguments like the userConfig . Is it possible to have parameterized fixtures? - How would you structure tests with fixtures? If you want to simulate complete user journey the tests are getting bigger than just testing a login for example. A test block would then have a lot of lines without the possibility to structure them.
- Is it possible to setup a page so it's shared accross all tests? The
beforeAllhook doesn't receive any page and the eachtestblock always receives its own page. This means that there is no connection betweentestblocks. If you create a page manually inbeforeAlland use the same page instance in every test it would probably be a bad practice and video and tracing would probably not work.. so what can be done here? - Are user journey like tests actually bad? I feel like they can't be combined well with the fixture approach of
playwrightas mentioned in the docs. Fixtures inplaywrightfeel like verydata-drivenwhich doesn't really fit toend-to-endtesting IMO.