Welcome to Part 12 of this comprehensive review and summary of Cory House’s Pluralsight course Building Applications with React and Redux in ES6.
Cory is a Microsoft MVP in C#, founder of OutlierDeveloper.com, avid tech reader, and speaker.
He believes in clean code, pragmatic development, and responsive native UIs.
Also in this series:
Part 12 – Testing React
Because every React component produces html based on props and state, this makes testing React code significantly easier than it would otherwise be.
Cory begins with an introduction to Mocha. According to the Twitter poll that Cory ran, Mocha is currently the most popular testing framework available.
I recommend doing your own research before deciding on your preferred Testing framework. Mocha is a good one, but don’t just follow the herd: understand the pros and cons of each one.
Cory mentions Jasmine and Jest here but prefers the extra configurability that Mocha provides.
Cory also likes the new framework AVA a lot, and shows a table comparing the features that Mocha and AVA offer you. A couple of standouts for me is AVA offers built-in ES6 support, and runs only impacted tests on save.
Because it is new, I had never even heard of AVA when Cory ran this poll and suspect most other voters hadn’t either.
In this module we’ll be using Mocha with Michael Jackson’s Expect library for doing our assertions. The most popular assertion library is currently Chai JS, but Expect works well, and if you pardon the pun, I expect that it will become increasingly popular.
Cory shows us another table listing the features on Chai up against those of Expect. It is much quicker to code with Expect than trying.to.write.assertions.in.Chai.
Additionally, Expect has spy built in, and this may or may not be want you want depending on whether you like using libraries such as Sinon.
With React Test Utils, there are two rendering options: shallowRender and renderIntoDocument, and Cory explains when each option is applicable and we learn when and where JS DOM can be helpful for us.
We learn that React Test Utils has the downside of a verbose API, with almost tongue twistingly long commands such as findRenderedDOMComponentWithTag and scryRenderedDOMComponentsWithTag.
Cory likens these to Enterprise Java. My personal all time favorite Java class is the classic InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState although I do also rather like
He also discusses the Simulate Test Utility here, and recommends that we use Airbnb Enzyme instead. Cory scans through some of their documentation and we can see that it bares a number of similarities to jQuery (in a good way).
Next Cory takes a step back and likens Enzyme with a theatre production.
When we go behind the scenes, we reveal that Enzyme has been using React Test Utils all along. But thanks to Enzyme, testing React is a lot prettier now.
Enzyme also uses JS DOM so that we can unit tests without the need for a browser to run them in. And thirdly, it uses Cheerio, which is a fast, flexible, and lean implementation of core jQuery designed specifically for the server.
Cory shows us a table comparing all of these technologies against each other: React Test Utils, JS DOM, Cheerio and Enzyme. He explains that Enzyme makes the best of each of these libraries strengths and minimizes their weaknesses.
I think that this is a fine example of how open source software can be carefully cherry picked and plugged together in a way that creates something much greater than the sum of its parts.
Where to Test
Cory lists the different places where we can run our tests:
1. In a real browser (e.g. Karma Test Runner)
Another advantage is you can test against a real DOM.
This has the disadvantage of requiring more configuration, and he tests run more slowly than the alternatives.
For a 3 minute introduction to Karma, see Egghead’s Introduction to Karma
2. Headless browser (e.g. Phantom JS/Casper JS)
Cory says he has used this approach successfully in the past. I have also found Phantom JS to be useful: although it is not as good as Karma at testing DOM manipulation, the tests tend to run fast.
3. In memory DOM
An in memory DOM is a simulation of a real DOM in memory. Enzyme uses this behind the scenes
Cory also mentions that as the Twitter vote was close, he’s using the fileName.test.js convention in this course.
Also discussed is where test files belong. I have always put my test specs into a separate project before, but Cory makes the case for putting them in the same directory as your production files:
- Easy imports
- Clear visibility
- Convenient to open
- Move files and test together
Since trying this approach to file organization, I have found that it is much easier to spot files that have no associated test files.
In this module, we explore the in memory DOM option. Cory runs through the testing plan:
What: React components and Redux
How: Mocha with Expect
Where: In-memory DOM via JSDOM
Testing React with React Test Utils
We begin by testing the React presentation components, which are the easiest to test.
Cory reminds us of the shallow Render and Render into DOM options and compares the benefits and drawbacks of each approach.
In this clip we use shallow rendering, and we will cover render into DOM later.
Cory changes his Mocha setting from progress to spec. I have found spec to be more useful because of the additional information that it provides.
Our first test checks that CourseForm renders the form and an h1 tag.
Next we test that the save button is labelled save when not saving, and this involves updating our setup code to use a boolean argument called saving.
We also test that the save button is labelled saving… when saving.
Testing React with Enzyme
Now we write the same tests again, but this time using Enzyme. We see that a lot less setup code is required now, and that the code is significantly more readable, especially if you are already familiar with jQuery.
Cory also shows us that the code we write is less fragile.
This is exactly how testing should be: easy to write, and even easier to read.
Continue to Part 13 – Testing Redux