What Makes CRC Code Testable?

Learn how testing should be done in a Phoenix application.

Why testing is important

Think of a test as a scientific experiment. The experiment’s target is a bit of code, and the thesis is that the code is working. Logically, each test is an experiment that does three things:

  • Sets up preconditions
  • Provides a stimulus
  • Compares an actual response to expectations

That definition is pretty broad and covers a wide range of testing strategies and frameworks. We’re going to write three tests of two specific types. Both types of tests will follow this broad pattern. One of the tests will be a unit test. We’ll write it to verify the behavior of the independent functions that set up the socket. We’ll also write two integration tests that will let us verify the interaction between components: one to test interactions within a LiveView process and another to verify interactions between processes.

The integration tests we write will interact with LiveView machinery to examine the impact of page loads and events that flow through a LiveView. A good example of such a test is simulating a button click and checking the impact on the re-rendered LiveView template. Integration tests have the benefit of catching integration problems—problems that occur at the integration points between different pieces of your system, in this case, the client and the server.

These integration tests are certainly valuable, but they can be brittle. For example, if the user interface changes the button into a link, your test must be updated. That means this type of test is costly in terms of long-term maintenance. Sometimes it pays to isolate specific functions with complex behavior—like our LiveView reducer functions—and write pure tests for them. Such tests are called unit tests because they test one specific unit of functionality. Let’s discuss a testing strategy that addresses both integrated and isolated tests.

Isolation Vs. Integration

Pure unit tests call one function at a time and then check expectations with one or more assertions. If you’ve designed your code well, you should find lots of opportunities for unit tests. By filling up your application’s functional core with pure, predictable functions and by adhering to the CRC pattern, you’ll find yourself with many small, isolated functions that can be tested with small, isolated unit tests, as follows.

Get hands-on with 1200+ tech skills courses.