Throughout this 20ish minutes talk, I've presented four different kind of tests with each time how to run them in a Vue.js application.
1. Functions unit tests (with mocha-webpack)
2. Components unit tests (with vue-test-utils and Mocha or Jest)
3. Snapshot tests (with Jest)
4 UI tests (with Cypress.io)
3. THE PYRAMID OF TESTS
Unit tests are fast and cheap
UI / E2E tests are slow and expensive
Martin Fowler https://martinfowler.com/bliki/TestPyramid.html
3
4. THE TESTS PYRAMID… REVISITED!
Includes functions unit tests
Includes snapshot tests
Inspired by Edd Yerburgh https://medium.freecodecamp.org/the-front-end-test-pyramid-rethink-your-testing-3b343c2bca51
4
7. KEY POINTS
Test JavaScript functions (ideally pure)
No need to mount my component
Framework-agnostic
7
“user-score.service.js”
8. MOCHA-WEBPACK
1. Ask webpack to create a bundle
> Our test files
> Functions we want to test
2. Call mocha on this bundle
8
Extract these JS functions into separate “service” files
Lighter components
TDD-friendly
12. WEB COMPONENTS (2/2)
12
App
Left menu Top toolbar
Sign-in buttonMenu item
Main content
Home page
Map Tutorial dialog Unlock dialog …
Question box … …
Depends on the active route
13. SHALLOW RENDERING
Render a component without its
children (by stubbing them)
13
Avoid asserting the behavior of child components
Faster to render
Included in vue-test-utils
Top toolbar
Sign-in button
14. FOCUS ON VUE-TEST-UTILS
Provides utility functions, makes things easier to test
> Mounting
> Traversing the DOM
> Triggering and catching events
> Etc…
Returns a wrapper around the mounted Component instance
> const wrapper = mount(MyComponent)
> const wrapper = shallow(MyComponent)
For example, we can access emitted events through this wrapper
> And make assertions on them
14
15. Mocha (The classic one)
Bring your own
> Assertions (chai, should…)
> Mocks (sinon, testdouble…)
> Coverage (Istanbul)
Real browsers with Karma
Jest (The new one)
All inclusive
> Uses popular solutions like
Jasmine and Istanbul under the
hood
New default test stack in vue-
cli webpack template
TWO MAIN CHOICES
18. USE SNAPSHOTS WITH JEST
Sometimes your UI changes too often
> You have to update your tests all the time…
“Just notice me when there is a change!”
> And I’ll tell you if this is expected or not
18
It will save your rendered component
> Creates and stores *.snap files in __snapshots__ folder
Works out-of-the-box with Jest
> expect(vm.$el.outerHTML).toMatchSnapshot()
19. WHEN IT FAILS
19
Fails if your rendered component doesn’t match the previous snapshot
Two options:
> Fix your code
> Tell Jest to update its snapshot
22. Open-source
No Selenium dependency!
Uses your favourite tools under the hood
> Mocha
> Chai
> Sinon
Automatic waiting
> More consistent results
> No need of random ‘sleeping times’ everywhere
Readable errors
22
CYPRESS - INTRODUCTION
23. CYPRESS.IO - API
Ability to stub server
requests with fixtures
Works well with promises
Includes jQuery
Change viewport
23
24. INSTALL IT AND OPEN IT
Install cypress as a dev dependency
> npm install cypress –save-dev (200 Mb...)
Cypress GUI
24
28. YOUR TAKE-AWAYS
Feasible to quickly unit test JavaScript functions
28
Jest is becoming more and more popular
Snapshot tests are a great new type of tests
Cypress.io is a viable and sexy alternative to Selenium
Alright, let’s kick off this session1
So for the next 20-ish minutes, I’ll be talking about Vue (of course) and more specifically about tests.
Before starting, my name is Cedric.
I work at OCTO as an IT conultant, and the subject that I like the most is… frontend development.
Alright, everybody has already seen that, at least once?
Martin Fowler, 5 years ago.
Cheap in the sense of “They are easy to write” and “Easy to maintain”.
Unit tests are good for TDD.
No more service tests? Depends on what you mean by service, but I guess it could be covered by the first slices we have here.
A full component, with its child components could be seen as a service, or at a least a part of your system…
Not really mainstream, I know.
I started to be interested in that when I was working with a big codebase in Angular 2, and running the tests was crazy slow.
Because there was a lot of dependencies to load.
Not motivated to run them.
Not motivated to create new ones.
So I kinda wanted to find a solution…
First of all, be careful, those tests are slow, and easy to break.
But still, sometimes it can be very useful to test an entire workflow. To simulate a user interaction with our webapp.
For quite a while there has been one major player in here — Selenium.
Most of the other solutions out there are basically building their APIs on top of selenium, so they all suffer from the same problems that selenium has.
Sometimes I need a way of testing a simple JavaScript function.
I don’t need to mount a component or anything…
Let’s take an example…
Here I have a player, each time he answers correctly to one question, there is a new line in the DB, and I want to calculate his total score.
And I obviously want to test that.
And usually what I use for that is mocha-webpack.
It will force you to extract some of your logic out of your component.
It will force you to write these functions in a more testable way.
I’m sure you have in your projects some pure JavaScript functions, that don’t depend on your frontend framework, and that you could easily test like that.
So I encourage you to have a look.
Alright, next kind of tests in our new pyramid…
So, everyone knows what a “component” is…
We can also represent that as a tree of components.
As you can see, most of our components have child components.
And it’s interesting to keep that in mind when it comes to testing.
Most of the time, we want to test our components in isolation. At least when we talk about unit tests.
Take the example of the ”Top toolbar”, if I want to test the value of my title for example, I don’t really want to render the “Sign-in button” child component. Actually, I want to stub it.
That brings me to explain what “shallow rendering is”.
Faster to render, important if you re-render your entire component before each of your tests.
We need this “shallow rendering”, and it’s included in vue-test-utils, let’s talk about it.
Vue-test-utils: https://vue-test-utils.vuejs.org/en/guides/common-tips.html
So vue-test-utils is the reference test library for Vue.js.
Vue-test-utils still in beta.
Replacement for “avoriaz” (Same guy)
So, we start from Vue.js, and then we have a test utility library, which will make our life easier as a developer, and now we want…
Pull-request which got merged 3 weeks ago.
On Jest, no real solution for running your tests in a real browser…
Facebook says: “It’s too slow, too flaky, we ran away from it.”
Recently, some people tried to use Puppeteer (a Node.js library for controlling headless Chrome)
https://www.valentinog.com/blog/ui-testing-jest-puppetteer/
PR: “Replace Karma + Mocha with Jest” (opened July 26th merged November 12th)
https://github.com/vuejs-templates/webpack/pull/824
There is more choices with “avoriaz”. (Tape, Ava…)
Difference between jsdom and PhantomJS: https://github.com/tmpvar/jsdom/wiki/jsdom-vs.-PhantomJS
Introduced by Jest and React.
<h2> instead of <h3>
All good?
Quite high in the pyramid of tests but actually it’s not expensive. It’s easy to write, fast to run.
It’s just high in the pyramid because it covers more than your unit tests, it covers your entire template.
And last slice of the pyramid!
You remember the pyramid from the beginning?
First of all, be careful, those tests are slow, and easy to break.
But still, sometimes it can be very useful to test an entire workflow. To simulate a user interaction with our webapp.
For quite a while there has been one major player in here — Selenium.
Most of the other solutions out there are basically building their APIs on top of selenium, so they all suffer from the same problems that selenium has.
Open-source, except for the team dashboard.
I’ve also seen yesterday that it is part of the last edition of the Thoughtworks tech radar.
https://assets.thoughtworks.com/assets/technology-radar-vol-17-en.pdf
Selenium WebDriver runs remotely outside the browser, Cypress runs inside the browser.
https://hackernoon.com/cypress-io-docker-the-ultimate-e2e-stack-a20ee25654b1
https://blog.red-badger.com/blog/2017/6/16/cypress-a-genuine-alternative-to-selenium-at-last
https://www.joecolantonio.com/2017/11/16/cypress-io-vs-selenium-test-automation/
Selenium versus Cypress.io
https://gist.github.com/jennifer-shehane/eaa017496b9b5cfc98e8f4ef31a437fc
https://github.com/cypress-io/cypress
Written in CoffeeScript
Supported browsers: https://docs.cypress.io/guides/core-concepts/launching-browsers.html#Browsers
Promises.
Here I first get a DOM element, I make an assertion “It should be visible”, and then once it is and only once it is, I continue…
jQuery.
In case you need some fancy selectors or you want to access the content of a DOM element to make more advances assertions.
Show the video! (if time)
Start testing with Jest and vue-test-utils
https://blog.codeship.com/get-started-with-vue-test-utils-and-jest
A future book on how to efficiently test Vue.js applications
by vue-test-utils author
https://www.manning.com/books/testing-vuejs-applications
“Why Cypress?” by Cypress team
https://docs.cypress.io/guides/overview/why-cypress.html
A Cypress.io set of slides
http://slides.com/bahmutov/effective-e2e-testing-with-cypress