Webアプリケーションをテスト駆動開発するには
TDDならモックの出番はない?
いつものように思いつきエントリなので、眉にツバをキュッキュとつけてお読みいただければ幸いです。
「Pinto公開に向けて #18 ― RSpecのモックを使ってみた」では、Rackエントリポイントの実装と、そのテストコードを考えました。
で、あとから気づいたのが、これってTDD(あるいはBDD)じゃないんですよね。テストを先に書いていないので当たり前ですが。
ともあれ、モックだのスタブだのを気にする時点で、内部実装に依存したテストコードになっているわけです。それで良いのか、という問題意識が、私の中で鎌首をシャーともたげてきました。シャー。
TDDが唯一の正解ではないと思うものの、開発手法として魅力的なのは確かです。できればPintoはTDDで作ってみたい。
どうしたらWebアプリケーションをTDDで開発できるのか
そこで、どうしたらWebアプリケーションをTDDで開発できるのか考えてみました。といっても答えは単純で、あるHTTPリクエストについて仕様通りのHTTPレスポンスが返る、というテストコードをたくさん書き、実装し、リファクタリングしていけばよいのではないでしょうか。
テストコードはこんな感じです。
$LOAD_PATH << 'lib' require 'pinto' require 'rubygems' require 'hpricot' require 'rack' describe "Pinto::RackServer#call with env for 'GET http://pinto.jp/'" do before do @env = Rack::MockRequest.env_for('http://pinto.jp/') end it 'should return 300 Multiple Choices' do response = Pinto::RackServer.new.call(@env) response[0].should == 300 end it 'should return XHTML written in XML 1.0 and UTF-8' do response = Pinto::RackServer.new.call(@env) response[1]['Content-Type'].should == 'application/xhtml+xml; charset=UTF-8' Hpricot(response[2]).each_child do |elm| next unless elm.xmldecl? elm.to_s.should == '<?xml version="1.0" encoding="UTF-8"?>' end end end
で、最低限の実装はこんな感じ。
module Pinto class RackServer def call(env) [ 300, { 'Content-Type' => 'application/xhtml+xml; charset=UTF-8', 'Content-Language' => 'en' }, <<END <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Pinto</title> </head> <body> </body> </html> END ] end end end
こんなもの、Webアプリケーションでもなんでもないですが、テストとして書かれた仕様は完全に満たしています。TDDですよね。
あとは仕様をどんどん追加し、実装し、リファクタリングしていけばよいわけです。しばらく、この方法を試してみようと思っています。