Web App Testing & Tools

Testing with Vitest

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 "Testing with Vitest" 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 introduces Vitest and begins writing a unit test for the GitHub API to verify repository information is returned. The tests are executed in the command line. Vitest also has a user interface that provides a list of tests and reports. Snapshots are also demonstrated in this lesson. The final code is on the lesson-1 branch


Transcript from the "Testing with Vitest" Lesson

>> So now that I have this, I would like to write some tests. So let's create a new file called github-api.unit.ts. Now remember how we talked about that this is going to be documentation? So the way I approach these particular things is I talk about, there's a describe method.

And you can describe the thing you want. So, we're gonna talk about github-api. And the question becomes, where does the describe method come from? And so now you need to have some kind of a test runner, some kind of way of running these tests. And there are many ones out there over the years.

We had all kinds of different test runners. Which one I like today, I like Vitest. So I'm gonna go down this particular path. And so if we go here, there should be a description of how to install Vitest. So let's install Vitest into our project. Should be as simple as that.

Now Vitest is nice because this particular project is already configured with Vite. And turns out Vitest uses the Vite infrastructure underneath it. And so it makes the life much much simpler. So now I can go in and I can do an import here. Import, describe from Vitest. And so now I would like to test something.

So, the thing we wanna do is, we wanna test the Git repository. And there might be more than one test that you wanna do. So again, I'm gonna nest a describe, right? So I am basically building up a documentation. In the future, why is this red? In the future, we're gonna have describes for other parts of the system.

So the way you think about it is, you use describe to tell the reader, right? You always have to think about, somebody in the future will come and read this code. And all by the way, chances are very good that it's gonna be future self of yourself. And that future of yourself is going to forget everything you know right now.

So I know you're thinking to yourself, all of this stuff is obvious. But your future self is gonna not remember any of this stuff. And is going to curse you for not putting all the stuff in. And is going to say which idiot did this? And then they will blame it and realize that the idiot was yourself.

Okay, this happens to me all the time, where it's code I have written and I don't recognize. And I get frustrated at the code only to blame it and realize that I have myself to blame. So describe kind of sets the context for the user, for the person reading it.

And so once you have a describe, you might wanna say what it should do. And so there is a it. And you can start with to do and say, it should return repository information. That seems like a good test, right? We can write other tests, for example, we can say, it to do, should return, should timeout after.

After x seconds with timeout. Response. If you think about it, these describes an its, a really requirements for your project, right? Every time you write an it, you're writing a requirement of what should happen, how you expect things to happen, and so on, right? And so as you build up this this vocabulary of the requirements, it makes it easier for the person that's gonna come in and be able to answer the why question.

Why are you doing all these things? Well, because if I go to the test, there is a it, which is really a requirement that says, hey this should happen. So presumably somebody decided that that's a feature that we need to have. And therefore we can go and write it.

Now so far, they're just it's and I think it's a red because I forgot to import it. Okay, so now what we wanna do is, we wanna run this. And I think if I just do let's see, so in here, I already, okay, perfect. I already have a test here.

So if I just do npm run test. It created a row, okay, so I created a test for my, because I called it unit instead of a spec. I'm sorry, lemme fix that. So this was supposed to be called spec. What you see if you run a test?

It shows you the tests in here? And what I really like about this particular thing is that if I go and hit Save. You notice the test automatically rerun. And you can also, I think if you click R in here, you can rerun the tests in here as well.

And if I save this particular test, the system is smart enough to only go and rerun the file that I've modified. And so this is what I mean by being lazy, right? I have taken away all of the problems of running the code and put them inside of this test runner, right?

And so what you will see is that as we're gonna work on this particular thing, we're just gonna change code and save because that's a natural thing for us to do. And as we save, we will immediately get updates of where we are. And I think that's kind of super cool and super important.

Also, the Vitest also comes with this cool thing, dash, dash UI. And if you run this, I think it, if I go local host. Where's the UI? There we go, now it's running. Okay, I guess npm doesn't pass the arguments through. I did not know that. So you can have a nice dashboard in the UI and this dashboard basically shows the same exact things.

It shows you what your describes are, what it should do in here. So for example, this is just one test, you can see that everything is passing in here. So that's sometimes useful as well to just different way of looking at it. Okay, so now we wanna write a test.

So let's go to our spec and let's go and implement this first test in here. So let's turn this into async. So what we're gonna do inside of test, let's see. So we say const api = new GithubApi, and let's just leave it as undefined. And then I'm gonna say getRepository, and I'm going to ask for 'mhevery', 'qwik', and I'm gonna say const response equals await.

And then what are we gonna do with the response? Well, we can do an expect, and by the way the proper way to do it is right here. So you can say expect that the response toSnapshot I think, MatchSnapshot. Okay, so we have a first test in this and what you might think.

So there's a piece of code, and you wanna execute it, right? So we executed it, and now the response that came from the server is shown over here. And you can see it's a huge amount of text, a wall of text. One and two is, this is not actually a unit test, right?

Because we are actually talking to a real server on the other side, which means if GitHub goes down, our tests will be failing. If GitHub changes the what it responds with the output, our test fails. As a matter of fact, I think if I just rerun this, okay it still passes.

But if I would go into my repo and I would change something in there, I would now make this test fail. Because the output would change, right? If I would go and modify something, I'm sure there are timestamps in here and other things. Is there timestamps? Probably. Yeah updated at, for example, you see that.

So this test, while it's super easy to write is not the best kinds of tests. And I think this is where a lot of people get in trouble, because they execute a piece of code. They're like look I'm doing testing, and then they assert that the output is correct.

And of course the output will not be correct tomorrow because somebody changes something because you're depending on live data. Or the service goes down or the test becomes flaky or if you just look at the amount of time it takes. If you just look at the amount of time it takes, it took 344 milliseconds to execute this test.

That is a lot. If you have thousands of tests and each one takes a third of a second, that is a lot. So while this is kind of an obvious way to do this, this is not the best way to do this.

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