The section header implies that you have to do some preparation work before you can start your testing activities. But you don’t. There is no external support to download or install. Groovy treats unit testing as a first-class developer duty and ships with everything you need for that purpose.
Even more important, it simplifies testing by making assertions part of the language, automatically executing test cases by transparently invoking its TestRunner when needed, and providing the means to run suites of test cases easily, both from the command line and through integration with your IDE or build environment. This section will show you how simple it can be and introduce you to GroovyTestCase , the base class used for most unit testing in Groovy.
Writing tests is easy
Assume you have a simple Groovy script that converts temperatures measured in Fahrenheit (F) to Celsius (C). To that end, you define a celsius method like so:
- def celsius(fahrenheit) { (fahrenheit - 32) * 5 / 9 }
additional confidence in this method before the next non-US traveler uses your method to understand the US weather forecast.
A common approach with unit testing is to call the code under test with static sample data that produces well-known results. That way, you can compare the calculated results against your expectations.
Choosing a good set of samples is key. As a rule of thumb, having a few typical cases and all the corner cases you can think of is a good choice. 4 Typical cases would be 68° F = 20° C for having a garden party or 95° F = 35° C for going to the beach. Corner cases would be 0° F, which is between -17° C and -18° C, the coldest temperature that Gabriel Daniel Fahrenheit could create with a mixture of ice and ordinary salt in 1714. Another corner case is when water freezes at 32° F = 0° C.
Sound complicated? It isn’t. Listing 14.1 contains the method together with inline unit tests made with the simple assertions that are built into the language itself.
- Listing 14.1 Inline unit tests for the Fahrenheit to Celsius conversion method.
- def celsius (fahrenheit) { (fahrenheit - 32) * 5 / 9 }
- assert 20 == celsius(68)
- assert 35 == celsius(95)
- assert -17 == celsius(0).toInteger()
- assert 0 == celsius(32)
Whenever the environment of self-testing code changes, the inline tests assert that it is still working. Environmental changes can happen for a number of reasons: evaluating the script on a different machine, using an updated JDK or Groovy version, or running with different versions of packages that the script depends upon.
There are circumstances when tests cannot be inlined, such as due to performance requirements. In such cases, it is conventional to pack all the tests of a given script or class into a separate class residing in a separate file. This is where GroovyTestCase appears on stage.
GroovyTestCase: an introduction
Groovy bundles an extended JUnit class dubbed GroovyTestCase , which facilitates unit testing in a number of ways. It includes a host of new assert methods, and it also facilitates running Groovy scripts masquerading as test cases.
The added assertions are listed in table 14.1. We won’t go into the details of each method, mostly because they are descriptively named—where it’s not absolutely obvious what the meaning is, the description provided in the table should be sufficient. Even though we won’t discuss them explicitly, we will use them in the assertions elsewhere in this chapter, so you’ll see how useful they are.
However, Groovy doesn’t force you to extend GroovyTestCase , and you are free to continue to extend the traditional TestCase class provided by JUnit. Having said that, unless you need the functionality of a different subclass of TestCase, there are plenty of reasons to use GroovyTestCase and no reasons to specifically avoid it. Along with the assertions listed in table 14.1, it’s easier to work with GroovyTestCase than TestCase , as you’ll see in the next section.
Working with GroovyTestCase
To utilize Groovy’s enhanced TestCase class, extend it as follows:
- class SimpleUnitTest extends GroovyTestCase {
- void testSimple() {
- assertEquals("Groovy should add correctly", 2, 1 + 1)
- }
- }
- import junit.framework.TestCase
- class AnotherSimpleUnitTest extends TestCase{
- void testSimpleAgain() {
- assertEquals("Should subtract correctly too", 2, 3 - 1)
- }
- }
If the output looks familiar to you, that’s probably because it is the standard JUnit output you’d expect to see if you ran a normal Java JUnit test using JUnit’s text-based test runner. Now that you’ve got your feet wet, let’s go back and start again from scratch, this time testing a little more methodically.