程式扎記: [ In Action ] Everyday Groovy - Unit Test : Getting started

標籤

2015年2月25日 星期三

[ In Action ] Everyday Groovy - Unit Test : Getting started

Preface 
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: 
  1. def celsius(fahrenheit) { (fahrenheit - 32) * 5 / 9 }  
Is this implementation correct? Probably, but you can’t be sure. You need to gain 
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. 
  1. def celsius (fahrenheit) { (fahrenheit - 32) * 5 / 9 }  
  2. assert 20  == celsius(68)  
  3. assert 35  == celsius(95)  
  4. assert -17 == celsius(0).toInteger()  
  5. assert 0   == celsius(32)  
Inline tests of this kind are very useful. Just look at this book: Most listings contain such self-checking asserts to ensure the code works and to help reveal your expectations from the code at the same time. 

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: 
  1. class SimpleUnitTest extends GroovyTestCase {  
  2.    void testSimple() {  
  3.      assertEquals("Groovy should add correctly"21 + 1)  
  4.    }  
  5. }  
Remember, you are free to extend any TestCase class you choose, so long as it is in your classpath. For example, you can easily extend JUnit’s TestCase as follows: 
  1. import junit.framework.TestCase  
  2. class AnotherSimpleUnitTest extends TestCase{  
  3.    void testSimpleAgain() {  
  4.      assertEquals("Should subtract correctly too"23 - 1)  
  5.    }  
  6. }  
GroovyTestCase has the added benefit that it also allows test cases to be run via the groovy command, which is not possible for test cases that extend the normal JUnit TestCase class. For example, the SimpleUnitTest script seen earlier, which extends GroovyTestCase , can be run by typing the command groovy SimpleUnitTest
> groovy SimpleUnitTest
.
Time: 0
OK (1 test)

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.

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!