簡単なsinatraアプリを例としたテスト駆動開発の紹介をします。今回作成するsinatraアプリの完成コードは以下です。
require 'sinatra'
get '/' do
'Hello'
end
完成後のすべてのコードは、https://github.com/ppworks/rspec_sample にあります。
それでは、まずはレポジトリをcloneします。
git clone git://github.com/ppworks/rspec_sample.git
ディレクトリを移動して、必要なgemファイルをインストールします。
cd rspec_sample
bundle install --path .bundle
テストが通ることを確認します。
bundle exec rspec
App
レスポンスの精査
/へのアクセス
正常なレスポンスが返ること
Helloと出力されること
Finished in 0.04865 seconds
2 examples, 0 failures
無事にテストが通りましたね。ではここまでに至る作業を見ていきます。各ステップはtagを作成してあるので以下のコマンドでtagが存在を確認して下さい。
git tag -n
tdd_001 テスト駆動開発例テストから書く
tdd_002 テスト駆動開発例テストに沿った実装を書く
tdd_003 テスト駆動開発例テストから書くその2
tdd_004 テスト駆動開発例テストに沿った実装を書くその2
tdd_005 specのリファクタリング
各tagに切り替えた際にコードを確認して見ることが大切です。実際にコードを見るようにして下さい。
テストから書く
まずは最初のtagをcheckoutします。
git checkout tdd_001
次にテストを実行します。
bundle exec rspec
以下のように、テストが失敗します。1 example, 1 failure
は全部で1つのサンプルが存在し、1つが失敗したことを表しています。
App
レスポンスの精査
/へのアクセス
正常なレスポンスが返ること (FAILED - 1)
Failures:
1) App レスポンスの精査 /へのアクセス 正常なレスポンスが返ること
Failure/Error: last_response.should be_ok
expected ok? to return true, got false
# ./spec/app_spec.rb:14:in `block (4 levels) in <top (required)>'
Finished in 0.09747 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/app_spec.rb:13 # App レスポンスの精査 /へのアクセス 正常なレスポンスが返ること
このとき、app.rb
を見てみると何も書いて有りませんね。このようにテスト駆動開発では、このように動いて欲しいという期待を先に記述します。ではこのテストコードを見てみましょう。git diff tdd_001..tdd_002
の実行結果です。
# encoding: utf-8
require File.dirname(__FILE__) + '/spec_helper'
describe "App" do
include Rack::Test::Methods
def app
@app ||= Sinatra::Application
end
describe "レスポンスの精査" do
describe "/へのアクセス" do
before { get '/' }
it "正常なレスポンスが返ること" do
last_response.should be_ok
end
end
end
end
次はこのテストが期待するコードを実装していきます。
テストに沿った実装を書く
次のtagをcheckoutしましょう。
git checkout tdd_002
この状態でテストを実行すると
bundle exec rspec
今度は成功しましたね。
App
レスポンスの精査
/へのアクセス
正常なレスポンスが返ること
Finished in 0.10743 seconds
1 example, 0 failures
どのような処理を書いたのか見てみましょう。
diff --git a/app.rb b/app.rb
index e69de29..920ebe6 100644
--- a/app.rb
+++ b/app.rb
@@ -0,0 +1,4 @@
+require 'sinatra'
+
+get '/' do
+end
実にシンプルですね。このようにテスト駆動開発では、実装から書きたくなりがちなところをテストから書いていきます。
テストから書くその2
もう少しテストを足してみましょう。
git checkout tdd_003
今回足したテストは以下です。git diff tdd_002..tdd_003
の実行結果です。
diff --git a/spec/app_spec.rb b/spec/app_spec.rb
index d849e1e..076f412 100644
--- a/spec/app_spec.rb
+++ b/spec/app_spec.rb
@@ -13,6 +13,9 @@ describe "App" do
it "正常なレスポンスが返ること" do
last_response.should be_ok
end
+ it "Helloと出力されること" do
+ last_response.body.should == "Hello"
+ end
end
end
end
bundle exec rspec
App
レスポンスの精査
/へのアクセス
正常なレスポンスが返ること
Helloと出力されること (FAILED - 1)
Failures:
1) App レスポンスの精査 /へのアクセス Helloと出力されること
Failure/Error: last_response.body.should == "Hello"
expected: "Hello"
got: "" (using ==)
# ./spec/app_spec.rb:17:in `block (4 levels) in <top (required)>'
Finished in 0.11694 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/app_spec.rb:16 # App レスポンスの精査 /へのアクセス Helloと出力されること
テストは通りませんね。では次はこのテストが通る実装をみてみましょう。
テストに沿った実装を書くその2
git checkout tdd_004
今回の差分は以下です。git diff tdd_003..tdd_004
の実行結果です。"Hello"という文字列を返しています。
diff --git a/app.rb b/app.rb
index 920ebe6..0520e2e 100644
--- a/app.rb
+++ b/app.rb
@@ -1,4 +1,5 @@
require 'sinatra'
get '/' do
+ 'Hello'
end
ではテストを実行しています。
bundle exec rpec
App
レスポンスの精査
/へのアクセス
正常なレスポンスが返ること
Helloと出力されること
Finished in 0.04242 seconds
2 examples, 0 failures
無事に通りましたね。次はテストコードのリファクタリングをしてみます。
specのリファクタリング
今回は振る舞いは同じまま、コードの修正を行なってみました。app.rb
のコードが単純なためspec/app_spec
をリファクタリングしています。git diff tdd_004..tdd_005
の実行結果です。
diff --git a/spec/app_spec.rb b/spec/app_spec.rb
index 076f412..1347ef9 100644
--- a/spec/app_spec.rb
+++ b/spec/app_spec.rb
@@ -10,11 +10,12 @@ describe "App" do
describe "レスポンスの精査" do
describe "/へのアクセス" do
before { get '/' }
+ subject { last_response }
it "正常なレスポンスが返ること" do
- last_response.should be_ok
+ should be_ok
end
it "Helloと出力されること" do
- last_response.body.should == "Hello"
+ subject.body.should == "Hello"
end
end
end
現在テストしている主題(subject)を明確にしてみました。同じくテストを実行すると
bundle exec rpec
App
レスポンスの精査
/へのアクセス
正常なレスポンスが返ること
Helloと出力されること
Finished in 0.04653 seconds
2 examples, 0 failures
同じ結果が得られましたね。以上で、sinatraとrspecを使ったテスト駆動開発の体験が出来たと思います。どうでしたでしょうか?