On this episode of React Wednesdays, we talk with Eric Elliott about the questions every unit test must answer and how to craft more modular, resuable and debuggable code.
Finally, Unit Testing is no longer that thing you said you’d eventually get to, and purposely avoid. Eric Elliott dropped a masterclass in testing, complete with demonstrations and live coding, covering things like “The Five Questions Every Unit Test Must Answer,” the importance of RITE, and how testing makes you a better software developer. Eric’s interview is rich with wisdom and clarity.
On our October 7th, 2020 edition of React Wednesdays, we hosted Eric Elliott, Jesse, and Sergio to discuss Unit testing in React. During the show, we discussed the finer points of Unit Testing and watched a live demonstration of building unit tests for a React application. This show was especially interesting to me and my colleagues at Digital Primates because we use Eric’s materials in our training program for new consultants who work on Enterprise React applications. The full recording of our show on React Unit Testing with Eric Elliott is available on YouTube.
Eric Elliott is a prolific author, mentor, advisor, and developer. As part of his work, he runs DevAnywhere, a live 1:1 remote mentorship program using video meetings with screen sharing and hands-on coding. Jesse is a member of the program and also serves as a mentor. Sergio is an active mentee in DevAnywhere and gives great code reviews.
Eric opened the discussion with a concise masterclass in proper test design (1:51). Many developers agree testing is necessary, but don't yet understand how to write quality tests. Eric's advice is clear and approachable and would fit on a sticky note. React developers would do well to place this on their monitor for reference.
His first point is to make components testable through proper component design. React provides mechanisms to separate visual elements from business logic and state. Components with properly separated concerns are easier to test, and easier to use and reuse. He then explained the five questions every unit test must answer.
The Five Questions Every Unit Test Must Answer
Eric developed a mental guide to help software developers ensure they write tests of good quality. He summarized the points into five questions.
- What is the unit under test (module, function, class, whatever)?
- What should it do? (Prose description)
- What was the actual output?
- What was the expected output?
- How do you reproduce the failure?
He explains the thinking behind each point, as well as why each is important.
Another point for the sticky-note is Eric's acronym on the elements of a good test. This acronym is RITE:
- Readable - Test should be self-explanatory.
- Isolated for Unit tests - Tests have their own setup and state. No mutable items are shared between tests.
- Integrated - Integration tests are also important tests to validate what happens when things are combined.
- Thorough - Test all likely edge cases, error conditions, and boundaries. Consider writing the test first, then the code.
- Explicit - Place all items required to undertake the test inside the test code (set up data, factory functions, tear down logic).
Testing Made Me a Better Programmer
Many software developers who are new to testing have a hard time reconciling testing with their other work. At times, testing can feel orthogonal to writing the code that ships. Developers usually feel pressed for time and feel the urge to skip testing. I asked Eric to offer advice to developers who shared that sentiment (10:51).
Eric explained that writing testable code encourages modularity, and modular software is most often better designed and implemented. Modularizing the code for testing helps the software developer build software that is easy to maintain and components that are easier to use.
From the management perspective, Test Driven Development practices grow confidence in development teams to ship code with less fear that an unexpected side effect will impact production.
Further, Eric says a good test suite is the best technical documentation you can have because it is granular and guaranteed not to get out of sync with the code, unlike written documentation does.
Jesse started a live coding demonstration of building and testing code (15:49). His example consisted of two components:
- Component 1 - Takes in text via an input form
- Component 2 - Displays accumulated text in list form+
We watched Jesse build the two components and add appropriate tests for the next 20 minutes. During the process, he and Eric explained the source code and the reasons and strategy behind each decision.
Jesse used RITEway, an open-source library for simple, readable, helpful unit tests that conform to the "Five Questions." RITEway forces you to write Readable, Isolated, and Explicit tests, because that's the only way you can use the API. The RITEway method of writing tests is very straightforward and easy to read. It also scales well as tests accumulate. RITEway looks to be a beneficial library to structure and run tests. If you are new to tests or are interested in RITEway, be sure to watch this segment. There are many interesting sections like:
- Which selectors should you use?
- What needs a test, and what does not?
- What is the role of Behavior Driven Development (BDD)?
- Is it really legacy code if it has tests?
- What about testing Redux reducers?
Unit testing is vital to ensuring high code quality. Unit testing also helps development teams maintain their feature shipping velocity. Even as the code base grows in size and complexity, the test coverage reduces unknown side-effects from code changes so software development teams can ship without worry.
To close out the show (56:14), I gave my impression that building unit tests with RITEway was very easy to do and didn't distract at all from the development work. Eric replied with what might be the most poignant advice:
The benefits [Of TDD] are monumental... I started to get a lot faster with TDD than before I started using TDD even though I'm writing two, three, or four times more code. It's not typing the characters out that is time-consuming. What is time-consuming about programming is thinking through what a component should do, how it should relate to other system components, and the system architecture. TDD helps you think through this process in a way to write more modular, more reusable, and more debuggable code. —Eric Elliott
We learned a lot from our time with Eric, Jesse, and Sergio and are glad to make the recording available for you on the React Wednesdays YouTube Playlist. If you'd like more information, check out Eric's book Composing Software, and Eric's YouTube Channel. If you’d like to stay current on topics like these, consider subscribing to the Enterprise React Newsletter. New issues come every two weeks.
React Wednesdays is a weekly, live show hosted by T.J. VanToll from Progress, and myself, Dan Wilson from Digital Primates. Each week, we have guests showing and discussing the most interesting topics in the React ecosystem. You can find information about the show, along with upcoming and previous episodes at the React Wednesdays website.