In today's lesson,
we'll be exploring one way in which tests can be classified.
There are many ways one can go about in classifying their tests,
but a very common classification used in the industry
revolves around three main types of tests based on their scopes.
These are the unit tests, feature tests, and finally, E2E tests.
Let's discuss these different types of tests
and their respective purposes in the test hierarchy.
Unit tests, as the name implies, focus on individual units of code.
For example, individual functions, methods, and, in the case of Vue projects,
even simpler support components are tested under unit tests.
When a unit test fails,
the developer will know precisely the problematic point in the code base.
Going a little higher, we get to the feature tests.
We are no longer talking about individual units of code by themselves,
but rather a specific feature that we want the application to fulfill.
Their execution will result in multiple elements of the application
interacting with each other.
These tests are still aware of some implementation details,
but not as much as unit tests.
For example, even at a feature test level,
our tests will make specific invocations tailored for Vue.js
through Vue Test Utils.
If a feature test fails,
the feedback will not necessarily point precisely
to the problematic piece of code,
but still very little investigation should be needed,
because the scope of the tests is still somewhat limited.
Finally, we have E2E tests.
At this level, we're testing the application as a whole,
in a full simulation of end-user interactions.
This is the type of test
that is at the highest level from all three we've covered today.
Just like your end-user will not know
that your website is running in Vue TypeScript,
your E2E tests also do not need to know that.
For that reason, from all the three tests that we have covered,
this is the one that knows the least
about the implementation of your application.
Since these are running at the highest level,
if an E2E test fails, the reason behind the failure
could be at many different places throughout the app.
For that reason, a longer investigation might be necessary
by the development team.
Each type of test is valuable and serves a purpose.
I think a great way for us
to understand where each of these types of tests falls in line
is by seeing them in practice.
I have put together a small weight converter calculator.
It's meant to convert between kilograms and pounds.
For example, I can turn 100 kilograms into pounds,
and I can also convert 100 pounds into kilograms.
As you may be able to see in this test suite over here,
I decided that one way for me to handle these weight conversions
would be to use a data object to represent the weight.
This data object is just a plain TypeScript class.
But what I want you to focus on, however,
are the unit tests that I wrote here.
For example, I wrote a test that would prove to me
that I can convert from pounds to kilograms,
and I also wrote another test
that I could provide a specific weight in kilograms,
and I hope to get the properly converted weight in pounds.
These tests here are just for this data object operating by itself.
I'm giving it some values
and requesting it to give me back as another unit of weight
and asserting that I'm getting the expected value back.
At a bit of a higher level now,
we can look into the feature tests that I wrote for the vue component.
Notice that at this point,
I'm mounting the vue component
and interacting with the different controls
that are being rendered to the page.
So for example, over here,
I am typing into the weight input the value of 100,
and I'm checking the pounds checkbox.
And then I'm hoping to get a specific value back,
in the input element for the weight.
This test does not know how I'm doing the conversion itself,
and this is good.
The test should know as little as possible about the implementation details.
I classify these as feature tests
because they are describing specific features
that the application needs to fulfill.
However, please note that part of the Vue.js community
would still be classifying these tests as unit tests.
And from that perspective,
it's because this is testing a vue component in isolation.
I tend not to get too worried about semantics.
All I hope here is that we can understand the idea
behind what I'm calling the feature tests.
Finally, I also want to show some E2E tests that I have written.
Notice that here,
I'm also testing specific user stories for my application.
But now, the test doesn't even know what front-end framework we're using.
As you can see here, to run these tests,
we are starting a local server and opening a browser.
And in here, we are visiting a real page in our application
and programmatically interacting with the page
like a real person would do.
For example, right here, I am visiting the page,
I am going to the input for the weight,
I'm clearing the input, typing 75,
and then I'm selecting the pounds button and clicking on it.
Finally, I'm verifying that I have the weight of 165.35 pounds
in my input.
Of the three types of tests we have covered today,
this is the slowest and most resource-intensive of them.
But it shines on the ground
that it's closest to what the user will truly be experiencing.
TDD can technically be used with any of these levels,
but my preferred pattern is to drive the behavior of the application first
through feature tests.
Any helper resources that prove to be needed over the development flow
can have their implementation driven through unit tests.
Finally, E2E tests are great
for protecting the most important user stories
once the feature tests are already in place.
My reasoning behind this
is that feature tests are in this sweet spot
where you can write tests
that guard user stories without enforcing specific implementation strategies.
They are also relatively fast to run and write,
and in case of failures, they still provide feedback
that can be specific enough for the development team
to understand what is the cause of the regression very quickly.
Great! Now you know the differences between unit, feature, and E2E tests.