Loading
Current section: Assertions 7 exercises
solution

Soft Assertions Solution

Use expect.soft() in Vitest to run multiple assertions without stopping at the first failure, giving fuller insight into test failures.

Loading solution

Transcript

00:00 So we've got this test case that makes sure that our system returns a list of posts. For that to happen, we're calling the fetchPosts function and awaiting its promise to get the response back. And then once we get it, we have a few expectations towards that response. So first of all, we want to make sure that the response.status is 200, it was a successful response.

00:19 Then that response has a cache control header of a specific value, just to make sure that the clients consuming that response will cache it. And then of course that the body of response, in this case the JSON body, actually equals to the list of the posts that we expect. If we run this test, we will see that it's failing.

00:36 And that's great because it lets us know that something is wrong with our system, probably with our fetchPosts function. Let's see what it tells us. Well, for once, this assertion over the response.status is failing because we're expecting a 200 response but we're getting a 404. That is a useful piece of information, but this status code alone is not enough for us

00:55 to understand what is the root cause of this problem. In fact, even getting this assertion, we have no context what happens to any other expect statements. Is the cache header correct? Is the response body what we expect? We simply don't know. That happens because every assertion we have defined in this test is a hard assertion,

01:14 just a regular expect statement. So as soon as any of them rejects, the test execution stops and we don't know the full context around this particular test case. In this situation, we have multiple expectations towards the response, but none of them are mutually exclusive.

01:30 For example, the server may return the wrong status code but still include the correct header and body. Or maybe just the header will be wrong and the other two assertions will pass. That is a very important distinction when writing expectations towards your system. If you have a non-exclusive expectations, it is much better to use soft assertions.

01:49 And using soft assertions in VTEST is really simple. Just go to any assertion you want and change expect to expect.soft. So calling the soft method on the expect object will introduce a soft assertion. Let me change all of these assertions to be soft assertions, because as we figure out,

02:07 none of them are mutually exclusive, so we can run all of them at the same time. Let's see how that changes our test. If we scroll up, we see multiple things here. Let me go to the top. So we see the first assertion failing for the status code over here. It failed even before, so that's the same.

02:23 But what changes is that if I scroll more, I will see the second assertion also failing. So now I have more context about this issue. I know that even the cache control header is not present. And if I scroll even more, I will see the assertion over the response body.

02:38 So I was expecting the list of posts, but I got another JSON response with a message and it says that it failed to find posts with IDs undefined. So now I ran all of these three assertions and they all printed their result. And then of course the test still failed, because if any assertion fails, whether it's

02:57 a hard assertion or a soft assertion, the test will still be marked as failed. Now having more context on the issue, I can actually figure out what's wrong. If I go to the fetch post function and see how it works, I can see that it has this post IDs argument that is an optional area of strings, and then it filters all the posts to be those

03:16 included in the post IDs. And since I'm not providing any IDs here in the test, I end up with empty matching posts. So this function treats this test case as if no posts were found at all. I can do a simple fix, just checking for the post IDs to exist and for them to have some values.

03:32 And of course, if they don't exist, I will just return all posts. Once I do this change and check on the tests, now they're passing because all of those three assertions are fulfilled. So what we had in this test is multiple assertions towards the same value, in this case, a response, and none of those assertions were mutually exclusive.

03:51 Because of that, we refactor them from the simple expect call to expect.soft, making them soft assertions. That means that VTEST will run all the soft assertions and all of them will print their results and only then VTEST will mark the test as failing or passing. Because of this, we are getting more context on the test failure.

04:10 And that is crucial, because the biggest value of tests is when they fail to let us know that something goes wrong. And it matters a lot how they fail and how much information they provide you while doing so. And you can use default or hard assertions to say that if this expectation fails, there is no point in continuing the test.

04:29 And you can use soft assertions to allow multiple expectations to run at the same time and then see all of them in the test report. Basically, a choice between hard and soft assertions becomes a lever, an instrument that helps you control how your tests run, when they fail, and how much information you get back when they do.

04:47 It is one more option you have to design great failure experiences and make debugging tests a little easier.