You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Automated tests help you and your team build complex Vue applications quickly and confidently by preventing regressions and encouraging you to break apart your application into testable functions, modules, classes, and components. As with any application, your new Vue app can break in many ways, and it's important that you can catch these issues and fix them before releasing.
4
10
5
-
When it comes to building reliable applications, automated tests can play a critical role in an individual or team's ability to build new features, refactor code, and fix bugs with confidence.
11
+
In this guide, we'll cover basic terminology and provide our recommendations on which tools to choose for your Vue 3 application.
6
12
7
-
In a Vue application, there are different types of concerns that can be covered by automated tests:
13
+
There is one Vue-specific section covering composables. See [Testing Composables](#testing-composables) below for more details.
8
14
9
-
-**Logic**: verify non-UI rendering logic is implemented correctly. This typically involves application-wide business logic (e.g. state management stores) and utility functions.
15
+
## When to Test
10
16
11
-
-**Visual**: given certain input props / state, verify that an isolated component or component tree is rendering the correct visual output.
17
+
Start testing early! We recommend you begin writing tests as soon as you can. The longer you wait to add tests to your application, the more dependencies your application will have, and the harder it will be to start.
12
18
13
-
-**Interaction**: simulate user behavior, such as a click or input, and verify that an isolated component or component tree renders correct, updated output.
19
+
## Testing Types
14
20
15
-
-**User Flow**: given a sequence of user interactions that are necessary to complete an actual user task, check whether the application as a whole is working as expected.
21
+
When designing your Vue application's testing strategy, you should leverage the following testing types:
16
22
17
-
For different testing concerns, we need to use different testing techniques:
23
+
-**Unit**: Checks that inputs to a given function, class, or composable are producing the expected output or side effects.
24
+
-**Component**: Checks that your component mounts, renders, can be interacted with, and behaves as expected. These tests import more code than unit tests, are more complex, and require more time to execute.
25
+
-**End-to-end**: Checks features that span multiple pages and make real network requests against your production-built Vue application. These tests often involve standing up a database or other backend.
18
26
19
-
-**Unit Testing** covers **Logic** tests.
20
-
-**Component Testing** covers **Visual** and **Interaction** tests.
Each testing type plays a role in your application's testing strategy and each will protect you against different types of issues.
28
+
29
+
## Overview
22
30
23
31
We will briefly discuss what each of these are, how they can be implemented for Vue applications, and provide some general recommendations.
24
32
25
33
## Unit Testing
26
34
27
-
Unit tests are written to verify that small, isolated units of code are working as expected. They focus on logical correctness that can be easily validated. The most common example of a unit test is testing whether a function returns expected values based on different input arguments.
35
+
Unit tests are written to verify that small, isolated units of code are working as expected. A unit test usually covers a single function, class, composable, or module. Unit tests focus on logical correctness and only concern themselves with a small portion of the application's overall functionality. They may mock large parts of your application's environment (e.g. initial state, complex classes, 3rd party modules, and network requests).
36
+
37
+
In general, unit tests will catch issues with a function's business logic and logical correctness.
28
38
29
-
As mentioned previously, unit testing is typically applied to application-wide business logic or utility functions that do not involve actual UI rendering. These are typically plain JavaScript / TypeScript modules living outside of Vue components. Therefore, writing unit tests in Vue applications does not differ significantly from applications using other frameworks.
39
+
Take for example this `increment` function:
40
+
41
+
```js
42
+
// helpers.js
43
+
exportfunctionincrement (current, max=10) {
44
+
if (current < max) {
45
+
return current +1
46
+
}
47
+
return current
48
+
}
49
+
```
50
+
51
+
Because it's very self-contained, it'll be easy to invoke the increment function and assert that it returns what it's supposed to, so we'll write a Unit Test.
52
+
53
+
If any of these assertions fail, it's clear that the issue is contained within the `increment` function.
54
+
55
+
```js{4-16}
56
+
// helpers.spec.js
57
+
import { increment } from './helpers'
58
+
59
+
describe('increment', () => {
60
+
test('increments the current number by 1', () => {
61
+
expect(increment(0, 10)).toBe(1)
62
+
})
63
+
64
+
test('does not increment the current number over the max', () => {
65
+
expect(increment(10, 10)).toBe(10)
66
+
})
67
+
68
+
test('has a default max of 10', () => {
69
+
expect(increment(10)).toBe(10)
70
+
})
71
+
})
72
+
```
73
+
74
+
As mentioned previously, unit testing is typically applied to self-contained business logic, components, classes, modules, or functions that do not involve UI rendering, network requests, or other environmental concerns.
75
+
76
+
These are typically plain JavaScript / TypeScript modules unrelated to Vue. In general, writing unit tests for business logic in Vue applications does not differ significantly from applications using other frameworks.
77
+
78
+
There are two instances where you DO unit test Vue-specific features:
79
+
80
+
1. Composables
81
+
2. Components
82
+
83
+
### Composables
30
84
31
85
One category of functions specific to Vue applications are [Composables](/guide/reusability/composables.html), which may require special handling during tests.
32
86
See [Testing Composables](#testing-composables) below for more details.
33
87
88
+
### Unit Testing Components
89
+
90
+
A component can be tested in two ways:
91
+
92
+
1. Whitebox: Unit Testing
93
+
94
+
Tests that are "Whitebox tests" are aware of the implementation details and dependencies of a component. They are focused on **isolating** the component under test. These tests will usually involve mocking some, if not all of your component's children, as well as setting up plugin state and dependencies (e.g. Vuex).
95
+
96
+
2. Blackbox: Component Testing
97
+
98
+
Tests that are "Blackbox tests" are unaware of the implementation details of a component. These tests mock as little as possible to test the integration of your component and the entire system. They usually render all child components and are considered more of an "integration test". See the [Component Testing recommendations](#component-testing) below.
99
+
34
100
### Recommendation
35
101
36
102
-[Vitest](https://vitest.dev/)
@@ -49,30 +115,113 @@ Vitest is relatively new and is still undergoing rapid development. While it is
49
115
50
116
## Component Testing
51
117
52
-
In Vue applications, components are the main building blocks of the UI. Components are therefore the natural unit of isolation when it comes to visual and interaction tests. From a granularity perspective, component testing sits somewhere above unit testing and can be considered a form of integration testing. In some cases we will be testing a single component, but in other cases we could be testing a tree of components to make sure they are integrated correctly.
118
+
In Vue applications, components are the main building blocks of the UI. Components are therefore the natural unit of isolation when it comes to validating your application's behavior. From a granularity perspective, component testing sits somewhere above unit testing and can be considered a form of integration testing. Much of your Vue Application should be covered by a component test and we recommend that each Vue component has its own spec file.
119
+
120
+
Component tests should catch issues relating to your component's props, events, slots that it provides, styles, classes, lifecycle hooks, and more.
121
+
122
+
Component tests should not mock child components, but instead test the interactions between your component and its children by interacting with the components as a user would. For example, a component test should click on an element like a user would instead of programmatically interacting with the component.
123
+
124
+
Component tests should focus on the component's public interfaces rather than internal implementation details. For most components, the public interface is limited to: events emitted, props, and slots. When testing, remember to **test what a component does, not how it does it**.
53
125
54
-
Component tests should focus on the component's public interfaces rather than internal implementation details. Or, in other words, **test what a component does, not how it does it**.
126
+
**DO**
55
127
56
-
-**DO**
128
+
- For **Visual** logic: assert correct render output based on inputted props and slots.
129
+
- For **Behavioral** logic: assert correct render updates or emitted events in response to user input events.
57
130
58
-
- For **Visual** tests: assert correct render output based on input props and slots.
59
-
- For **Interaction** tests: assert correct render updates or emitted events in response to user input events.
131
+
In the below example, we demonstrate a Stepper component that has a DOM element labeled "increment" and can be clicked. We pass a prop called `max` that prevents the Stepper from being incremented past `2`, so if we click the button 3 times, the UI should still say `2`.
132
+
133
+
We know nothing about the implementation of Stepper, only that the "input" is the `max` prop and the "output" is the state of the DOM as the user will see it.
134
+
135
+
<TestingApiSwitcher>
136
+
137
+
<divclass="testing-library-api">
138
+
139
+
```js
140
+
render(Stepper, {
141
+
props: {
142
+
max:1
143
+
}
144
+
})
145
+
146
+
const { getByText } =render(Component)
147
+
148
+
getByText('0') // Implicit assertion that "0" is within the component
149
+
150
+
constbutton=getByText('increment')
151
+
152
+
// Dispatch a click event to our increment button.
Assert the private state of a component instance or test the private methods of a component. Testing implementation details makes the tests brittle, as they are more likely to break and require updates when the implementation changes.
64
207
65
208
The component's ultimate job is rendering the correct DOM output, so tests focusing on the DOM output provide the same level of correctness assurance (if not more) while being more robust and resilient to change.
66
209
67
-
If a method needs to be tested, extract it into a standalone utility function and write a dedicated unit test for it. If it cannot be extracted cleanly, it should be tested as a part of an interaction test that invokes it.
210
+
Rely exclusively on snapshot tests. Asserting HTML strings does not describe correctness. Write tests with intentionality.
211
+
212
+
If a method needs to be tested thoroughly, consider extracting it into a standalone utility function and write a dedicated unit test for it. If it cannot be extracted cleanly, it may be tested as a part of a component, integration, or end-to-end test that covers it.
68
213
69
214
### Recommendation
70
215
71
-
-[Vitest](https://vitest.dev/) or the other unit testing frameworks mentioned above can be used for component testing by simulating the DOM in Node.js. See [Adding Vitest to a Project](#adding-vitest-to-a-project) for more details.
216
+
-[Vitest](https://vitest.dev/) for components or composables that render headlessly. (e.g. the [`useFavicon`](https://vueuse.org/core/useFavicon/#usefavicon) function in VueUse. Components and DOM can be tested using [@testing-library/vue](https://testing-library.com/docs/vue-testing-library/intro).
217
+
218
+
-[Cypress Component Testing](https://on.cypress.io/component) for components whose expected behavior depends on properly rendering styles or triggering native DOM events. Can be used with Testing Library via [@testing-library/cypress](https://testing-library.com/docs/cypress-testing-library/intro).
72
219
73
-
### Libraries
220
+
The main differences between Vitest and browser-based runners are speed and execution context. In short, browser-based runners, like Cypress, can catch issues that node-based runners, like Vitest, cannot (e.g. style issues, real native DOM events, cookies, local storage, and network failures), but browser-based runners are *orders of magnitude slower than Vitest* because they doopen a browser, compile your stylesheets, and more. Cypress is a browser-based runner that supports component testing. Please read [Vitest's comparison page](https://vitest.dev/guide/comparisons.html#cypress) for the latest information comparing Vitest and Cypress.
74
221
75
-
Component testing often involves mounting the component being tested in isolation, triggering simulated user input events, and asserting the rendered DOM output. There are dedicated utility libraries that make these tasks simpler.
222
+
### Mounting Libraries
223
+
224
+
Component testing often involves mounting the component being tested in isolation, triggering simulated user input events, and asserting on the rendered DOM output. There are dedicated utility libraries that make these tasks simpler.
76
225
77
226
-[`@testing-library/vue`](https://github.com/testing-library/vue-testing-library) is a Vue testing library focused on testing components without relying on implementation details. Built with accessibility in mind, its approach also makes refactoring a breeze. Its guiding principle is that the more tests resemble the way software is used, the more confidence they can provide.
78
227
@@ -82,15 +231,23 @@ We recommend using `@testing-library/vue` for testing components in applications
82
231
83
232
### Other Options
84
233
85
-
-[Cypress](https://www.cypress.io/) is an E2E test solution, but it also supports [Component Testing](https://docs.cypress.io/guides/component-testing/introduction) which can test components in real browsers with a GUI that shows the actual DOM state during tests.
86
-
87
-
-[Nightwatch](https://v2.nightwatchjs.org/) is another E2E test runner with Vue Component Testing support. ([Example Project](https://github.com/nightwatchjs-community/todo-vue) in Nightwatch v2)
234
+
-[Nightwatch](https://v2.nightwatchjs.org/) is an E2E test runner with Vue Component Testing support. ([Example Project](https://github.com/nightwatchjs-community/todo-vue) in Nightwatch v2)
88
235
89
236
## E2E Testing
90
237
91
238
While unit tests provide developers with some degree of confidence, unit and component tests are limited in their abilities to provide holistic coverage of an application when deployed to production. As a result, end-to-end (E2E) tests provide coverage on what is arguably the most important aspect of an application: what happens when users actually use your applications.
92
239
93
-
In other words, E2E tests validate all of the layers in your application. This not only includes your frontend code, but all associated backend services and infrastructure that are more representative of the environment that your users will be in. By testing how user actions impact your application, E2E tests are often the key to higher confidence in whether an application is functioning properly or not.
240
+
End-to-end tests focus on multi-page application behavior that makes network requests against your production-built Vue application. They often involve standing up a database or other backend and may even be run against a live staging environment.
241
+
242
+
End-to-end tests will often catch issues with your router, state management library, top-level components (e.g. an App or Layout), public assets, or any request handling. As stated above, they catch critical issues that may be impossible to catch with unit tests or component tests.
243
+
244
+
End-to-end tests do not import any of your Vue application's code, but instead rely completely on testing your application by navigating through entire pages in a real browser.
245
+
246
+
End-to-end tests validate many of the layers in your application. They can either target your locally built application, or even a live Staging environment. Testing against your Staging environment not only includes your frontend code and static server, but all associated backend services and infrastructure.
247
+
248
+
> The more your tests resemble the way your software is used, the more confidence they can give you. - [Kent C. Dodds](https://twitter.com/kentcdodds/status/977018512689455106) - Author of the Testing Library
249
+
250
+
By testing how user actions impact your application, E2E tests are often the key to higher confidence in whether an application is functioning properly or not.
0 commit comments