open up terminal and create a new Rails project, simple_test:
$ rails new simple_test --skip-test-unit
$ cd simple_test
option --skip-test-unit, tells Rails not to generate a test directory associated with Test::Unit framework. this is because we want to use another testing framework named RSpec to write our tests.
then we need to include RSpec Gem in 'Gemfile' in your project root directory
group :development, :test do
gem 'sqlite3', '1.3.8'
gem 'rspec-rails', '2.13.1'
end
group :test do
gem 'selenium-webdriver', '2.35.1'
gem 'capybara', '2.1.0'
end
This includes rspec-rails in a development environment so that we have access to RSpec-specific generators, and it includes it in test mode in order to run the tests. We don’t have to install RSpec itself because it is a dependency of rspec-rails and will thus be installed automatically. We also include the Capybara gem, which allows us to simulate a user’s interaction with the sample application using a natural English-like syntax, together with Selenium, one of Capybara’s dependencies.
$ bundle install
it might be better to update the gems with bundle update to make sure the versions match, and then run bundle install to make sure the Gemfile.lock file is fully up-to-date.
Next, we need to configure Rails to use RSpec in place of Test::Unit.
$rails generate rspec:install
you should see:
create .rspec
create spec
create spec/spec_helper.rb
if you're using sublimeText, you can open the entire project by navigating to your project directory and then
$ subl .
or any other editor.
ok, now we set to start developing. since we're following MVC pattern here, I jut give an short overview about that. model is your data access layer. view is your presentation layer, and controller is your business logic layer. business layer i.e. controllers, are between those 2 other layers.
it means, if some data needs to be shown by presentation layer, i.e. views, it can't access the model (data access layer, or database side) by itself. it needs to go through the business layer i.e. controllers.
now if you opened the entire project in your editor, and then go into 'app' folder in project root directory you'll see folders related to these layers, models, views, controller. there are some convention here which makes the development easier, which you can search it for yourself.
now lets make a controller:
rails generate controller StaticPages home help --no-test-framework
--no-test-framework option suppresses the generation of the default RSpec tests, which we won’t be using. Instead, we’ll create the tests by hand. this will generates a controller, StaticPages, with 2 action methods : home and help, which both represent 2 pages(look into app/view/static_pages). now, since i just want to show how TDD works, i don't go into details on how writing tests for the existing code. instead suppose i want to add another page, About.
In test-driven development, we first write a failing test, represented in many testing tools by the color red. We then implement code to get the test to pass, represented by the color green. Finally, if necessary, we refactor the code, changing its form (by eliminating duplication, for example) without changing its function. This cycle is known as “Red, Green, Refactor”.
because here, i'll do integration testing we need to run following command:
$ rails generate integration_test static_pages
invoke rspec
create spec/requests/static_pages_spec.rb
This creates the static_pages_spec.rb in the spec/requests directory. As with most generated code to use the Capybara you need to add the following line in spec/spec_helper.rb
.
.
.
RSpec.configure do |config|
.
.
.
config.include Capybara::DSL
end
checkpoint: now we have a controller, static_pages_controller, it has 2 action methods, home, help and we want to add another one, about. we have RSpec installed, and we execute the rails generate integration_test static_pages, which generated spec/requests/static_pages_spec.rb for us. we put our test inside that file.
Actual TDD
We’ll start the testing cycle by writing a failing test for the About page.
in spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "Static pages" do
describe "About page" do
it "should have the content 'About Us'" do
visit '/static_pages/about'
expect(page).to have_content('About Us')
end
end
end
if you run the RSpec using
$ bundle exec rspec spec/requests/static_pages_spec.rb
the output is very informative. it includes:
No route matches [GET] "/static_pages/about"
this means we need to add /static_pages/about to routes file in config/routes.rb
get "static_pages/about"
now running the test again
$ bundle exec rspec spec/requests/static_pages_spec.rb
complains that
The action 'about' could not be found for StaticPagesController
go to app/controllers/static_pages_controller.rb and add action for about, same as home and help actions
def about
end
now running the test again
$ bundle exec rspec spec/requests/static_pages_spec.rb
says that we are missing a “template”, i.e., a view:
Missing template static_pages/about
To solve this issue, we add the about view. This involves creating a new file called about.html.erb in the app/views/static_pages directory with following content:
<h1>About Us </h1>
Running the test again$ bundle exec rspec spec/requests/static_pages_spec.rb
it should show us the green.
to see the page you created, run the rails server in terminal:
$rails server
then in your browser navigate to
0.0.0.0:3000/static_pages/about
and you should see the about view you created.
now suppose we want to write test to check the page title. we want the "About page" has the title "About Us". we write the test first:
it "should have the title 'About Us'" do
visit '/static_pages/about'
expect(page).to have_title("About Us")
end
if you run the test
$ bundle exec rspec spec/requests/static_pages_spec.rb
it should fail
expected #has_title?("About Us")
The test uses the *have_title* method, which checks for an HTML title with the given content. In other words, the code
expect(page).to have_title("About Us")
to pass the test you just need to change the title of about page to "Abut Us" in its relevant view file in app/views folder, which is easy
some side notes:
these tests are technically integration tests, however writing unit tests are similar. you just test the data based on your model, for example for invalid data, or password length. etc.
- I tried to be more detailed and descriptive, sorry if that's so long.
- all the steps have been tested on Kubuntu 14.04
- this was adopted mostly from http://www.railstutorial.org/
- if you see any errors, leave a comment please
No comments:
Post a Comment