やること
- 静的ページを作成
-
Capybara
を使って結合テスト
準備
- Railsプロジェクトの作成
$ cd rails_projects/
# --skip-test-unitでtestディレクトリを作成しない
# 別途rspecでテストを記載する
$ rails new sample_app --skip-test-unit
$ cd sample_app/
$ vim Gemfile
- Gemfileの編集
source 'https://rubygems.org'
ruby '2.0.0'
gem 'rails', '4.0.4'
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
gem 'sass-rails', '4.0.2'
gem 'uglifier', '2.1.1'
gem 'coffee-rails', '4.0.1'
gem 'jquery-rails', '3.0.4'
gem 'turbolinks', '1.1.1'
gem 'jbuilder', '1.0.2'
group :doc do
gem 'sdoc', '0.3.20', require: false
end
# Heroku用の設定
group :production do
gem 'pg', '0.15.1'
gem 'rails_12factor', '0.0.2'
end
-
gem
のインストール
$ bundle install --without production
$ bundle update
$ bundle install
- セッション変数の暗号化に使用するための、秘密トークンの設定
-
.gitignore
で.secret
をリポジトリで公開しないようにする
-
config/initializers/secret_token.rb
require 'securerandom'
def secure_token
token_file = Rails.root.join('.secret')
if File.exist?(token_file)
# 既に.secretファイルが存在している場合はそのまま使用
File.read(token_file).chomp
else
# 動的にトークンを生成
token = SecureRandom.hex(64)
File.write(token_file, token)
token
end
end
SampleApp::Application.config.secret_key_base = secure_token
- テストで使用するツールの変更
-
Test::Unit
の代わりにRspec
を使用
-
# .rspecファイルとspecディレクトリ、spec/spec_helper.rbが作成される
$ rails generate rspec:install
- リポジトリの初期化
$ git init
$ git add .
$ git commit -m "Initial commit"
- READMEの変更
- 変更内容は割愛
- READMEファイルをMarkdown形式に変更してコミット
$ git mv README.{rdoc,md}
$ git commit -am "Improve the README"
- サンプルアプリケーションをGitHubにpush
- 事前にGitHub上にリポジトリ作成しておく
$ git remote add origin https://asam-3@github.com/ASAM-3/sample_app.git
$ git push -u origin master
- Herokuにデプロイ
$ heroku create
$ git push heroku master
$ heroku run rake db:migrate
- Herokuのデプロイに失敗した時の対応
- ログの確認
- プリコンパイルしてからpush
# ログの確認
$ heroku logs
# プリコンパイルしてからpush
$ rake assets:precompile
$ git add .
$ git commit -m "Add precompiled assets for Heroku"
$ git push heroku master
- 定期的なGitHubへのpushやHerokuへのデプロイをすべき
$ git push
$ git push heroku
$ heroku run rake db:migrate
静的ページ
- トピックブランチの作成
$ git checkout -b static-pages
- StaticPagesコントローラの作成
-
home
とhelp
というアクションを作成 - 今回は
rspec
のテストをしないため、--no-test-framework
オプションをつける
-
$ 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
# なお、下記コマンドでもstatic_pages_controller.rbを作成できる
# キャメル記法→スネークケースに変換される
$ rails generate controller static_pages
# 自動生成を取り消ししたい場合はrails destroyを使う
$ rails destroy controller StaticPages
- 自動生成されたRailsルータの確認
-
home
アクションとhelp
アクションのルーティングが記載されている -
get
はGETリクエストを表す -
/static_pages/home
、/static_pages/help
でそれぞれアクセスできる
-
config/routes.rb
SampleApp::Application.routes.draw do
get "static_pages/home"
get "static_pages/help"
end
-
自動生成されたコントローラ
- 生成時に指定した
home
アクションとhelp
アクションが生成されている -
REST
ではない - 静的なページを扱う場合には向いている
- 生成時に指定した
-
REST
(REpresentational State Transfer)- インターネットやWebアプリケーションなどの、分散/ネットワーク化されたシステムやアプリケーションを構築するためのアーキテクチャの一つ
- Railsアプリにおいては、アプリケーションを構成するコンポーネントをリソースとしてモデル化すること
- その2で言うところの
user
やmicropost
- その2で言うところの
-
RESTfulなスタイルを採用することで得られるメリット
- 作成すべきコントローラやアクションの決定が容易になる
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
end
def help
end
end
-
home
メソッドとhelp
メソッド- 実装が空だが、Railsの場合は
ApplicationController
クラスを継承しているので、Rails特有の振る舞いをする -
/static_pages/home
にアクセスした場合の振る舞い-
home
メソッドに記述されているコードを実行 - アクションに対応するビューを出力
/app/views/static_pages/home.html.erb
-
- 実装が空だが、Railsの場合は
-
自動生成されたビュー
app/views/static_pages/home.html.erb
<h1>StaticPages#help</h1>
<p>Find me in app/views/static_pages/help.html.erb</p>
- ここまででコミット
$ git add .
$ git commit -m "Add a StaticPages controller"
テスト
-
振舞い駆動開発(Behavior-Driven Development, BDD)
- アプリケーションの振舞いをテストしながら実装
-
結合テスト
- ユーザがアプリケーションを使う際の一連のアクションをシミュレーション
- アプリケーションの各ページが正常に動作するかテスト
- 結合テストのためのツール
Capybara
Cucumber
-
テスト駆動開発(TDD)
- アプリケーションを開発する際に最初にテストを作成し、次にコードを作成
テスト駆動開発
-
テスト駆動開発の用語
-
Red
:失敗するテスト -
Green
:テストにパスするコード - リファクタリング:動作を変えずにコードを改善、冗長なコードの削除
-
-
上記の順に開発を行っていく
- このサイクルのことを
Red/Green/Refactor
という
- このサイクルのことを
-
結合テストの生成
$ rails generate integration_test static_pages
invoke rspec
create spec/requests/static_pages_spec.rb
- テストコードの記述
-
describe
- テストの説明を引数として渡す
-
visit
-
Capybara
のvisit
機能を使い、ブラウザでの/static_pages/home
へのアクセスをシミュレート
-
-
expect
-
Capybara
が提供するpage
変数を使用 -
have_content
の引数がコンテンツに含まれているかをテスト
-
-
spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "StaticPages" 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
-
spec/spec_helper.rb
の変更-
Capybara DSL
をRSpec
ヘルパーファイルに追加
-
spec/spec_helper.rb
RSpec.configure do |config|
config.include Capybara::DSL
end
- テストの実行
- 現時点ではエラーになる
$ bundle exec rspec spec/requests/static_pages_spec.rb
F
Failures:
1) StaticPages 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:7:in `block (3 levels) in <top (required)>'
Finished in 0.68511 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/requests/static_pages_spec.rb:5 # StaticPages Home page should have the content 'Sample App'
Randomized with seed 27019
-
home.html.erb
を修正- 本文の中に
Sample App
という文言を追加
- 本文の中に
app/views/static_pages/home.html.erb
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</p>
- テストを再実行
- 今度は成功
$ bundle exec rspec spec/requests/static_pages_spec.rb
.
Finished in 0.10047 seconds
1 example, 0 failures
Randomized with seed 39422
- Helpページのテストコードを追加
spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "StaticPages" 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
# ここから追加
describe "Help page" do
it "should have the content 'Help'" do
visit '/static_pages/help'
expect(page).to have_content('Help')
end
end
# ここまで追加
end
- テストを実行
-
Help
部分がエラー
-
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
F.
-
help.html.erb
を修正- 本文に
Help
を追加
- 本文に
app/views/static_pages/help.html.erb
<h1>Help</h1>
<p>
Get help on the Ruby on Rails Tutorial at the
<a href="http://railstutorial.jp/help">Rails Tutorial help page</a>.
To get help on this sample app. see the
<a href="http://railstutorial.jp/book">Rails Tutorial book</a>.
</p>
- 再度テストを実施
- 今度は成功
$ bundle exec rspec spec/requests/static_pages_spec.rb
..
ページの追加
* Aboutページを作成
* まずはテストコードを記載
* そしてテスト実行
* about
へのルートが設定されていないためエラー
spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "StaticPages" 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
describe "Help page" do
it "should have the content 'Help'" do
visit '/static_pages/help'
expect(page).to have_content('Help')
end
end
# ここから追加
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
テスト実行(ルートがないためエラー)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
F..
Failures:
1) StaticPages 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:20:in `block (3 levels) in <top (required)>'
-
routes
ファイルに/static_pages/about
へのルートを追加してテスト-
StaticPagesController
にabout
アクションがないためエラー
-
config/routes.rb
SampleApp::Application.routes.draw do
get "static_pages/home"
get "static_pages/help"
## ここから追加
get "static_pages/about"
## ここまで追加
end
テスト実行(aboutアクションが存在しないためエラー)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
..F
Failures:
1) StaticPages 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:20:in `block (3 levels) in <top (required)>'
-
StaticPagesController
にabout
アクションを追加- ビューなどのテンプレートが見つからない
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
end
def help
end
# ここから追加
def about
end
# ここまで追加
end
テスト実行(ビューなどのテンプレートが見つからないためエラー)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
F..
Failures:
1) StaticPages 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/asam-3/rails_projects/sample_app/app/views"
# ./spec/requests/static_pages_spec.rb:20:in `block (3 levels) in <top (required)>'
-
about
ビューを追加- テスト成功
app/views/static_pages/about.html.erb
<h1>About Us</h1>
<p>
The <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
is a project to make a book and screencasts to teach web development
with <a href="http://rubyonrails.org/">Ruby on Rails</a>. This
is the sample application for the tutorial.
</p>
テスト実施(成功)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
...
Finished in 0.13243 seconds
3 examples, 0 failures
- リファクタリング
- この時点では特になし
新規ページ追加時の手順
- 新規ページのテストコード追加
-
config/routes
にルーティングを追加 - コントローラにアクションを追加
- ビューを追加
動的なページ
-
タイトル変更のテスト
- ページ毎に異なるタイトルが表示されるように変更
-
作業手順
- タイトルのテストを作成
- タイトルを追加
- レイアウトファイルを使ったリファクタリングと重複の削除を実施
-
レイアウトファイルのリネーム
- 後でレイアウトファイルの役割を確認するため、一旦無効にする
レイアウトファイルのりネーム
$ mv app/views/layouts/application.html.erb{,_bk}
- タイトルは下記のように設定
URL | タイトル |
---|---|
/static_pages/home | Ruby on Rails Tutorial Sample App - Home |
/static_pages/help | Ruby on Rails Tutorial Sample App - Help |
/static_pages/about | Ruby on Rails Tutorial Sample App - About Us |
- テストコードの記載とテスト実行
- もちろんエラーになる
spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "StaticPages" 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
# ここから追加
it "should have the title 'Home'" do
visit '/static_pages/home'
expect(page).to have_title("Home")
end
# ここまで追加
end
describe "Help page" do
it "should have the content 'Help'" do
visit '/static_pages/help'
expect(page).to have_content('Help')
end
# ここから追加
it "should have the title 'Help'" do
visit '/static_pages/help'
expect(page).to have_title("Help")
end
# ここまで追加
end
describe "About page" do
it "should have the content 'About Us'" do
visit '/static_pages/about'
expect(page).to have_content('About Us')
end
# ここから追加
it "should have the title 'About'" do
visit '/static_pages/about'
expect(page).to have_title("About")
end
# ここまで追加
end
end
テスト実施(タイトル部分がエラー)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
.F.F.F
- 各ビューにタイトルを追加
- テスト成功
- ただ、同じようなコードが繰り返されているため、保守性が低い
app/views/static_pages/home.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App - Home</title>
</head>
<body>
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</p>
</body>
</html>
app/views/static_pages/help.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App - Help</title>
</head>
<body>
<h1>Help</h1>
<p>
Get help on the Ruby on Rails Tutorial at the
<a href="http://railstutorial.jp/help">Rails Tutorial help page</a>.
To get help on this sample app. see the
<a href="http://railstutorial.jp/book">Rails Tutorial book</a>.
</p>
</body>
</html>
app/views/static_pages/about.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App - About Us</title>
</head>
<body>
<h1>About Us</h1>
<p>
The <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
is a project to make a book and screencasts to teach web development
with <a href="http://rubyonrails.org/">Ruby on Rails</a>. This
is the sample application for the tutorial.
</p>
</body>
</html>
テスト実施(成功)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
......
Finished in 0.08417 seconds
6 examples, 0 failures
-
リファクタリング
- ページのタイトルがほぼ同じ
-
Ruby on Rails Tutorial Sample App
が3つのタイトルで共通している - HTMLの構造全体が各ページで重複している
-
DRY(
Don't Repeat Yourself
)に反している -
埋め込みRubyの利用
- Railsの
provide
関数を使用して、タイトルをページ毎に変更 -
ERb
はWebページに動的な要素を加えるときに使うテンプレートシステム
- Railsの
-
まずは
home.html.erb
だけ変更- 変更後にテストを実施して成功することを確認
app/views/static_pages/home.html.erb
<% provide(:title, 'Home') %>
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App - <%= yield(:title) %></title>
</head>
<body>
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</p>
</body>
</html>
-
provide
関数-
:title
というラベルに'Home'という文字列を関連付ける
-
-
yield
関数- テンプレートにタイトルを挿入
テスト実行(成功)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
......
Finished in 0.08411 seconds
6 examples, 0 failures
-
help
、about
も同じような感じで記述できる - 各ERbファイルの構成は下記のとおり
-
html
、head
の構成は全て共通 -
body
の中身だけ異なる
-
<% provide(:title, 'タイトル') %>
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App - <%= yield(:title) %></title>
</head>
<body>
中身
</body>
</html>
- レイアウトファイルの変更
- 元のファイルからタイトル部分だけ変更
レイアウトファイルのリネーム
$ mv app/views/layouts/application.html.erb{_bk,}
-
<% yield %>
- 各ページの内容をレイアウトに挿入
-
/static_pages/home
にアクセスすると、home.html.erb
の内容がHTMLに変換され、<%= yield %>
の位置に挿入される
-
<%= stylesheet_link_tag ... %>
- スタイルシートをインクルード
-
Asset Pipeline
の一部
-
<%= javascript_include_tag "application", ... %>
- JavaScriptをインクルード
-
Asset Pipeline
の一部
-
<%= csrf_meta_tags %>
- クロスサイトリクエストフォージェリを防ぐために使用する
Rails
のメソッド
- クロスサイトリクエストフォージェリを防ぐために使用する
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails Tutorial Sample App - <%= yield(:title) %></title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
- 各種ビューをレイアウトを利用した形に変更
- リファクタリング後にテスト実施
app/views/static_pages/home.html.erb
<% provide(:title, 'Home') %>
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</p>
app/views/static_pages/help.html.erb
<% provide(:title, 'Help') %>
<h1>Help</h1>
<p>
Get help on the Ruby on Rails Tutorial at the
<a href="http://railstutorial.jp/help">Rails Tutorial help page</a>.
To get help on this sample app. see the
<a href="http://railstutorial.jp/book">Rails Tutorial book</a>.
</p>
app/views/static_pages/about.html.erb
<% provide(:title, 'About Us') %>
<h1>About Us</h1>
<p>
The <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
is a project to make a book and screencasts to teach web development
with <a href="http://rubyonrails.org/">Ruby on Rails</a>. This
is the sample application for the tutorial.
</p>
テスト実行(成功)
$ bundle exec rspec spec/requests/static_pag
es_spec.rb
......
Finished in 0.16055 seconds
6 examples, 0 failures
コミットとpush
- コミット
-
master
ブランチとマージ - GitHubにアップロード
- herokuにアップロード
$ git add .
$ git commit -m "Finish static pages"
$ git checkout master
$ git merge static-pages
$ git push
$ git push heroku
演習
Contactページを作成
- テストコード作成
-
config/routes.rb'に
contact`のルーティングを追加 -
static_pages_controller.rb
にcontact
アクションを追加 -
contact.html.erb
を追加
spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "StaticPages" do
describe "Contact page" do
it "should have the content 'Contact'" do
visit '/static_pages/contact'
expect(page).to have_content('Contact')
end
it "should have the title 'Contact'" do
visit '/static_pages/contact'
expect(page).to have_title("Contact")
end
end
end
config/routes.rb
SampleApp::Application.routes.draw do
get "static_pages/home"
get "static_pages/help"
get "static_pages/about"
get "static_pages/contact"
end
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
end
def help
end
def about
end
def contact
end
end
app/views/static_pages/contact.html.erb
<% provide(:title, 'Contact') %>
<h1>Contact</h1>
<p>
Contact Ruby on Rails Tutorial about the sample app at the
<a href="http://railstutorial.jp/contact">contact page</a>.
</p>
specテストの重複部分をlet
を使ってまとめる
- タイトルの文字列全体をテストするように変更
-
let
で共通部分を定義 - テスト部分で文字列連結してテスト
-
spec/requests/static_pages_spec.rb
require 'spec_helper'
describe "StaticPages" do
let(:base_title) { "Ruby on Rails Tutorial Sample App" }
describe "Home page" do
it "should have the content 'Sample App'" do
visit '/static_pages/home'
expect(page).to have_content('Sample App')
end
it "should have the title 'Home'" do
visit '/static_pages/home'
expect(page).to have_title("#{base_title} - Home")
end
end
# 中略
end
その他のセットアップ
bundle exec
を使わない
-
bundle exec
- 現在の環境に依存するgemをGemfileから読み込んでプログラムを実行するために指定が必要
-
RVM
を使用している場合、RVMを最新化することにより、インストールされたgemが自動的に適切なBundlerの環境で実行される(1.11.x以降)
-
rake
やrspec
を実行する際に指定していたが、今後は使わない
rvmの最新化
$ rvm get stable
$ rvm -v
rspecの実行
$ rspec spec/
Guard
によるテストの自動化
-
Guard
- テストを自動化する
gem
- ファイルシステムの変更を監視し、ファイルが変更されると自動実行するようにできる
- specファイル:
*_spec.rb
- viewファイル:
*.html.erb
など
- specファイル:
- テストを自動化する
-
Guard
のセットアップ-
Gemfile
にguard-rspec
を追加 - gemのインストール
-
Guard
の初期化 -
Guardfile
の編集
-
Gemfile
# 変更箇所の抜粋
group :development, :test do
gem 'sqlite3', '1.3.8'
gem 'rspec-rails', '2.13.1'
# ここから追加
gem 'guard-rspec', '2.5.0'
# ここまで追加
end
gemのインストール、Guardの初期化
$ bundle install
# Guardfileが生成される
$ bundle exec guard init rspec
-
guard 'rspec', all_after_pass: false do
- 失敗したテストがある場合は以降のテストを実施しない
Guardfile(追加・変更点のみ)
require 'active_support/inflector'
guard 'rspec', all_after_pass: false do
# 中略
# Custom Rails Tutorial specs
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) do |m|
["spec/routing/#{m[1]}_routing_spec.rb",
"spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb",
"spec/acceptance/#{m[1]}_spec.rb",
(m[1][/_pages/] ? "spec/requests/#{m[1]}_spec.rb" :
"spec/requests/#{m[1].singularize}_pages_spec.rb")]
end
watch(%r{^app/views/(.+)/}) do |m|
(m[1][/_pages/] ? "spec/requests/#{m[1]}_spec.rb" :
"spec/requests/#{m[1].singularize}_pages_spec.rb")
end
watch(%r{^app/controllers/sessions_controller\.rb$}) do |m|
"spec/requests/authentication_pages_spec.rb"
end
end
Sporkを使ったテストの高速化
-
rspec
はテスト開始までに時間がかかってしまう-
rspec
を実行するたびにRailsの環境全体を読み込みなおす必要があるため
-
-
Spork
テストサーバ- 環境を1回だけ読み込み、今後実行するテストのためのプロセスを管理する
-
Spork
のセットアップ手順- Gemfileに
Spork
を追加 -
gem
のインストール -
Spork
の設定にbootstrap
を指定 -
RSpec
の設定を変更- 環境の読み込みを1回で済ますため、
spec/spec_helper.rb
の中で環境をprefork
のブロックで読み込むようにする
- 環境の読み込みを1回で済ますため、
- テストスイートを実行し、基準となる実行時間を測定
-
Spork
サーバを起動 -
.rspec
の設定を変更
- Gemfileに
Gemfile(変更箇所のみ抜粋)
group :development, :test do
gem 'sqlite3', '1.3.8'
gem 'rspec-rails', '2.13.1'
gem 'guard-rspec', '2.5.0'
gem 'spork-rails', '4.0.0'
gem 'guard-spork', '1.5.0'
gem 'childprocess', '0.3.6'
end
gemのインストール
$ bundle install
$ bundle update
Sporkの設定にbootstrapを指定
$ bundle exec spork --bootstrap
spec/spec_helper.rb(環境をpreforkのブロックで読み込む)
require 'rubygems'
require 'spork'
Spork.prefork do
# 既存のコードをカット&ペースト
ENV["RAILS_ENV"] ||= 'test'
# 中略
config.include Capybara::DSL
end
end
Spork.each_run do
# This code will be run each time you run your specs.
end
rspecの実行時間を計測
$ time bundle exec rspec spec/requests/static_pages_spec.rb
........
Finished in 0.19846 seconds
8 examples, 0 failures
Randomized with seed 25711
real 0m4.395s # テストスイートの時間
user 0m3.818s
sys 0m0.517s # テストの実行時間
別ターミナルでSporkサーバを起動
$ cd rails_projects/sample_app/
$ bundle exec spork
Using RSpec, Rails
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!
--drbオプションをつけてrspecの実行時間を計測
$ time bundle exec rspec spec/requests/static_pages_spec.rb --drb
........
Finished in 0.32188 seconds
8 examples, 0 failures
Randomized with seed 8842
real 0m1.633s
user 0m1.037s
sys 0m0.104s
--drbオプションを明示的に指定しないように、.rspecに設定を追加
$ sed -i -e '/--drb/d' .rspec
$ echo "--drb" >> .rspec
# --drbなしでも高速で終了
$ time bundle exec rspec spec/requests/static_pages_spec.rb
........
Finished in 0.20508 seconds
8 examples, 0 failures
Randomized with seed 8842
real 0m1.218s
user 0m0.786s
sys 0m0.085s
GuardにSporkを導入
SporkとGuardを併用
$ bundle exec guard init spork
16:23:28 - INFO - spork guard added to Guardfile, feel free to edit it
-
bundle exec guard init spork
を実行すると、Guardfile
に設定が追加される -
guard
に--drb
の設定を追加-
rspec
が高速化
-
Guardfile
# 自動生成された部分
guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
watch('config/application.rb')
watch('config/environment.rb')
watch('config/environments/test.rb')
watch(%r{^config/initializers/.+\.rb$})
watch('Gemfile')
watch('Gemfile.lock')
watch('spec/spec_helper.rb') { :rspec }
watch('test/test_helper.rb') { :test_unit }
watch(%r{features/support/}) { :cucumber }
end
# cli: '--drb'を追加
guard 'rspec', all_after_pass: false, cli: '--drb' do
...
end
GuardとSporkを同時に起動
$ bundle exec guard