Jest, React and Preact!

Rupav Jain
5 min readJun 9, 2018

--

So this is my first blog on Medium, excited to share with you all what I have learnt so far about testing in my first phase of GSoC 2018 with Candis, HelikarLab.

Candis is an open source data mining suite (released under the GNUv3 licence) for DNA microarrays that consists of a wide collection of tools you require, right from Data Extraction to Model Deployment.

What’s with the title?

Well I didn’t make it to rhyme. Jest is a Javascript testing framework. React is a JS library. Preact is also a JS library, built to increase performance dramatically as compared to React. In Candis, we are using Preact as frontend and Flask backend. And while writing tests for Preact based app using Jest, I have not found much of a difference from testing React code. I have tested almost all Reducers and Action objects in Candis. This blog is about unit testing using Jest. So why React and Preact in the title? - Found it quite mouthful and catchy.😅

Why tests?

Consider a situation when you just pushed your enhancement feature, say X into your app. You adore the improvements in the app. Days passed, you added more features, but then one day a user reports a bug on your app feature, say Y which you believe was working before. Now, you can use your version control tool( assuming you were tracking your changes with Git or SVN) to revert back and forth and see at what time did that reported feature bug happened and then take the opportunity to blame the person who committed erroneous code using git blame.

To your horror, it was you only who brought that X feature along with errors on the Y feature and you thought that someday, someone would praise you for introducing X feature using git praise. “DUH”

This is where Continuous Integration/Development tools like Travis/Jenkins comes into picture for the rescue which for every commit or Pull request runs scripts/tests which you specify. Just like I am introduced to Candis to enhance it, I would not like to break some parts of the app just to introduce new ones in haste. So I began writing tests alongside setting up Travis, adding few front-end features and writing API endpoints for Flask back-end. Also writing tests will get you a good understanding of the code-base. If you still are not motivated to write tests for your project, check this video from PyCon 2014 by Nat Batchelder.

Why Jest?

Jest is a testing framework used by Facebook(creators of React) itself, so I chose this without comparing with others. Candis is Preact based, not a React project. But I have not found any roadblocks yet while using Jest for Preact, possibly will face when testing components (because of no official support of Enzyme for Preact).

Examples

Setting up 2 test cases, one for testing sum function and the other hello function. Process of testing with jest is quite simple, you specify test description, exercise calls to SUT(subject under test: In this case sum and hello ES6 functions), and the check for validation (if response of function is same as your expected one) using expect call. To compare 2 objects you need to use toEqual instead of toBe. That much easy is to test synchronous functions, but what about Asynchronous function? — use done parameter!

Mocks
So in Candis, we are using axios to send requests to flask server. Now testing axios will require to actually setup the server, then make a call, and the behaviour of axios will be unpredictable and slow, which makes this approach unsuitable for testing. So testing this asynchronous function, we use and should use Mocks. So Mocks are those objects which goes by the name of your real object, simulates the action you want them to perform, and then can return the value as you specified while making them. Actually stubs are also are used for the same purpose but they don’t change the behaviour of the function, instead returns canned/predetermined response. Checkout this thread and great insight on Mocks vs Stubs. For mocking axios, I am using axios-mock-adapter library. For example purpose lets use a simpler one, in Candis, I needed to test if nprogress library in one of the Reducers(a switch case) is setting the progress bar value to 1.0( which gets shown up in the browser). To test it, I created its mock in __mocks__ directory which returns the mocked version of norogress module.

const nprogress = jest.genMockFromModule('nprogress')                       export default nprogress

Then to test it if its set function was called with correct parameters in my reducer function, I used,

expect(nprogress.set).toHaveBeenCalledWith(1.0)

Without mocks, I couldn’t have tested nprogress without using automated browser tools like selenium. Mocks basically fakes the dependencies in testing a unit, thus provides us to do Unit Testing (a test per unit/function/feature).

Mocking must be limited but should be exploited if being used.

What Else?

There is much more than I have covered in this article about testing, most notably Snapshot Testing which I haven’t covered yet on Candis as well. So testing React Components is cumbersome unlike Actions and Reducer, because components are the one that renders to the web browsers. So we should be testing what renders on the screen due to components. And for that purpose we use Snapshot Testing. What it does, is saves the serializable value for your React component in a file with extension *.snap, and now if you change the code in that component, and rerun the snapshot test, it will fail as it will not match the saved snapshot you created earlier. Why is it important — If you don’t want to see changes in the UI, you just need to snap and save. Obviously jest offers you an option to update snapshots. For React components, use Enzyme to shallow render them and then snap using jest .toMatchSnapshot function.

Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren’t indirectly asserting on behavior of child components. ” — source: docs of Enzyme.

Thank you. I hope you can now start writing tests. :)

- My blog from more related stuff (more experience oriented in the GSoC with technical stuff related to issues and PRs of Candis).
- My Related PRs on jest tests in Candis.

Resources:

--

--

Rupav Jain

GSoC'18 with HelikarLab/Candis, GCI-17-18/18-19 Mentor @fossasia, ML enthusiast, NSIT undergrad.