(TDD) Test-driven development is the act of writing tests before writing any code. Also known as red/green testing because you write the test, it fails, and then you write the code that makes it pass.
RSpec is a behavior-driven development (BDD) testing tool for Ruby, and is widely used for testing both plain Ruby and full-on Rails applications.
Setting up RSpec
Install the Rspec gem in your gemfile and run bundle install.
Create your new rails application as:
rails new <app_name> -T
Or remove your
test
directory from your existing application:
rm -rf test/
Make an entry in your Gemfile:
group :development, :test do
gem ‘rspec-rails’
end
From the command line install the gem
$ bundle install
From the command line install rspec into your application:
$ rails generate rspec:install
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
This will create a spec folder which will contain a spec_helper.rb, a rails_helper.rb. An .rspec file will also be created in the root directory which will allow you to automatically require the spec helper in all specs.
Running RSpec tests
To run all RSpec tests in your Rails project, use this console command:
bundle exec rspec
RSpec Blocks : describe and it
Here’s the first test from random_character_generator_spec.rb
:
# /spec/services/random_character_generator_spec.rbRSpec.describe RandomCharacterGenerator do
describe "#new_character" do
# NOTE: Do NOT create your test variables this way!! rcg = RandomCharacterGenerator.new
player = Player.create(user_name: "Ronald McDonald", display_name: "Mac")
character = rcg.new_character("Ronnie the Rat", player) it "creates a new Character instance" do
expect(character).to be_an_instance_of Character
end end
end
Let’s walk through this:
- At the top, we have
RSpec.describe <ClassName> do
. This encapsulates our tests for theRandomCharacterGenerator
service object class. - Underneath, we have
describe "#method_name" do
. This encapsulates our tests for thenew_character
method. It is a Rails convention to add#
before this--that way, the test output will readRandomCharacterGenerator#new_character
, which helps us know what we're testing. - Inside that
describe
block for our method, we instantiate a couple objects to test, and run thenew_character
method so we can assign its output to the variablecharacter
. This will give us all the objects we need to test the method's behavior. - Finally, we have an
it "description of expected behavior" do
block. This is where we write the test code logic! In a very expressive style, we see that the test itself expects the variablecharacter
to be an instance of the classCharacter
. If this line evaluates to True, our test will pass--otherwise, it will fail!
Equal value (or not)
expect(target).to eq 1
expect(target).not_to eq 1
Math comparisons
expect(5).to be < 6
expect(5).to == 5
expect(5).to equal value
expect(5).to be_between(1, 10)
expect(5).to be_within(0.05).of value
Type-specific
expect(x).to be_zero # FixNum#zero?
expect(x).to be_empty # Array#empty?
expect(x).to have_key # Hash#has_key?
Objects
expect(obj).to be_an_instance_of MyClass
expect(obj).to be_a_kind_of MyClass
Errors
expect { user.save! }.to raise_error
expect { user.save! }.to raise_error(ExceptionName, /msg/)
Enumerables
expect(list).to include(<object>)expect(list).to have(1).things
expect(list).to have_at_least(2).things
expect(list).to have_at_most(3).things
If you are more visual here a small video (by Jesus Castello) that describe the base of testing with Rspec :.