The goal of a unit test is to improve code quality and assure future development or refactoring does not result in broken builds and functionality. Tests that require consistent updating when refactoring code are likely tightly coupled to the internals of the component.
Writing unit tests is a constant struggle between writing enough tests and not writing too many. I call this the unit testing Goldilocks rule—not too many, not too few, but just enough. Thousands of tests for a small application can be as damaging to development time as no tests.
-- Ed Yerburgh, Testing Vue Applications (New York: Manning Publications, 2019)
The OpenBMC Web UI unit test framework uses the Jest test runner and relies on the following libraries:
AppHeader.spec.js
PageSection.vue
in the /tests/global
directory with the name PageSection.spec.js
/tests/mixins
directory with the name BVToastMixin.spec.js
Running TestsThe test:unit
script will run all the test suites. Until the integration of the test script with the continuous integration tool is complete, it needs to be run manually before pushing up code for review. If you are working on fixing a test that is failing, follow the guidelines for debugging a failed tests or fixing failed snapshot tests.
The test:unit:debugger
script will help to debug failing tests using the Chrome Developer Tools. To debug a test:
debugger
statement in the specifications filechrome://inspect
The test:update
script will update snapshot tests. If the UI has changed and the snapshot tests are failing, after manually verifying the UI changes, run the update script to update the snapshots. Running test:update
can be dangerous, as it will update all snapshot tests.
It is critical to verify all snapshot tests before running the update script. The easiest way is to run the unit test in watch mode, npm run test:unit -- --watch
and verify each snapshot.
shallowMount
rather than mount unless child component rendering is requiredlocalVue
for all plugin installs, for example, when testing a plugin like VuexA snapshot test is a comparison of the code from two different points in time. When the view is rendering as expected, a snapshot is taken and when the test suite is run, this snapshot is compared to the current code to make sure nothing has changed.
This type of testing is good for testing that static content output has not changed due to any code updates or refactoring. Too many snapshots can slow down development during refactors. Typically, these are written once the UI presentational layer is complete and validated.
There are two testing strategies for testing a Vuex store, which include testing store parts separately or testing a running store instance. Each strategy has its pros and cons. Given the size of the store and the number of developers that could potentially contribute to the project, the suggested strategy is to test store parts separately
.
Testing the parts separately is easy since each of the parts is a JavaScript function. Store parts to test include actions
, getters
, and mutations
.
Since HTTP calls should never be used in a test, actions require extreme mocking. Mocking tests rely on assumptions and can lead to faulty tests.
Getters are JavaScript functions that return an output. These are basic functions that may not require testing unless there is getter logic. Any logic in a getter should be tested.
Mutations are JavaScript functions that mutate the store state. These are basic functions that may not require testing unless there is mutation logic. Any logic in a mutation should be tested.
localVue
when creating the store to avoid leaky testsRouteLink
items, we should unit test that functionality, which requires stubbing