CSC/ECE 517 Fall 2010/ch1 1f TU
Unit-testing frameworks for Ruby
Unit Testing
A unit is the smallest building block of a software. Such a unit can be: a class, a method, an interface etc. Unit testing is the process of validating such units of code.
Benefits
Some of the benefits are:
- Proof of your code
- Better design - Thinking about the tests can help us to create small design elements, thereby improving the modularity and reusability of units.
- Safety net on bugs - Unit tests will confirm that while refactoring no additional errors were introduced.
- Be able to detect and remove defects in a more cost effective manner compared to the other stages of testing.
- Be able to test parts of a source code in isolation.
- Making debugging more efficient by searching for bugs in the probable code areas.
- Documentation - Designers can look at the unit test for a particular method and learn about its functionality.
Unit-testing frameworks
Unit Test Framework is a software tool to support writing and running unit test.
List of unit testing frameworks for Ruby
- Test::Unit
- RSpec
- Shoulda
- Cucumber
Simple Calculator Program in Ruby
This is a simple Calculator class having four methods addition,subtraction,multiplication and division.We will test each of these methods using above frameworks.
class Calculator attr_writer :number1 attr_writer :number2 def initialize(number1,number2) @number1 = number1 @number2 = number2 end #-----------Addition of two numbers----------------# def addition result = @number1 + @number2 return result end #----------Subtraction of two numbers--------------# def subtraction result= @number1 - @number2 return result end #----------Multiplication of two numbers------------# def multiplication result= @number1 * @number2 return result end #-----------Division of two numbers-------------------# def division result = @number1 / @number2 return result end end
Test::Unit
Features of Test::Unit
- It provides assertions which return pass or fail result for each unit test.
- Each of the assertions has to be called from a context which is also called Test Method
Usage
require "calculator" require "test/unit" class TC_Calculator < Test::Unit::TestCase def test_addition assert_equal(8,Calculator.new(3,4).addition) end def test_subtraction assert_same(1,Calculator.new(4,3).subtraction) end def test_multiplication assert_not_same(12,Calculator.new(3,4).multiplication) end def test_division assert_not_equal(5,Calculator.new(8,2).division) end end
If we run it as "Ruby Application " we will get the output as following
Loaded suite tc__calculator Started F.F. Finished in 0.046 seconds. 1) Failure: test_addition(TC_Calculator) [tc__calculator.rb:8]: <8> expected but was <7>. 2) Failure: test_multiplication(TC_Calculator) [tc__calculator.rb:17]: <12> with id <25> expected to not be equal? to <12> with id <25>. 4 tests, 4 assertions, 2 failures, 0 errors
Shoulda
Features of Shoulda
- It allows to write code with more clarity for ruby application
- It allows to run test with the help of Test::Unit Configurations
- It provides context to group tests for a particular requirement
Usage
require "rubygems" require "calculator" require "test/unit" require "shoulda" class TC_Calculator_Shoulda < Test::Unit::TestCase context "Calculate" do should "addition of two numbers " do assert_equal 8,Calculator.new(3,4).addition end should "subtraction of two numbers " do assert_equal 1,Calculator.new(4,3).subtraction end should "multiplication of two numbers" do assert_equal 12,Calculator.new(3,4).multiplication end should "division of two numbers" do assert_equal 4,Calculator.new(12,3).division end end end
If we run above test as "Ruby Application" we will get the output as follows
Loaded suite tc__calculator__shoulda Started F... Finished in 0.064 seconds. 1) Failure: test: Calculate should addition of two numbers . (TC_Calculator_Shoulda) <8> expected but was <7>. 4 tests, 4 assertions, 1 failures, 0 errors
Cucumber
Features of Cucumber
- Its a Behavior Driven Development(BDD) tool for Ruby.
- It focuses on story styling plain English Text.
- It follows GWT(Given,When,Then) pattern
Usage
Let us first create a feature file to describe about our requirements
Feature: Addition In order perform addition of two numbers As a user I want the sum of two numbers Scenario: Add two numbers Given I have entered <input1> And I have entered <input2> When I give add Then The result should be <output>
Then we will create a ruby file to give a code implementation
require 'calculator' Before do @input1=3 @input2=4 end Given /^I have entered <input(\d+)>$/ do |arg1| @calc = Calculator.new(@input1,@input2) end When /^I give add$/ do @result = @calc.addition end Then /^The result should be <output>$/ do puts @result end
Now if we run the feature file we will get the following
Feature: Addition In order perform addition of two numbers As a user I want the sum of two numbers Scenario: Add two numbers # calculator.feature:7 Given I have entered <input1> # addition.rb:8 And I have entered <input2> # addition.rb:8 When I give add # addition.rb:12 7 Then The result should be <output> # addition.rb:16 1 scenario (1 passed) 4 steps (4 passed) 0m0.010s
RSpec
Features of RSpec
- Use RSpec to independently specify models, views, controllers and helpers.
- Integrated fixture loading.
- Special generators for models and controllers that generate specs instead of tests.
- Special RSpec matchers for even more readable specs.
Usage
Let us create our first specification file:
require "calculator" describe "TheCalculator's", "basic calculating" do before(:each) do @cal = Calculator.new(6,2) end it "should add two numbers correctly" do @cal.addition.should == 8 end it "should subtract two numbers correctly" do @cal.subtraction.should == 4 end it "should multiply two numbers correctly" do @cal.multiplication.should == 12 end it "should divide two numbers correctly" do @cal.division.should == 3 end #... end
This file contains nothing more than a description of an aspect of the calculator class. It contains a description of the basic calculating system. Inside the description are a set of four expectations (it "should add/subtract/multiply/divide..." and so on).
Let us associate code blocks with our expectations.
require "calculator" describe "TheCalculator's", "basic calculating" do before(:each) do @cal = Calculator.new(6,2) end it "should add two numbers correctly" do @cal.addition.should == 8 end it "should subtract two numbers correctly" do @cal.subtraction.should == 4 end it "should multiply two numbers correctly" do @cal.multiplication.should == 12 end it "should divide two numbers correctly" do @cal.division.should == 3 end end