The promise of unit tests is grand: with proper tests in place, you can refactor code like crazy and have confidence that you didn’t break anything. You can add new features or tweak existing ones with that same level of confidence.
When it comes time to actually write the tests though, we often get stuck. What exactly should you test? It can be hard to tell when or why to test your app, too.
And are tests even worthwhile? A lot of examples test silly things like “when the mouse hovers over a link, the color should change.” If that’s the kind of stuff being tested, why bother?
So, here are a few reasons why testing done right is worth it. The first couple sections are more general, and the last is more specific to React.
(and no, testing link hover colors is not worth it)
The Big Reason
The main reason to write tests is to ensure that your app works the way it should. That’s really all it is.
The trouble comes when you define “works the way it should” to be very, very fine-grained, to the point of checking link hovers and static text.
Instead, test the high-value features.
Features Worth Testing
For example, let’s say you have a shopping cart. You click an “Add to Cart” button. The app had better damn well add that item to the cart. Even though this logic is fairly straightforward, you’d want to write a test for this.
What else… How about updating an item’s count in the cart? That seems test-worthy.
What if the count is incremented too high? Is there a maximum? What if it’s decremented to 0? Does the item get removed, or does it remain with a count of “0”? Edge cases like this are worth testing.
Also worth testing: anything that takes user input. Form validation, error handling when the input is wrong, and so on.
Fiddly algorithms, like some kinds of array manipulation… or recursive algorithms like building a tree out of a flat array – these things are worth testing, and might be worth tackling with test-driven development.
What to Test?
Here are some general guidelines for what’s worth testing about a React component. This is an excerpt from Getting Started with TDD in React.
It must render: At the very least, make sure the component renders without error. This verifies there are no JSX syntax errors, that all variables are defined, etc. This could be as simple as verifying that the rendered output is not null.
Test the output: One step above “it renders” is “it renders the correct
thing.” Given a set of props, what output is expected? Does Person
render
its name and age, or does it render a name and “TODO: age coming in
v2.1”?
Test the states: Every conditional should be accounted for. If the
classNames are conditional (enabled/disabled, success/warning/error, etc),
make sure to test that the className-deciding logic is working right. Likewise
for conditionally-rendered children: if a Logout
button is only
visible when the user is logged in, for instance, make sure to test for that.
Test the events: If the component can be interacted with (an input
or
button
with an onClick
or onChange
or onAnything
), test that the
events work as expected and call the specified functions with the correct
arguments (including binding this
, if it matters).
Test the edge cases: Anything that operates on an array could have boundary cases — an empty array, an array with 1 element, a paginated list that should truncate at 25 items, and so on. Try out every edge case you can think of, and make sure they all work correctly.
Optionally, you can test that no errors are printed to the console. This verifies that you didn’t miss any required props, among other things.
Wrap Up
Hopefully this post gave you some ideas of what’s worth testing. If you want to learn more about testing React, check out the comprehensive Getting Started with TDD in React post.
What other things do you think are worth testing, or not worth testing? Leave a comment below.