Web App Testing & Tools

Anatomy of a Test

Miško Hevery

Miško Hevery

Qwik Creator (Previously Angular)
Web App Testing & Tools

Check out a free preview of the full Web App Testing & Tools course

The "Anatomy of a Test" Lesson is part of the full, Web App Testing & Tools course featured in this preview video. Here's what you'd learn in this lesson:

Miško breaks down the anatomy of a test. Tests should contain a setup that initializes anything needed for the test, a stimulus that is the target of the test, and the expectations containing what is tested. A few questions about the differences between unit and end-to-end tests are also answered in this lesson.


Transcript from the "Anatomy of a Test" Lesson

>> Well, what if the GitHub API changes? So, I'm curious what your thoughts on something like that would be.
>> Right, so this is where end-to-end tests come into play, right? So with unit tests, you wanna verify that what you're doing is correct. With end-to-end tests, you're saying, I wanna make sure that all of the pieces in the system, which may include GitHub, come into play.

And you can have two different kinds of end-to-end tests, right? You can have an end-to-end test where GitHub is actually involved, where you're actually verifying that it works all the way through GitHub. Or you can have an end-to-end test where GitHub is mocked out, where you're assuming that you are correctly mocking out how GitHub works on your side, and do it.

And both of them have value, right? One is verifying that the API hasn't changed with GitHub. Now, GitHub has their APIs versioned and there's other discussions to be had around like why that's a good idea. And on your side you have a choice to do one way or the other, and both of these tests are useful and they test different things.

>> How are the testing objects shared with the spec files existing in the routes directory?
>> So, I like to put the spec files right next to the test that you have. There is a small risk that you accidentally include your test code in production. My argument towards that would be like, make sure your bundling system has a glob that says, do not include anything that has spec.ts.

That should be pretty safe. I like it because it's right next to each other, and so it's easy to correlate the files together. In the past, I have been in projects where we put the test in a separate folder. Because they're just far away, it becomes kinda complicated to manage it.

So I personally like when they're right next to each other.
>> Would you create another test with the actual correct repo and correct username to make sure it builds correctly? This is a generic test, but would you ever create something that's very specific to your project?
>> So, it depends where you are in the stack, right?

For an end-to-end test, because we're mocking everything out, it doesn't really matter what you choose. But if you wanted to actually go against the real repo, it's more of an end-to-end test. And you might wanna choose to have a couple of smoke tests like that in that category.

You probably don't wanna put them with your unit test, because they might run slower, they might be flaky, etc. You probably wanna run them in a separate command, with a separate build, etc, that maybe they only run as part of your CI build or something of that sort.

But both of those things are useful, right? Each one of these test a different thing. Now, I really wanna stress out this angle of documentation, right? So look at this test, and let's just think about, what can we do to make the test easier to read, right? Typically, you just wanna pull things out so that you end up with something that reads easily for the user, because you wanna be able for the next person to come in here and easily understand what's going on, right?

So typically we have some form of a setup, and the setup is something that we can pull to a common location that might be useful. And I think as we are going to go through multiple different tests, we're gonna see that the same setup occurs over and over again.

We will go and refactor it to a common location. Then there is usually the stimulus, the actual piece of work that you do, right? The thing that you're testing, right, the thing on the test, sorry, that goes all over here. Sorry, let me back up a second. The setup is all the way up to here, right?

Because setting up an API with a mock is part of the setup. So this is a setup portion, then there is a stimulus portion, right? The actual work, the thing that I'm testing, right? And finally, I have a whole bunch of expects. And these expects come in either in the form of just a plain expect, like expect fetch mark to have been called with whatever, or they come in a form of replaying the other side, right?

So i'm kind of straddling both sides of the test. Like, I can expect things from the front, but in the back, I can go and pretend that stuff happened using the mocks. And that's how I sandwich my test and do whatever I need into it, and finally I expect the response.

The other thing I wanna point out is that, as much as you can, you really wanna get away with these simple responses, or the simplified objects. Because it tells the reader that it doesn't matter. Like, you're simplifying the mental model for them, because you're saying, look, there's some response that's gonna come in and it's gonna show up over here.

The actual details don't matter, right? If I was actually going to make a real humongous object, like, I could grab the object from the snapshot, right? I could say, this thing here is my response. But it would make the test a lot more complicated for the user to kind of follow along because then they don't know, is it something that matters to the test or not?

So you really wanna simplify this and you really wanna break your test into these three phase, the setup phase, the stimulus phase, and the expectations phase. And every test should follow this particular pattern overall.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now