Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Box Test Steps in Playwright
     

Box Test Steps in Playwright

We have a scenario where we are running a variety of tests to test that a user can add products to the shopping cart. On doing this we have realised that we have some duplicate code.

Each test has the same code to add a product to the cart. When we create a helper function for this we can use thetest.step method to group several actions into one named step and then set thebox option totrue so that errors inside the step are not shown and we therefore hide the implementation details for this step. Let's take a look at how this works.

Our Test Scenarios

On our site there are many ways to add a product such as from the main hero banner, from the search box and from the all products page. We have created a test for each of these scenarios.

import{test,expect}from'@playwright/test';test.describe('add to cart scenarios',()=>{test.beforeEach(async({page})=>{awaitpage.goto('https://cloudtesting.contosotraders.com/')});test('add to cart from carousel',async({page})=>{awaitpage.getByRole('button',{name:'Buy Now'}).click();awaitpage.getByRole('button',{name:'Add To Bag'}).click();awaitpage.getByLabel('cart').click();awaitexpect(page.getByText('Xbox Wireless Controller Lunar Shift Special Edition')).toBeVisible();});test('add to cart from search',async({page})=>{constproduct='Xbox Wireless Controller Mineral Camo Special Edition'constplaceholder=page.getByPlaceholder('Search by product name or search by image')awaitplaceholder.click();awaitplaceholder.fill('xbox');awaitplaceholder.press('Enter');awaitpage.getByRole('img',{name:product}).click();awaitpage.getByRole('button',{name:'Add To Bag'}).click();awaitpage.getByLabel('cart').click();awaitexpect(page.getByText(product)).toBeVisible();});test('add to cart from all products page',async({page})=>{constproduct='Xbox Wireless Controller Lunar Shift Special Edition'awaitpage.getByRole('link',{name:'All Products'}).first().click();awaitpage.getByRole('img',{name:product}).click();awaitpage.getByRole('button',{name:'Add To Bag'}).click();awaitpage.getByLabel('cart').click();awaitexpect(page.getByText(product)).toBeVisible();});});
Enter fullscreen modeExit fullscreen mode

Helper Function

We can create a helper function calledaddAndViewCart which captures the common functionality of adding a product to the cart. This function finds an element on the page with the role ofbutton and the nameAdd To Bag and clicks it:

asyncfunctionaddAndViewCart(page:Page){awaitpage.getByRole('button',{name:'Add To Bag'}).click();awaitpage.getByLabel('cart').click();}
Enter fullscreen modeExit fullscreen mode

We can then use this helper function throughout our tests so we have less repetitive code. Also if we were to make a change to this button we would only have to modify it in one place in our code, in the helper function.

awaitaddAndViewCart(page);
Enter fullscreen modeExit fullscreen mode

In the example below our helper function is used in all 3 of our tests.

import{test,expect,Page}from'@playwright/test';asyncfunctionaddAndViewCart(page:Page){awaitpage.getByRole('button',{name:'Add To Bag'}).click();awaitpage.getByLabel('cart').click();}test.describe('add to cart scenarios',()=>{test.beforeEach(async({page})=>{awaitpage.goto('https://cloudtesting.contosotraders.com/')});test('add to cart from carousel',async({page})=>{awaitpage.getByRole('button',{name:'Buy Now'}).click();awaitaddAndViewCart(page);awaitexpect(page.getByText('Xbox Wireless Controller Lunar Shift Special Edition')).toBeVisible();});test('add to cart from search',async({page})=>{constproduct='Xbox Wireless Controller Mineral Camo Special Edition'constplaceholder=page.getByPlaceholder('Search by product name or search by image')awaitplaceholder.click();awaitplaceholder.fill('xbox');awaitplaceholder.press('Enter');awaitpage.getByRole('img',{name:product}).click();awaitaddAndViewCart(page);awaitexpect(page.getByText(product)).toBeVisible();});test('add to cart from all products page',async({page})=>{constproduct='Xbox Wireless Controller Lunar Shift Special Edition'awaitpage.getByRole('link',{name:'All Products'}).first().click();awaitpage.getByRole('img',{name:product}).click();awaitaddAndViewCart(page);awaitexpect(page.getByText(product)).toBeVisible();});});
Enter fullscreen modeExit fullscreen mode

