Chapter 6. Testing in Clojure

Testing is quite possibly the most controversial topic in software development I've ever seen. Some developers are passionate about the merits of automated testing, what should be tested, and how. Conversely, some developers are dead set against automated testing. This can be especially so in languages that come with a REPL. That being said, Clojure still ships with a clojure.test namespace. As such, this chapter will focus primarily on how we can use clojure.test to write tests for our hipstr.validators.user namespace. In this chapter, we will:

  • Explore the necessity of automated testing in Clojure (hint: I believe there is always room for testing)
  • Discuss how to write assertions and tests, and how to run them

    Tip

    What this chapter won't cover, however, is extensive philosophy, patterns, and so on. Automated testing is a huge topic, one that I've studied for over ten years, and still have an enormous amount to learn. The purpose of this chapter is to show you enough to get going: to provide you with a starting point from which you may branch out.

Buckle up, this chapter will likely produce some disagreements.

Note

There are more testing frameworks for Clojure than you can possibly imagine. While this chapter will focus on the clojure.test namespace that ships with Clojure, you might want something a little more fancy. You can see a high-level overview of various Clojure testing libraries at https://clojure-libraries.appspot.com/cat/Testing.

The necessity of testing

I will fully admit that, for the bulk of my career, I've used automated testing in some capacity on almost every project I've worked on. For nearly a decade, I've employed the practice of test-driven development (TDD) to some degree.

While working on applications using Java or .NET, I often write tests to help me explore ideas and assist in the design and implementation of those ideas. I follow the TDD "Red/Green/Refactor" (http://en.wikipedia.org/wiki/Test-driven_development#Development_style) with discipline, and what I produce often works, is extensible, and is in the style of those languages (for better or for worse). I also have a safety net, which validates whether the system does what it is supposed to do; this comes in handy as the system grows, changes, and gets refactored over time.

The Red/Green/Refactor methodology dictates that you write a failing test first, then implement the least amount of code to get that test to pass, and then refactor your code (both the code that you're testing, as well as the test itself). The following diagram illustrates this process:

The necessity of testing

This methodology works well for Java and .NET applications, as well as any application that has a compiling step in the build process, which prohibits us from being able to test the function inline while we develop it.

However, when working with languages such as Python, JavaScript, or Clojure, wherein a shell/console/REPL exists and is at my disposal, my practice changes. In Clojure, I will start writing the function first, and will use the REPL to validate the results of the function. Once I'm satisfied with the result of the function, I then write the tests. Sometimes, I'll toggle back and forth between the REPL and the test, writing the test for each scenario I attempt in the REPL. I'll repeat this process for any refactors I make to the function under test, as well. The following diagram illustrates this somewhat more streamlined process:

The necessity of testing

This process works particularly well if you're using an editor such as Light Table. One of the great features in Light Table is called InstaREPL, wherein you can convert any Clojure file you're working on into a REPL and get live feedback on everything happening in the module while you type. Function results, variable values, and exceptions appear inline with your code. The result is an incredibly immersive development experience and the turnaround time on feedback is approximately zero.

The following is a screenshot of Light Table's InstaREPL in action while developing the hipstr.validators.user-validator namespace in Chapter 5, Handling Form Input.

The necessity of testing

Some developers argue that using the REPL is the only thing required when developing in Clojure, as it allows them to validate the results of their function and proceed after they get what they want. However, this does not address the ongoing maintenance, especially in teams where more than one person is working on the code base or in an environment employing continuous integration, where running tests is typically a step in the build process.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.20.231