Ruby is a beautiful language. The simplicity, expressiveness makes it an addictive programming language. The dynamic nature of the Ruby language advocates the use of unit testing. In this article we will walk through a simple application which checks if a number is prime or not.

Writing Unit Tests in Ruby:

As mentioned before unit testing is built into the Ruby framework. You do not need to install any third party libraries to get started with unit testing in the Ruby language. Add a reference to the 'test/unit' module in your ruby file and you are ready to write your unit test.



Next, we declare a class which inherits from Test::Unit::TestCase class. The TestCase class provides all the necessary features for performing unit tests.



There are couple of things to note here! First the class name must always begin with a capital letter. Second the name of the unit test must begin with the keyword "test". Ruby is a conventional language instead of configuration and it is advised that you follow Ruby's convention.

Our first test will make sure that if 0 or 1 is passed then false is returned since both of these numbers are not prime numbers. We can create a separate class called "PrimeService" which can have a "is_prime?" method responsible for the validity of the prime number. A separate "PrimeService" class will function property but since the "is_prime?" method is only exposed on numbers why not just extend the Integer class.

Extending classes in the Ruby language is quite simple! Simply start adding methods to the class and the new methods will be available for the particular extended type. The implementation below shows how to extend the Integer class and add a new method "is_prime?" to it.  



Isn't that just beautiful!

Here is our first test:



The test makes sure that when 0 or 1 is sent to the "is_prime" method false is returned. This can be implemented in many different ways the easiest being the following:



The "self" keyword refers to the object on which the extension method is acting. In our case the self will refer to a number since we are typing 2.is_prime?, 0.is_prime? etc.

The above code can be changed to use the unless keyword.



The above statement returns false unless the array does not contain numbers which are either 0 or 1. To run the test in TextMate press the command key and the "R" key at the same time. This will run all the unit tests in the file. If you only want to run the currently focused unit test then press "Shift" + "Command" + "R" key.

Our next unit test makes sure that the user input is not a negative number. In this case we would like to through an exception. The unit test is shown below:



The above unit test makes sure that an ArgumentError exception is thrown whenever a negative number is checked for the validity of a prime number. The "is_prime?" method is changed to reflect this feature.



The raise keyword raises an exception unless the input supplied by the user is greater than zero. The statement reads like an English language and conveys the message clearly to the user.

The following unit test ensures that the numbers validated against the "is_prime?" method are all prime numbers.



The is_prime? method is changed to the following:



The above is the complete implementation of the "is_prime?" method. As, you can see it takes only a couple of lines to implement the complete feature.

We used the dot notation to run a loop. The three dots indicate that the end value which in this case is the value of the number is not included in the loop. This means if we invoke "is_prime?" on the number 5 then the loop will run for the following numbers.


Finally, we perform the MOD between the user input and the loop value and if the remainder results in "0" then the number is not prime since it is divided by number other then itself and "1".

Conclusion:

In this article we introduced unit testing in the Ruby language. Unit testing is an absolute must when writing Ruby applications. In the next article we will discuss how to write better unit test by using the spec framework.