Rspec : RSpec is a Behaviour Driven Development framework for Ruby. It provides two frameworks for writing and executing examples of how your Ruby application should behave: a Story Framework for describing behaviour at the application level; and a Spec Framework for describing behaviour at the object level. RSpec is the original Behaviour Driven Development framework for Ruby 1) A story Framework for describing behaviour at the application level 2)A Spec Framework for describing behaviour at the object level
Before going to the BDD let us discuss about what is testing and how to integrate it with our Rails application. Before proceeding let's have a quick look of few definitions: The Tests - They are test applications that produce consistent result and prove that a Rails application does what it is expected to do. Tests are developed concurrently with the actual application. The Assertion - This is a one line of code that evaluates an object (or expression) for expected results. For example, is this value = that value? is this object nil? The Test Case - This is a class inherited from Test: Unit::TestCase containing a testing strategy comprised of contextually related tests. The Test Suite - This is a collection of test cases. When you run a test suite, it will, in turn, execute each test that belongs to it.
Rails Testing : When you run the helper script script/generate to create controllers and models, Rails generate a framework for unit and functional tests. There are two important points to test in a Rails application: Testing the Models. Testing the Controllers. Sample Example: Create a sample rails application by using the following command C:
uby> rails -d mysql demoapp
production: adapter: mysql encoding: utf8 database: demoapp_production username: root password: password host: localhost Generate Migration: Assume you have a table containing books, including their titles, price and a small description. The following migration sets up this table: demoapp > ruby script/generate migration books Now modify the demoapp /db/migrate/20080616170315_books.rb file as follows:
Now modify the demoapp /db/migrate/20080616170315_books.rb file as follows: class Books < ActiveRecord::Migration def self.up create_table :books do |t| t.string :title, :limit => 32, :null => false t.float :price t.text :description t.timestamp :created_at end end def self.down drop_table :books end end demoapp > rake db:migrate This will create books table in demoapp_development database. Now after this we need to set up your test database using rake command as follows:
ubydemoapp > rake db:test:clone_structure Testing Models: When you generate a model with the generate script, Rails also generates a unit test script for the model in the test directory. It also creates a fixture, a YAML file containing test data to be loaded into the testapp_test database. This is the data against which your unit tests will run: demoapp > ruby script/generate model Book you'll write corresponding tests in these files. So let's create two test book records using YAML in test/fixtures/books.yml as follows: name1: id: 1 title: 'Ruby' price: 100 description: 'Ruby programming' name2: id: 2 title: 'Rails' price: 200 description: 'Rails programming'
Now let's relace exsiting code in book unit test file test/unit/book_test.rb with the following code: require File.dirname(__FILE__) + '/../test_helper' class BookTest < ActiveSupport::TestCase fixtures :books def test_book perl_book = Book.new :title => books(:perl_cb).title, :price => books(:perl_cb).price, :description => books(:perl_cb).description, :created_at => books(:perl_cb).created_at assert perl_book.save perl_book_copy = Book.find(perl_book.id) assert_equal perl_book.title, perl_book_copy.title perl_book.title = "Ruby Tutorial" assert perl_book.save assert perl_book.destroy end end
Finally, run the test method as follows: demoapp > ruby test/unit/book_test.rb Here's the output of running the successful test case: demoapp > ruby test/unit/book_test_crud.rb Loaded suite ./test/unit/book_test Started . Finished in 0.0625 seconds. 1 tests, 4 assertions, 0 failures, 0 errors
BDD ( Behaviour Driven Development) : Behaviour Driven Development is an Agile development process that comprises aspects of Acceptance Test Driven Planning, Domain Driven Design and Test Driven Development. RSpec is a BDD tool aimed at TDD in the context of BDD. We say that RSpec is what is traditionally known as a unit testing framework, but we prefer to describe it as “a Domain Specific Language for describing the expected behaviour of a system with executable examples.” To install the RSpec gem, open up a command prompt and type … gem install rspec
RSpec provides a Domain Specific Language for describing the expected behaviour of a system with executable examples. The first methods we’ll encounter are describe and it. These methods used to have other names (which are still supported but generally not recommended), but we use describe and it because they lead you to thinking more about behaviour than structure. create a file in this directory named user_spec.rb and type the following: describe User do end and next In the shell, type the following command: spec user_spec.rb The spec command gets installed when you install the rspec gem. It supports a large number of command line options.
you want to know more commands for spec just type spec running spec user_spec.rb should have resulted in output that includes the following error: ./user_spec.rb:1: uninitialized constant User (NameError) We haven’t even written any examples and already RSpec is telling us what code we need to write. We need to create a User class to resolve this error, so create user.rb with the following: class User end and require it in user_spec.rb: require 'user' describe User do end
Now run the spec command again. spec user_spec.rb Finished in 6.0e-06 seconds 0 examples, 0 failures The output shows that we have no examples yet, so lets add one. We’ll start by describing the intent of example without any code. describe User do it "should be in any tasks assigned to it" do end end
The it method returns an instance of Example. This is a metaphor for an example of the behaviour that we are describing Run the spec, but this time add the --format option: spec user_spec.rb --format specdoc User - should be in any tasks assigned to it Finished in 0.022865 seconds 1 example, 0 failures Now add a Ruby statement that begins to express the described intent.
describe User do it "should be in any tasks assigned to it" do user.should be_in_project("assigned task") end end and run the spec command. spec user_spec.rb --format specdoc User - should be in any tasks assigned to it (ERROR - 1) NameError in 'User should be in any tasks assigned to it‘ undefined local variable or method `user' for <#<Class:0x14ed15c>:0x14ecdd8> ./user_spec.rb:6: Finished in 0.017956 seconds 1 example, 1 failure
There are a couple of things to note about this output. First, the text “(ERROR – 1)” tells us that there was an error in the “should be in any roles assigned to it” example. The “1” tell us that as we scroll down to the detailed failure report that this particular failure is described under “1)”. This will become more useful as the number of examples increases. Another thing to note is the absence of any references to RSpec code in the backtrace. RSpec filters that out by default, however you can see the entire backtrace by adding the --backtrace switch to the command.