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
Test the output: One step above “it renders” is “it renders the correct
thing.” Given a set of props, what output is expected? Does
its name and age, or does it render a name and “TODO: age coming in
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
button with an
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.
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.comments powered by Disqus