What is Rspec?
RSpec is the most popular testing framework for Ruby
RSpec-rails which is an extension of RSpec allows you to write controller, views, helpers and model tests in isolation.
It also provide capability to write integration tests with selenium (using capybara)
Before we start
few points about testing
1. It's About Design
Test Driven Development is not necessarily about the correctness of the code but more for the betterment of the design. So the software is more maintainable overtime and you can write highly cohesive and loosely coupled classes.
2. Red/Green/Refactor
TDD coding cycle is red/green/refactor. Which means make sure your test fails first (i.e. red), then you see your test passing (green) and then refactor your code (refactor)
Don't try to refactor too much before you seeing a passing green test
3. Test the Interface NOT Implementation
Test in a way that when internal implementation of your code changes or things your test doesn't care changes then test still passes. Otherwise after every refactor you do, your tests will start getting unnecessary failures and making refactor a big pain.
Who wants to fix 300 failures for a minor refactor
4. Test only One thing iN iSOlation
While you are testing you will tempted to have multiple assertions within the same test. Resist it :)
This allows you to make sure your tests are atomic and helps you in refactoring. You see the failed test, you know exactly which assertion your code is failing on.
5. Force Yourself to write TEST First
Start with writing test first, its really difficult initially and many times you will fail and go back to coding and then write test after.
But always try to start with writing test first and then if it doesn't work out then move forward and start writing code and then test.
Tools We are going To USE
- RSpec
- Factory Girl
- Capybara
- Spork
Running Rspec
Running Rspec With Spork
This will start the spork server
On a separate console window
Rspec Example Groups and Examples
-
Example Groups (Test Groups): Describe and Context
- Examples (Test Cases) : it
describe HoldsController do
describe "GET #place_hold"
context 'user logged in'
it 'should render to index'
........
end
end
context 'user not logged in'
end
end
end
RSPEC Matchers (assertions)
- expect(...).to be_* (where * is anything which responds to boolean result like be_blank, be_nil
- expect(...).to eq(*)
expect(actual).to be > expected
expect(actual).to be >= expected
expect(actual).to be <= expected
expect(actual).to be < expected
expect(actual).to match(/expression/)
expect(actual).to be_within(delta).of(expected)
expect(actual).to be(expected)
RSPEC Hooks
Hooks are similar to filters in rails they run before each or all the tests
# Order of hooks
before suite
before all
before each
after each
after all
after suite
Spec Helper
This file does the loading of the rails, factories, source files and spec support files. This is also in our case initializes the global variables for our app like @app, @library and @resource
**Let's take a look**
Testing Controllers
- was the web request successful?
- was the user redirected to the right page?
- was the user successfully authenticated?
- was the correct object stored in
the response template?
-
was the appropriate message displayed to
the user in the view?
TESTING Views
There is a very little info on view specs because generally Rails developers don't write view specs. They rely on integration tests or controller tests to render views.
But in our case, isolated view tests can be very useful since our views have lot of logic, secondly integration test is very difficult because of the legacy system.
TESTING Helpers & Presenters
Testing helpers and presenters are much easier then controller and views since they are very isolated.
You will notice an issue while testing helpers is that we don't pass global variables to our helpers but just expect that to be there and that is a problem we should fix wherever we can.
Summary
- Follow the red/green/refactor cycle
- Testing is hard and it's bit harder with our legacy system but you will see the payoffs very soon when you are changing your code.
- Write isolated test so that we don't break those tests when refactor the implementation of the code and the interface returns the same result.
- Use factory girl and double to mock our calls to java app.
-
Please go over the docs for rspec and rspec-rails those are the best places to get answers.