CSC/ECE 517 Fall 2011/ch2 2e gp: Difference between revisions
Line 142: | Line 142: | ||
== Shoulda == | == Shoulda == | ||
Shoulda | Shoulda is a library rather than a framework which gives the flexibility to write better and easy to understand tests for the Ruby application being tested. Shoulda compliments Test::Unit and RSpec in the sense that it can be used within both of them. Using Shoulda one can provide context to tests so that, tests can be grouped according to a specific feature or scenario. | ||
===Features=== | |||
[[File:Capture1.JPG|thumb|left|170px|components of Shoulda]] | |||
Shoulda consist of matchers, test-helpers and assertions - | |||
Assertions | '''Matchers'''<br> | ||
Matchers are Test::Unit- and RSpec-compatible one-liners that test common Rails functionality. These tests would otherwise be much longer, more complex, and error-prone. | |||
'''Helpers'''<br> | |||
Helpers like ''#context'' and ''#should'' gives RSpec like test blocks in Test::Unit. In addition, one gets nested contexts and a much more readable syntax. | |||
'''Assertions'''<br> | |||
Many common Rails testing idioms have been distilled into a set of useful assertions. | Many common Rails testing idioms have been distilled into a set of useful assertions. | ||
<br><br><br> | |||
===Usage=== | |||
== RSpec == | == RSpec == |
Revision as of 13:39, 19 September 2011
Testing Frameworks for Ruby
This page serves as a knowledge source for understanding the different Testing Frameworks available for Ruby.
Introduction
No code is perfect from the word go! Testing plays an important role in System Development Life Cycle. During testing, we follow a taxonomic procedure to uncover defects at various stages. A test framework provides various Test Types, Test Phases, Test Models, Test Metrics and acts as a guideline as to how to perform effective testing <ref> http://www.scribd.com/doc/15909730/Software-Testing-Framework </ref>. Various testing tools are available for Rubylanguage, each having some unique features over others. Here is a brief introduction and feature comparisons of popular testing frameworks.
Testing Approaches
Before we delve into testing for Ruby, in general, these are the followed approaches in industry today
Test Driven Development
This strategy, (abbreviated as TDD) <ref> http://en.wikipedia.org/wiki/Test-driven_development </ref>, though cumbersome due to its methodology develops efficient code. First a unit test is written for a function, even before the code for that function is developed. Based on this test minimal code is developed to ensure the test succeeds; if not the code is modified until test run successfully. In this iterative approach, effort is made to ensure flawless code is developed.
Behavior Driven Development
BDD <ref> http://en.wikipedia.org/wiki/Behavior_Driven_Development </ref> as its popularly know, upholds the traditional iterative workflow of Test Driven Development, but it focuses on defining behaviors that is easy to understand to naive people (with no programming background) by writing tests in natural language. This approach focuses more on looking at code development from a behavioral abstraction. For example testing the code for a recipe belonging to a category of a cookbook, in BDD would be something like 'A recipe can't be without a category'
Unit Testing
Unit Testing is a method by which we can isolate and test a unit functionality of the program, typically individual methods during and long after the code is written.
Cucumber
Cucumber is a testing tool that follows the BDD approach of testing. Cucumber written itself in Ruby programming language allows the execution of feature documentation written in natural language often termed as [user stories]
Features of Cucumber
Terminology of Cucumber
Stakeholder - A person who gets some value out of the system like an administrator
Feature - A feature is a piece of system functionality that delivers value to one or more stakeholders
User story - It is a rough description of scope for future work used as planning tools. Most common format for the stories are - "in order to...","as a...","I want"
Feature file - It describes a feature or a part of feature with illustrative example of expected results
Key Example - Each feature is illustrated with Key Examples which show what are expected in a given test case
Scenario - Scenario captures one key example for a feature file. It represents how stakeholder gets some value from that system. Example of good scenarios for checking login module includes user not signed up, password has expired
Step - Steps are domain language phrases which can be combined to write scenarios. They combine a GWT directive with a regular expression to evaluate something and add a simple ruby code which tells the step what should be done further.
Pattern
Cucumber follows a GWT (Given-When-Then) pattern for developing test cases. In the scenarios written for Cucumber, we state what a given scenario is, when we are presented with information and then what should happen so that the logic of information can be validated.
Example
Cucumber is a high-level testing tool that defines the feature specs. An typical [example] for a Cucumber Scenario is shown below -
First we need to install the Cucumber gem on Ruby using this simple command
$gem install cucumber-rails
Successfully installed cucumber-rails-0.3.0
1 gem installed
Installing ri documentation for cucumber-rails-0.3.0...
Installing RDoc documentation for cucumber-rails-0.3.0...
When installed, a basic Cucumber test is generated using generator script
$script/generate rspec
$script/generate cucumber
force config/database.yml
create config/cucumber.yml
create config/environments/cucumber.rb
create script/cucumber
create features/step_definitions
create features/step_definitions/web_steps.rb
create features/support
create features/support/paths.rb
create features/support/env.rb
exists lib/tasks
create lib/tasks/cucumber.rake
A feature file is next created with name feature_name.featrue . the Feature is described in the Feature: directive, followed by the story. The story is written in the format shown in the code: As a <role> , I want <feature> , So that <business Value>.
$ nano tasklist.feature
Feature: Tasks
In order to keep track of tasks
People should be able to
Create a list of tasks
Each feature can have multiple scenario. One such scenario for the login feature is as shown below
Scenario: List Tasks
Given that I have created a task "task 1"
When I go to the tasks page
Then I should see "task 1"
When a scenario is ready following command is issued
$script/cucumber features/tasklist.feature
0 scenarios
0 steps
Steps can be added to scenarios, which are combination of a GWT directive, a regular expression and a block of ruby code which states what this step does
/features/step_definitions$nano tasklist_steps.rb
Given /^that I have created a task "(.*)"$/ do |desc|
Task.create!(:description => desc)
end
When /^I go to the tasks page$/ do
visit "/tasks"
end
Test::Unit
The in-built, ready to use unit testing mechanism for Ruby is called Test::Unit.It belongs to the XUnit family unit testing framework. It has a setup method for initialization, a teardown method for cleanup and the actual test methods itself. The tests are bundled separately in a test class in the code it is aimed to test.
Features
This salient features of the Test::Unit Framework are:-
Assertions
We can use Test::Unit to make assertions. The test is successful if the assertion is true and fails if the assertion is false. All the assertion methods provided by test::unit can be found at Test::Unit::Assertions.
assert( boolean, [message] ) | True if boolean |
assert_equal( expected, actual, [message] ) assert_not_equal( expected, actual, [message] ) |
True if expected == actual |
assert_raise( Exception,... ) {block} assert_nothing_raised( Exception,...) {block} |
True if the block raises (or doesn't) one of the listed exceptions. |
Test-Fixtures
Using a test fixture, we can initialize (and cleanup) the common set of data for two or more tests hence eliminating unnecessary duplication. Fixtures are written in the setup() and teardown() methods.
Test-Suite
As unit tests increase in number for a given project, it becomes tough running them one at a time. It is hence useful to combine a bunch of related test cases and run them as batch. Test::Unit provides a class called TestSuite for this purpose<ref>[1]</ref>.
Example Test
The Test::Unit::TestCase class is the main class and the BinarySearchTest is the subclass, it overrides setup and teardown methods. All test methods start with 'test_' prefix thus differentiating helper methods from main methods. The Test::Unit::TestCase class makes the test methods into tests, wrapping them into a suite and running the individual tests. The results are collected into Test::Unit::TestResult object.
require 'test/unit' require 'english_french' class EnglishFrenchTest < Test::Unit::TestCase include EnglishFrenchTranslator def test_simple_word s = translate("house") assert_equal("mason", s) end def test_word_beginning_with_vowel s = translate("apple") assert_equal("pomme", s) end def test_two_consonant_word s = translate("stupid") assert_equal("stupides", s) end end
The tests are run by running the file test_english_french.rb.Sample results for the above test is shown below.
$ ruby test_english_french.rb Loaded suite test_english_french Started FFF Finished in 0.01091 seconds. 3 tests, 3 assertions, 0 failures, 0 errors
Shoulda
Shoulda is a library rather than a framework which gives the flexibility to write better and easy to understand tests for the Ruby application being tested. Shoulda compliments Test::Unit and RSpec in the sense that it can be used within both of them. Using Shoulda one can provide context to tests so that, tests can be grouped according to a specific feature or scenario.
Features
Shoulda consist of matchers, test-helpers and assertions -
Matchers
Matchers are Test::Unit- and RSpec-compatible one-liners that test common Rails functionality. These tests would otherwise be much longer, more complex, and error-prone.
Helpers
Helpers like #context and #should gives RSpec like test blocks in Test::Unit. In addition, one gets nested contexts and a much more readable syntax.
Assertions
Many common Rails testing idioms have been distilled into a set of useful assertions.
Usage
RSpec
Comparison
Conclusion
References
<references/>