Making our tests fail

What happens when we have some errors in our test? Let's fail our test in the line before where we use our helper function. We can simply comment this line out on two of our tests.

Our test will try to click theadd to cart button but won't be able to because the previous step is what takes us to the product page that contains this button. Without this step our test will fail.

import{test,expect,Page}from'@playwright/test';asyncfunctionaddAndViewCart(page:Page){awaitpage.getByRole('button',{name:'Add To Bag'}).click();awaitpage.getByLabel('cart').click();}test.describe('add to cart scenarios',()=>{test.beforeEach(async({page})=>{awaitpage.goto('https://cloudtesting.contosotraders.com/')});test('add to cart from carousel',async({page})=>{awaitpage.getByRole('button',{name:'Buy Now'}).click();awaitaddAndViewCart(page);awaitexpect(page.getByText('Xbox Wireless Controller Lunar Shift Special Edition')).toBeVisible();});test('add to cart from search',async({page})=>{constproduct='Xbox Wireless Controller Mineral Camo Special Edition'constplaceholder=page.getByPlaceholder('Search by product name or search by image')awaitplaceholder.click();awaitplaceholder.fill('xbox');awaitplaceholder.press('Enter');// await page.getByRole('img', { name: product }).click();awaitaddAndViewCart(page);awaitexpect(page.getByText(product)).toBeVisible();});test('add to cart from all products page',async({page})=>{constproduct='Xbox Wireless Controller Lunar Shift Special Edition'awaitpage.getByRole('link',{name:'All Products'}).first().click();// await page.getByRole('img', { name: product }).click();awaitaddAndViewCart(page);awaitpage.getByLabel('cart').click();awaitexpect(page.getByText(product)).toBeVisible();});});
Enter fullscreen modeExit fullscreen mode

Now lets run our test using the terminal.

npxplaywrighttest--project=chromium
Enter fullscreen modeExit fullscreen mode

Two of our tests have failed as expected. However, the error messages tells us that the click is failing inside the functionaddAndViewCart on the line that involves clicking the button with the name 'Add to Bag'. While this is true, it would be much more helpful to see what happened before we called the function / where in the actual test this function got called.

In this case, we can't click this button because we are not on a page that has this button displayed, which we could have spotted directly. So this helps us to save time while looking at the actual error message instead of getting pointed to a helper function where the click has failed.

This would then result e.g. in such an error:

error message

Helper Function using test steps and boxed

We need a better way to show the errors and that is where boxed steps come in.

Thetest.step is used to group several actions into one named step, useful for better test reports. Let's add atest.step to our helper function. Thetest.step method takes a name followed by an async function. Inside this function we add our click event and at the end of the function we add another parameter settingbox totrue. Make sure to await thetest.step so it will await the inner function as well.

asyncfunctionaddAndViewCart(page:Page){awaittest.step('add to cart',async()=>{awaitpage.getByRole('button',{name:'Add To Bag'}).click();awaitpage.getByLabel('cart').click();},{box:true});}
Enter fullscreen modeExit fullscreen mode

We don't need to make any changes to our test code as we have only updated the helper function. Let's go ahead and run our test again to see what the difference is and how box steps can help us.

npxplaywrighttest--project=chromium
Enter fullscreen modeExit fullscreen mode

You can see from the screenshot of the terminal results that even though the error is the same, as in the test timed out while waiting for theAdd to Bag button to appear the actual error code and line numbers are different.

Instead of showing us the helper function code it is in fact showing us the test code of where that helper function is being used meaning we can easily see what was happening before the helper function so we can much easier debug our tests.

error message

Check out ourrelease video to see a live demo of box test steps.

Conclusion

Boxed steps allows us to hide the implementation details of our helper functions and instead show the test code where the helper function is being used. This makes it much easier to debug our tests when they fail either through error messages in the terminal or in the reporters (e.g. HTML).

Useful Links

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Reliable end-to-end testing for modern web apps

Get started by installing Playwright using npm, yarn or pnpm. Alternatively you can also get started and run your tests using the VS Code Extension.

More fromPlaywright end to end Testing

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp