It's always useful to know why a test fails. Ideally, we immediately see why (and which line(s)) causes the test to fail. But this isn't always easy to know when you have a test that contains multiple steps. This is where a good test runner helps you to win some time.
Dividing an end-to-end test into multiple steps is a popular practice because it makes the test cases faster to execute and because you probably built on top of the created/changed data.
For me, this is important because I like to write whole flows in an end-to-end test, this way I'm confident that everything works, but it's even helpful for simpler test cases. Luckily, Playwright can give us a hand and can quickly point us toward the problem.
As an example, let's take a closer look at a Playwright example, which is generated as an example with the init command (
npm init playwright).
The test case below isn't large, but it's already containing symptoms of a test that is not well-structured and hard to maintain. As you can notice, the test case is divided into multiple steps. Each step contains a comment to make the intent of the code block (a step) clear to the reader.
In these cases, a step can be compared to a smaller test case within the bigger test.
Let's also take a look at the Playwright report for the test case.
We can see that all the user actions and asserts are added to the report. It's even possible to expand them and to see the corresponding code. This is fine when everything works, but let's see what the Playwright report looks like when the same test fails.
Looking at the Playwright report it's still clear why the test fails, which is "waiting for selector '.new-todo-fail'".
In other words, it can't find the
There's even the line number with the code block that causes the test to fail. While it's something, I don't find this ideal because we don't see the full context. We have to open the test file manually to get the full picture of the test, for example, to know the steps before.
In this specific example, we don't know which to-do item caused the test to fail. This might be a trigger for you to know what to do next in order to fix the failing test.
As a countermeasure for this problem, I usually see a lot of projects that add
console.log statements to get more information.
So, let's include them in the test and see what happens. In the following example, log statements are added to know which todo is created, and which todo is checked.
The test still fails when it's re-executed, but the added logs are now included in the Playwright report.
While this is better, I still don't find this to be ideal because the information is scattered. We receive all the pieces, but we have to put the pieces together to get the full picture.
So far, we've seen that code comments and log statements offer a way to better understand the test, but they aren't ideal.
The best solution in my opinion is to use the
We can replace the comments and log statements, with the
test.step function, which accepts two arguments.
The first argument is a description, and the second argument is a function that contains the code that we want to test.
This signature should be familiar, as it's almost identical to the
The refactored test with steps looks like this.
But the refactored test has a small problem because we don't have access to the
secondTodo variables anymore.
To fix this, return the variables within the
test.step function, and assign them to a variable.
Now, when the test is executed, it results in the following Playwright report.
The Playwright report now includes the steps in detail, and we can easily find what caused the test to fail.
When we eventually fix the test, the Playwright report contains a nice summary of each step.
To summarize, we can replace comments and log statements with the
By adding descriptive step descriptions it becomes easier to understand what is happening while reading the test case.
The steps also give a well-organized summary of the flow because these are included in the Playwright test report, which makes it easier to find the cause of the failure. As a benefit, these reports can also be useful used while talking about the flow of the test.
I appreciate it if you would support me if have you enjoyed this post and found it useful, thank you in advance.