前回のチュートリアルの続き。
Learn Web Development with the Ruby on Rails Tutorial | A Demo App の 3.1, 3.2 をやっていく。
静的なページの作成
静的なページを扱うためのコントローラを作成する。
$ bundle exec rails generate controller StaticPages home help --no-test-framework
create app/controllers/static_pages_controller.rb
route get "static_pages/help"
route get "static_pages/home"
invoke erb
create app/views/static_pages
create app/views/static_pages/home.html.erb
create app/views/static_pages/help.html.erb
invoke helper
create app/helpers/static_pages_helper.rb
invoke assets
invoke coffee
create app/assets/javascripts/static_pages.js.coffee
invoke scss
create app/assets/stylesheets/static_pages.css.scss
--no-test-framework を指定したのはこの後自分でテスト行う為?
ちなみに generate controller したものは destroy controller で削除できる。
$ bundle exec rails destroy controller StaticPages index help
controller を追加したら config/routes.rb に以下のように変更がある。
DemoApp::Application.routes.draw do
get "static_pages/home"
get "static_pages/help"
...
end
static_pages/home にアクセスしたら以下のように表示されるはず。
app/controller/static_pages_controller.rb は以下のようになっている。
class StaticPagesController < ApplicationController
def home
end
def help
end
end
空のメソッドは一件何もしないように見えるが、このクラスは Rails が提供する ApplicationController を継承している為、Rails として動作する。ユーザが /static_pages/home にアクセスした際に Rails は StaticPages コントローラの home メソッドを実行し、View ( MVC の V ) を表示する。
Rails コマンドによって作成された View は app/views/static_pages/home.html.erb にある
<h1>StaticPages#home</h1>
<p>Find me in app/views/static_pages/home.html.erb</p>
Test driven development
テスト駆動開発 (てすとくどうかいはつ、test-driven development; TDD) とは、プログラム開発手法の一種で、プログラムに必要な各機能について、最初にテストを書き(これをテストファーストと言う)、そのテストが動作する必要最低限な実装をとりあえず行った後、コードを洗練させる、という短い工程を繰り返すスタイルである。
というわけで Rails でもやってみる。
Gemfile を書き換える
Gemfile を書き換えて test で使用するパッケージを入れます。ここでは rspec を使用します。
group :development, :test do
gem 'rspec-rails', '2.13.0'
end
group :test do
gem 'selenium-webdriver', '2.0'
gem 'capybara'
end
Gemfile 書き換えたら bundle update します。bundle exec bundle update ってやったら出来なかったので bundle update を先にしたんですけど大丈夫ですかねぇ・・・
$ bundle update
$ bundle exec bundle update
$ bundle exec rails generate rspec:install
create .rspec
exist spec
create spec/spec_helper.rb
rspec 自体は入ったようなのでテストを作ります
$ bundle exec rails generate integration_test static_pages
invoke rspec
create spec/requests/static_pages_spec.rb
spec/requests/static_pages_spec.rb の中は以下のような感じ
require 'spec_helper'
describe "StaticPages" do
describe "GET /static_pages" do
it "works! (now write some real specs)" do
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
get static_pages_index_path
response.status.should be(200)
end
end
end
これを以下のように書き換えます。
require 'spec_helper'
describe "Static pages" do
describe "Home page" do
it "should have the content 'Sample App'" do
visit '/static_pages/home'
expect(page).to have_content('Sample App')
end
end
end
細かい事はわかってないので省略するが、 /static_pages/home にアクセスしたら 'Sample App' という文言がページにある事を期待している、という意味になる。
次に 上記コードにある page を使うために Capybara DSL を RSpec helper ファイルに追加します。
...
RSpec.configure do |config|
...
config.include Capybara::DSL
end
書いたらテストを実行してみよう。
以下のような表記でなく、スタックトレースが出るようなエラーが出た場合は、エラーメッセージをよく見て対応しよう。自分の場合は、'rake db:migrate RAILS_ENV=test' を実行すると良いみたいな文言がエラーと共に表示されたので実行した後以下のようにテストが動いた。
$ bundle exec rspec spec/requests/static_pages_spec.rb
F
Failures:
1) Static pages Home page should have the content 'Sample App'
Failure/Error: expect(page).to have_content('Sample App')
expected #has_content?("Sample App") to return true, got false
# ./spec/requests/static_pages_spec.rb:17:in `block (3 levels) in <top (required)>'
Finished in 0.82028 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/requests/static_pages_spec.rb:15 # Static pages Home page should have the content 'Sample App'
Randomized with seed 18838
無事テストに失敗したのでテストに通る様に app/views/static_pages/home.html.erb を書き換える。
<h1>Sample App</h1>
<p>this is the home page for the Ruby on Rails Tutorial sample application.</p>
そして再度実行する。
$ bundle exec rspec spec/requests/static_pages_spec.rb
.
Finished in 0.15423 seconds
1 example, 0 failures
Randomized with seed 52655
無事テストに通過しました。
help ページについても同じように書く。
TDD でページを追加する
About ページを Static pages に追加します。
まずはテストを書きます。
...
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
そしてテストを実行。
$ bundle exec rspec spec/requests/static_pages_spec.rb
Failures:
1) Static pages About page should have the content 'About Us'
Failure/Error: visit '/static_pages/about'
ActionController::RoutingError:
No route matches [GET] "/static_pages/about"
# ./spec/requests/static_pages_spec.rb:30:in `block (3 levels) in <top (required)>'
もちろん失敗します。
エラーメッセージ内に "No route matches [GET] "/static_pages/about" とあるのでまずはルーティングを設定します。
about ページのルーティングの追加
まずルーティングを修正します。
config/routes.rb を開いて以下のように about を追加します。
DemoApp::Application.routes.draw do<
get "static_pages/home"<
get "static_pages/help"<
get "static_pages/about"<
resources :microposts<
...
再度テストを実行してみます。
$ bundle exec rspec spec/requests/static_pages_spec.rb
Failures:
1) Static pages About page should have the content 'About Us'
Failure/Error: visit '/static_pages/about'
AbstractController::ActionNotFound:
The action 'about' could not be found for StaticPagesController
# ./spec/requests/static_pages_spec.rb:30:in `block (3 levels) in <top (required)>'
こんどは "AbstractController::ActionNotFound" といわれました。なのでアクションを追加します。app/controllers/static_pages_controller.rb を開いて以下のように about を追加します。
class StaticPagesController < ApplicationController
def home
end
def help
end
def about
end
end
そしてまたテストを実行します。
$ bundle exec rspec spec/requests/static_pages_spec.rb
Failures:
1) Static pages About page should have the content 'About Us'
Failure/Error: visit '/static_pages/about'
ActionView::MissingTemplate:
Missing template static_pages/about, application/about with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
* "/home/ryomatsu/public_html/ryomatsu.sillca.com/rortest/demo_app/app/views"
# ./spec/requests/static_pages_spec.rb:30:in `block (3 levels) in <top (required)>'
今度は "Missing template" といわれました。テンプレートを追加します。
テンプレートのファイル名は app/views/static_pages/about.html.erb ですのでこれを新規作成し、以下のようにします。
<h1>About Us</h1>
<p>this is a Ruby on Rails tutorial page</p>
そしてまたテストを実行します。
$ bundle exec rspec spec/requests/static_pages_spec.rb
Finished in 0.17406 seconds
3 examples, 0 failures
Randomized with seed 22802
テストに通過しました。ブラウザで /static_pages/about にアクセスすると作成した About ページが表示されるはずです。