<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ひげろぐ &#187; テスト</title>
	<atom:link href="http://brass.to/blog/tag/%E3%83%86%E3%82%B9%E3%83%88/feed" rel="self" type="application/rss+xml" />
	<link>http://brass.to/blog</link>
	<description>技術者として仕事人としての思うところや覚え書きやらです</description>
	<lastBuildDate>Tue, 07 Sep 2010 16:53:11 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>テスト駆動開発にうまくなじむ方法</title>
		<link>http://brass.to/blog/starting_tdd.html</link>
		<comments>http://brass.to/blog/starting_tdd.html#comments</comments>
		<pubDate>Sat, 29 Mar 2008 14:44:06 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/starting_tdd.html</guid>
		<description><![CDATA[InfoQ: テスト駆動開発導入時のよくある質問
というエントリが日頃考えていることと内容がマッチしていたので興味深く読んだ。
そこからたどって以下のエントリも読んでみた。

The first 2 hours of T [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.infoq.com/jp/news/2008/03/tdd-smells" target="_blank">InfoQ: テスト駆動開発導入時のよくある質問</a></p>
<p>というエントリが日頃考えていることと内容がマッチしていたので興味深く読んだ。<br />
そこからたどって以下のエントリも読んでみた。</p>
<ul>
<li><a href="http://lostechies.com/blogs/chad_myers/archive/2008/02/12/the-first-2-hours-of-tdd-are-the-most-painful.aspx" target="_blank">The first 2 hours of TDD are the most painful &#8211; Chad Myers&#8217; Blog</a></li>
<li><a href="http://avocadosoftware.com/csblogs/dredge/archive/2008/02/13/785.aspx" target="_blank">ThoughtStream.Create(me); : In response to Chad Myers&#8217; TDD questions</a></li>
</ul>
<p>「TDDに関する本やブログを読みあさったけど意味がなかった」「そばによいペアがいればそんなことないんだけど」などといったコメントが印象的。<br />
やっぱり経験者とのペアプロが一番いいんだろうなぁ。百聞は一見にしかずということで。</p>
<p>自分もたまに「テストってどう書いたらいいんでしょう？」みたいな質問をされるのだけど、明確なアドバイスを返せないでいたのでこれを期に考えてみた。</p>
<p>まず経験者が周りにいるならペアプロするか、プログラミングしているところを見せてもらうのが一番いい。</p>
<p>経験者が身近に誰もいない環境で始めるのならば、意味があるのかとか役に立つのかとか考えずテストを書き続けるのがいい。<br />
たぶんテスト駆動開発にチャレンジしてみたけどなじめずやめてしまう人というのは、ちょっと試して効果を実感できないうちに疑問を感じてやめてしまうケースが多いと思われるので。</p>
<p>また何に関してテストを書いたらいいのかわからんと思うけど、とりあえずテストのシンタックスに慣れる意味も兼ねて、シンプルにすべてのメソッドに対してひとつずつテストを書く。<br />
愚直に数ヶ月書き続けることで自然とわかってくることがあるだろう。</p>
<p>わかるまで手を動かすという方法は効率は悪く感じられるかもしれないけど確実ではある。それに実は思ったほど無駄でもないはず。<br />
繰り返しになるけど効率を求めるなら経験者を捕まえていっしょにキーボードの前に座るのがベスト。</p>
<p>座学より実技で。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/starting_tdd.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSpecでモックとスタブ</title>
		<link>http://brass.to/blog/rspec_mock_stub.html</link>
		<comments>http://brass.to/blog/rspec_mock_stub.html#comments</comments>
		<pubDate>Thu, 27 Mar 2008 13:01:23 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rspec_mock_stub.html</guid>
		<description><![CDATA[きちんと理解してなかったのでいろんなページを参考にいじくりまわしてみた。
そのメモ。
モックとはスタブとは
Martin Fowler&#8217;s Bliki in Japanese &#8211; TestDoub [...]]]></description>
			<content:encoded><![CDATA[<p>きちんと理解してなかったのでいろんなページを参考にいじくりまわしてみた。<br />
そのメモ。</p>
<h4>モックとはスタブとは</h4>
<p><a href="http://capsctrl.que.jp/kdmsnr/wiki/bliki/?TestDouble" target="_blank">Martin Fowler&#8217;s Bliki in Japanese &#8211; TestDouble</a>の定義がわかりやすいので引用。</p>
<pre><q>
スタブは、テスト時の呼び出しに対して、あらかじめ用意された結果を返す。
通常、テスト用にプログラムされたところ以外には応答しない。
スタブは呼び出しの情報を記録することもある。
例えば、Eメールゲートウェイスタブは「送られた」メッセージを記録するような場合だ。
単に「送られた」メールの数を記録する場合もあるだろう。
</q></pre>
<p>スタブによってデータベース接続やネットワークIOなどの要素をテストから分離することができる。<br />
また時間のかかる処理をスタブで置き換えることによってテスト時間を短縮することにも使われる。</p>
<pre><q>
モックは、エクスペクテーションが事前にプログラムされたものである。
エクスペクテーションとは、受信する一連の呼び出しの仕様を表わしたものである。
期待されない呼び出しが行なわれた場合は例外をスローする。
また、テスト実行後の検証 (verification)で、期待された呼び出しがすべてきちんと行われたかどうかを確認する。
</q></pre>
<p>Railsで言うと、例えばコントローラのテストではモデルのモックを使ってコントローラがモデルを意図したとおりに使っているのかというところを検証する。<br />
実際のモデルの代わりにモックを渡してコントローラがそれをどう使うかを見るわけだ。<br />
モックは自分がどのように使われるべきかというエクスペクテーション（期待）を持ち、それと実際に自分が受けた扱いを比較して検証を行う。</p>
<p>モックによってモデルがなくてもインタフェースが決まっていればコントローラのテストを書いていけるし、逆にモデルの内部に直接手を突っ込むようなコードが書けないのでお互いの仕事が明確になるという効果もある。</p>
<p>これで理解が難しい場合はコードを書いてみるとわかると思う。コードの書き方については最後にまとめた参考サイトを参照。</p>
<h4>モックとスタブの効能</h4>
<p>モックとスタブを使う利点はいっしょに動作する個々のクラスやオブジェクトを（例えばコントローラとモデルおよびビュー）を完全に分離してテストできるという点だ。<br />
それはお互いの役割をより明確にできて、よりシンプルかつ堅牢な設計にできると言うことでもある。</p>
<p>最初、モックとスタブを使い始めて既存のテストに適用しようとするとうまく組み込めなかった。<br />
コントローラ内でモデルのモックを使おうとすると、エクスペクテーションが複雑になりすぎてどうにもうまくいかない。</p>
<p>これはモデルの中にもっと処理をまとめてインタフェースを単純化することで解決することができた。<br />
結果、コントローラの中身がすっきりして見通しがよくなりメンテナンス性が上がったように思える。</p>
<p>今まではコントローラがモデルに細かくあれこれと口を出して動かしていたのが、今では一言かけるだけでモデルがテキパキと動くようになったみたいな。<br />
「まかせれば人は楽しみ動き出す」ってやつだね。違うな。まあいいや。</p>
<p>とにかくモックやスタブによって自然と設計がよくなると思う。</p>
<h4>モックとスタブの書き場所</h4>
<p>サンプルコードは世にたくさんあるので特にここでは書かないがひとつだけ。<br />
RSpecでモックとスタブを書き始めるときにちょっとだけ悩んだのが、モックとスタブのコードをどこに書くのか？というところ。<br />
そこだけメモっておく。</p>
<p>これはテスト対象の処理の実行の前に書く。<br />
すると処理の中でモックやスタブが使われるというスンポーだ。</p>
<p>そして以下の例ではindexアクションの処理の中で@item.some_methodが呼ばれていればモックのエクスペクテーションをパスする。</p>
<pre><code>it "なにかのテストですよー" do
  # モック
  @item.should_receive(:some_method)

  # テスト対象の処理
  get :index

  # 普通のRSpecのエクスペクテーション
  @items.should be_true
end</code></pre>
<h4>参考サイト</h4>
<ul>
<li><a href="http://rspec.info/documentation/mocks/" target="_blank">RSpec-1.1.3: Mock Objects</a></li>
<li><a href="http://rspec.info/documentation/rails/writing/controllers.html" target="_blank">RSpec-1.1.3: Controllers</a></li>
<li><a href="http://www.ibm.com/developerworks/jp/web/library/wa-mockrails/" target="_blank">Ruby on Rails でのモックとスタブの作成</a></li>
<li><a href="http://capsctrl.que.jp/kdmsnr/wiki/bliki/?TestDouble" target="_blank">Martin Fowler&#8217;s Bliki in Japanese &#8211; TestDouble</a></li>
<li><a href="http://rakuto.blogspot.com/2006/11/rails-rspec-on-rails-behaviour.html" target="_blank">Young risk taker.: [rails] 実践RSpec on Rails &#8211; コントローラとモデルのBehaviourを書く</a></li>
<li><a href="http://www.kaeruspoon.net/articles/275" target="_blank">Rspecでコントローラのspecファイルを書く &#8211; kaeruspoon</a></li>
</ul>
<p>参考サイトを見て実際手を動かすのが理解の早道という気がする。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rspec_mock_stub.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>テストする時フィクスチャのリロード忘れに注意</title>
		<link>http://brass.to/blog/fixture_reload.html</link>
		<comments>http://brass.to/blog/fixture_reload.html#comments</comments>
		<pubDate>Tue, 18 Mar 2008 12:47:06 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/fixture_reload.html</guid>
		<description><![CDATA[Railsのコントローラのテストにおいて、フィクスチャのリロードをしないでテストを進めると期待通りの結果にならず首をかしげることになる。
初心者のハマリがちなところ。
例えば次のようなフィクスチャがあり
first_fe [...]]]></description>
			<content:encoded><![CDATA[<p>Railsのコントローラのテストにおいて、フィクスチャのリロードをしないでテストを進めると期待通りの結果にならず首をかしげることになる。<br />
初心者のハマリがちなところ。</p>
<p>例えば次のようなフィクスチャがあり</p>
<pre><code>first_feed:
  id: 1
  title: hoge</code></pre>
<p>次のような更新のテストを書くと</p>
<pre><code>post :update, :id =&gt; @first_feed.id, :title =&gt; 'hogehoge'

@first_feed.title.should == 'hogehoge'</code></pre>
<p>更新処理（updateアクション）が成功してもこのテストは失敗する。<br />
@first_feed.titleは&#8221;hoge&#8221;のままだからだ。</p>
<p>期待通りの結果にするには次のようにしなくてはならない。</p>
<pre><code>post :update, :id =&gt; @first_feed.id, :title =&gt; 'hogehoge'

@first_feed.reload
@first_feed.title.should == 'hogehoge'</code></pre>
<p>これはなぜかというとデータベースの更新が@first_feedとは別のActiveRecordインスタンスで行われるため。たぶん。</p>
<p>更新処理内で同じレコードを参照する別のActiveRecordのインスタンスが作られてデータベースの更新はそちらで行われる。<br />
他のインスタンスによる変更を既存のインスタンスであるところの@first_feedが知るすべはないので、リロードしてやらなければならないというわけだ。</p>
<p>というわけでフィクスチャの、と言っているが実はフィクスチャ以外でもこの現象は起こる。<br />
でもテスト時は特にフィクスチャでよくやる。</p>
<p>で、初心者のハマリがちなところとか偉そうに行ってる割に自分自身が昨日これで30分くらいはまってたわけだが。</p>
<p>@first_feed.itemsにアクションで変更が発生したときにも@first_feedをリロードしないといけないんだぜ。<br />
あと長時間の連続コーディングもNGなんだぜ。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/fixture_reload.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSpecの violated と pending</title>
		<link>http://brass.to/blog/rspec_violated_and_pending.html</link>
		<comments>http://brass.to/blog/rspec_violated_and_pending.html#comments</comments>
		<pubDate>Sat, 15 Mar 2008 11:53:22 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rspec_violated_and_pending.html</guid>
		<description><![CDATA[RSpecにはテストの実装が不完全であることを表すための二つのメソッドがある。


violated(message = nil)
テストを強制的に失敗させる


pending(message)
テストが意図的に保留状 [...]]]></description>
			<content:encoded><![CDATA[<p>RSpecにはテストの実装が不完全であることを表すための二つのメソッドがある。</p>
<table>
<tr>
<td>violated(message = nil)</td>
<td>テストを強制的に失敗させる</td>
</tr>
<tr>
<td>pending(message)</td>
<td>テストが意図的に保留状態であることを示す</td>
</tr>
</table>
<h4>violated</h4>
<p>Test::Unitにおけるflunkと同じようなもの。</p>
<p>it のブロック内に内に書くとそのテストケース（Example）は必ず失敗する。</p>
<pre><code>it "昨日布団の中で思いついた仕様" do
  violated
end</code></pre>
<p>さっさとテスト書けよというプレッシャーが漂う。</p>
<h4>pending</h4>
<p>テスト自体や実コードの実装の保留状態を示す。</p>
<p>it のブロック内にpendingと書くと、その行以降の処理は実行されない。<br />
pendingメソッドを使うときには引数に必ず理由を書かなくてはならない。</p>
<pre><code>it "一昨日風呂の中で思いついた仕様" do
  pending("やんごとなき理由")
  # 検証されないエクスペクテーション
end</code></pre>
<p>またpendingにはブロックを与えることができ、その場合はそのブロック内の処理だけがペンディング扱いになる。</p>
<pre><code>it "こないだバイクに乗ってて思いついた仕様" do
  pending("大人の事情") do
    # 実コード未実装のため例外が出るエクスペクテーション
  end
end</code></pre>
<p>こちらはpendingブロック内のエクスペクテーションがすべてパスすると逆にテスト失敗とみなすようになる。<br />
pendingなのに通るのはおかしいと言うことだろう。</p>
<h4>未実装によるpending</h4>
<p>it にブロックを与えなかった場合には自動的にpendingになる。</p>
<pre><code>it "先日散歩してて思いついた仕様"</code></pre>
<p>仕様だけ先にぱぱっと書いてしまうとpendingの多い状態になるだろう。<br />
しかし強制的に全部失敗と言われるよりは気楽に仕様をどんどん書いて行けそうだ。</p>
<h4>使い分け</h4>
<p>violatedとpendingの使い分けの一般的なポリシーがいまいちわからない。</p>
<p>これだけはどうしても今日中に実装しなくてはならない！といか言うときだけviolated使えばいいかんじかな。例えば緊急度の高いバグ対応用のテストとか。<br />
あとはpendingにしといて粛々と実装。</p>
<p>まあとりあえず最低限チーム内でどういう扱い方をするか合意がとれていればよさそうだ。</p>
<h4>「保留」の意味合い</h4>
<p>最終的にはpendingもゼロを目指すのがやっぱり本筋なんだろうな。<br />
「状況が変わらない限りずっとペンディングの機能」とかは多分ペンディングのレベルが違うのでいったんテストごと削ってしまうのがクリーンな気がする。</p>
<p>「テストの保留」および「近く対応すると決まっている実装の保留」であって「機能を実装するかしないかわからないから保留」とは違うと区別していた方が幸せになれそうだ。<br />
やっぱり全部グリーンにならないと気持ちよくないもんな。</p>
<h4>参考</h4>
<p><a href="http://jp.rubyist.net/magazine/?0021-Rspec" target="_blank">Rubyist Magazine &#8211; スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rspec_violated_and_pending.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSpec楽しいなぁ</title>
		<link>http://brass.to/blog/enjoy_rspec.html</link>
		<comments>http://brass.to/blog/enjoy_rspec.html#comments</comments>
		<pubDate>Thu, 13 Mar 2008 16:01:58 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/enjoy_rspec.html</guid>
		<description><![CDATA[楽しいです。ええ。
RSpecはTest::Unitに比べて書きやすく感じる。
直感的に書けるというか。
RSpecを使うようになってから、仕様をテストコードとして書いてからプロダクトコードを書く、という流れが自然になっ [...]]]></description>
			<content:encoded><![CDATA[<p>楽しいです。ええ。</p>
<p>RSpecはTest::Unitに比べて書きやすく感じる。<br />
直感的に書けるというか。</p>
<p>RSpecを使うようになってから、仕様をテストコードとして書いてからプロダクトコードを書く、という流れが自然になった。<br />
多分テストコードを書くストレスが減ったせいかと思う。</p>
<p>コーディングの最初に考えた仕様やまたはコーディングの途中で思いついた仕様をテストコードに</p>
<pre><code>it "一覧はポイントの高い順に表示"</code></pre>
<p>といった風に日本語でどんどんメモ感覚を書いていけるというのが大きいようだ。</p>
<p>Test::Unitでもコメントで同じことは実現できると言えばそうなのだが、それは自然とは思いつかない。<br />
また日本語で仕様を書くのとは別にテストメソッド名を英語で考えなくちゃならない。</p>
<p>RSpecでは何も考えなくてもSyntaxがそういう流れを方向付けてくれるし、メソッド名を考える必要もない。<br />
この差は大きい。</p>
<p>ここまで考えてきて言語やフレームワークのSyntaxはUIと同じなんだなぁ、とふと思った。<br />
よいSyntaxはよいUIと同じってことだね。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/enjoy_rspec.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSpecのStoryの書き方に関するメモ</title>
		<link>http://brass.to/blog/rspec_user_stories.html</link>
		<comments>http://brass.to/blog/rspec_user_stories.html#comments</comments>
		<pubDate>Wed, 12 Mar 2008 12:31:22 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rspec_user_stories.html</guid>
		<description><![CDATA[RSpecでストーリーテストの書き方を調べたので忘れないようにまとめておく。
手順

StoryとScenarioを書く [プレーンテキスト]
Stepを書く [Rubyコード]

テストコードを書く前にテキストで仕様を [...]]]></description>
			<content:encoded><![CDATA[<p>RSpecでストーリーテストの書き方を調べたので忘れないようにまとめておく。</p>
<h4>手順</h4>
<ul>
<li>StoryとScenarioを書く [プレーンテキスト]</li>
<li>Stepを書く [Rubyコード]</li>
</ul>
<p>テストコードを書く前にテキストで仕様を書く。<br />
テストコードはその仕様にあわせて書いていく。</p>
<p>ファイル構造は以下の通り。</p>
<ul>
<li>stories/hoge/hoge &#8211; StoryとScenario</li>
<li>stories/hoge/hoge.rb &#8211; Stepをまとめて実行するためのコード</li>
<li>stories/hoge/hoge_steps.rb &#8211; Step</li>
</ul>
<p>今のところ標準でこのひな形を作るジェネレータは用意されていないが、<a href="http://brass.to/blog/rspec_story_generator.html" target="_blank">Storygen</a>で生成できる。<br />
多分これはそのうちマージされるのかな？</p>
<h4>StoryとScenarioを書く</h4>
<p>Storygenで生成されるひな形のStoryとScenarioは以下の通り。</p>
<pre><code>
Story: put your story name here

  As role
  I want feature
  So that benefit

  Scenario: everything is cool
    Given precondition
    And   another precondition
    When  action
    And   another action
    Then  outcome
    And   another outcome
    </code></pre>
<p>英語だとまったく素敵に自然に書けるっぽい。<br />
だが私は母国語を愛している。というわけで以下。</p>
<pre><code>
Story: ショッピングカートで買い物をする

  アクター：ユーザー
  目的：ショッピングカートにものを入れて中身と合計価格が確認できる
  結果：安心してお買い物を楽しめる
  ※ ここは自由記述っぽい As, I want, So thatをそのまま残すか悩んだけど消した。 

  Scenario: ショッピングカートにものを入れる
    Given ショッピングカートには何も入っていない
    And   りんご は単価 100 円
    And   みかん は単価 80 円
    When  ユーザーは りんご を 3 個カートに入れる
    And   ユーザーは みかん を 5 個カートに入れる
    And   ユーザーはショッピングカートの内容を確認する
    Then  ショッピングカートの合計価格は 700 円
    And   ショッピングカートには りんご が 3個 入っている
    And   ショッピングカートには みかん が 5個 入っている
    </code></pre>
<p>以下備考。</p>
<ul>
<li>Scenarioはこの後に続けて複数書いていける。</li>
<li>Given, When, Thenは単純に上から順に実行される。</li>
<li>Thenの後にまたWhenを書いてつなげていくのも可。</li>
<li>単語や数値だけ変えた同じ形の文はStepで再利用できる文になる。</li>
<li>単語や数値は半角スペースで他と区切る（英語だったら自然に単語で切れる）</li>
<li>Scenarioが異なってもStepは再利用できる。</li>
<li>Scenarioの文の内容を変えるとStepの方も変えなくてはならない。これは若干めんどい。</li>
</ul>
<ul>Scenarioの量が増えるとStepの再利用率が高くなっていいかんじになる？</p>
<h4>Stepを書く</h4>
<p>Scenarioがまとまったらそれに沿ってStepを書いていく。</p>
<p>Givenには前提条件。<br />
Whenにはアクション。<br />
Thenには結果を書く。</p>
<p>これは紳士協定的決まりで、どの種類のStepに何を書かないとエラーになるとかそういうことはない。<br />
Givenに前提条件の準備からアクションから結果の検証まで全部書いちゃうこともできるし、頭にいきなりThenと書いてその後ろに前提条件を書いたりもできるのだが、まあそういう変なことはしない方がいいだろう。</p>
<h5>Given</h5>
<p>前提条件。</p>
<p>商品データの準備。<br />
一応ショッピングカートに何も入ってないことも確認。</p>
<pre><code># Precondition steps / Given
steps_for :hoge do
  Given "ショッピングカートには何も入っていない" do
    get "cart/show"

    response.should have_tag('span[class="no_item_message"]')
    response.should have_tag('span[class="amount"]', "0")
    # 一応確認
  end

  Given "$name は単価 $price 円" do |name, price|
    Item.create(:name =&gt; name, :price =&gt; price)
  end
end</code></pre>
<p>下の方のGivenは「りんご は単価 100 円」「みかん は単価 80 円」に適用される。<br />
こういう仕組みによってStepが再利用できる。</p>
<h5>When</h5>
<p>アクション。</p>
<p>ユーザーの行動をトレース。<br />
カートに商品を入れて中身を確認する。</p>
<pre><code># Action steps / When
steps_for :hoge do
  When "ユーザーは $name を $n 個カートに入れる" do |name, count|
    item = Item.find_by_name(name)
    post "cart/add/", :id =&gt; item.id, :count =&gt; count
  end

  When "ユーザーはショッピングカートの内容を確認する" do
    get "cart/show"
  end
end</code></pre>
<p>ここでは上のWhenが「ユーザーは りんご を 3 個カートに入れる」「ユーザーは みかん を 5 個カートに入れる」に適用される。</p>
<h5>Then</h5>
<p>結果。</p>
<p>HTMLの内容を確認する。<br />
合計価格とカートの中身の明細。</p>
<pre><code># Outcome steps / Then
steps_for :hoge do
  Then "ショッピングカートの合計価格は $amount 円" do |amount|
    response.should be_success

    response.should have_tag('span[class="amount"]', amount)
  end

  Then "ショッピングカートには $name が $n 個入っている" do |name, count|
    item = Item.find_by_name(name)
    response.should have_tag("span[class=\"item_name_#{item.id}\"]", name)
    response.should have_tag("span[class=\"item_count_#{item.id}\"]", count)
  end
end</code></pre>
<p>これを書いているうちにひとつ技を思い出した。<br />
HTMLに出力される変数の内容を確認しやすくするために、変数をユニークな名前のidかclassを持たせたspanタグで囲むとよいって技があったのだった。</p>
<h4>ストーリーテストの実行</h4>
<p>Stepがすべて書けたら以下のように実行。</p>
<pre><code>$ ruby stories/hoge/hoge.rb</code></pre>
<p>rakeのタスクでrake spec:storiesとか言うタスクがそのうちできるのでしょう。<br />
今はないので欲しければ自分で定義するのもまたよしでせうか。</p>
<h4>雑感</h4>
<p>Scenarioの文の内容を変えるとStepの方も変えなくてはならない、という部分が若干めんどくさいけど、Stepが思ったより再利用できそうだし悪くないかもしれない。<br />
とりあえずしばらく書いてみるかな？</p>
<p>しかしユースケースの書き方とかかなり忘れてるな。</ul>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rspec_user_stories.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSpecのストーリーのひな形を作ってくれるジェネレータ</title>
		<link>http://brass.to/blog/rspec_story_generator.html</link>
		<comments>http://brass.to/blog/rspec_story_generator.html#comments</comments>
		<pubDate>Mon, 10 Mar 2008 15:48:14 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rspec_story_generator.html</guid>
		<description><![CDATA[Rails上でRSpecのストーリーを書いてみようと思って当てずっぽうで以下のコマンドを打ってみた。
$ ruby script/generate rspec_story hoge
Couldn't find 'rspe [...]]]></description>
			<content:encoded><![CDATA[<p>Rails上でRSpecのストーリーを書いてみようと思って当てずっぽうで以下のコマンドを打ってみた。</p>
<pre><code>$ ruby script/generate rspec_story hoge
Couldn't find 'rspec_story' generator</code></pre>
<p>だめっぽい。<br />
公式にも情報なし。</p>
<p>そこでぐーぐる先生に聞いてみると以下のページを教えてくれた。</p>
<p><a href="http://github.com/michaelklishin/storygen/tree/master" target="_blank">michaelklishin&#8217;s storygen at master ? GitHub</a></p>
<p>すばらしい。<br />
早速RAILS_ROOTのlib/generators以下に設置して使ってみる。</p>
<pre><code>$ ruby script/generate rspec_story hoge
      create  stories/hoge
      create  stories/hoge/hoge
      create  stories/hoge/hoge.rb
      create  stories/hoge/hoge_steps.rb</code></pre>
<p>ジェネレータの名前はやっぱりそれか（´∀`）</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rspec_story_generator.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails標準のテストとRSpecのテストの種類の対応</title>
		<link>http://brass.to/blog/rails_test_and_rspec.html</link>
		<comments>http://brass.to/blog/rails_test_and_rspec.html#comments</comments>
		<pubDate>Mon, 10 Mar 2008 13:32:55 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rails_test_and_rspec.html</guid>
		<description><![CDATA[ちょっと整理してみた。
RSpecは本当はRSpec on Railsと書くべきかもしれないけど冗長なのでRSpecで行きます。
対応表


対象
標準
RSpec


モデル
Unit Test
Model Examp [...]]]></description>
			<content:encoded><![CDATA[<p>ちょっと整理してみた。<br />
RSpecは本当はRSpec on Railsと書くべきかもしれないけど冗長なのでRSpecで行きます。</p>
<h4>対応表</h4>
<table>
<tr>
<th>対象</th>
<th>標準</th>
<th>RSpec</th>
</tr>
<tr>
<td>モデル</td>
<td>Unit Test</td>
<td>Model Examples</td>
</tr>
<tr>
<td>コントローラ</td>
<td rowspan="2">Functional Test</td>
<td>Controller Examples</td>
</tr>
<tr>
<td>ビュー</td>
<td>View Examples</td>
</tr>
<tr>
<td>ヘルパー</td>
<td>なし</td>
<td>Helper Examples</td>
</tr>
<tr>
<td>インテグレーションテスト</td>
<td>Integration Test</td>
<td>User Stories</td>
</tr>
</table>
<h4>RSpecへ移行した観点からの所見</h4>
<p>狭い見識からちょっとした雑感をば。</p>
<h5>コントローラのテストが書きやすくなった</h5>
<p>Railsの機能テスト（Functional Test）ではコントローラとビューのテストをいっしょくたに扱っていたが、RSpecでは別々になっている。</p>
<p>そのためコントローラのテストが書きやすい。<br />
データベースからの値の取得やセッションの状態の確認、どのテンプレートをレンダリングしているか、httpのレスポンスの結果は何か、などコントローラの仕事だけにフォーカスしてテスト（「Example」と呼ぶべきなんだろうけどまだなじみがないので「テスト」で）が書けるので、ビューテンプレート側での変更などを気にする必要がなくなった。</p>
<p>デザイン変更で機能テスト失敗するようになりましたとか言う凹む状況から解放された。</p>
<h5>ビューのテストはいらない子になった</h5>
<p>同じようにビューのテストでもビューテンプレートとしての役割だけに集中したテストが独立した形で書けるようになっている。</p>
<p>が、一方でコントローラとビューの連携が正しく働いているかということがテストできなくなった。（ビューが要求している変数をコントローラがちゃんとアサインしているかなど）<br />
つまりコントローラのテストとビューのテストが単体でそれぞれパスしていても、実際動いたときにきちんと動くかどうかはわからなくなった。</p>
<p>この問題に関してはビューのテストをストーリーテスト（User Stories）で対応することが推奨されている。<br />
正しい気がする。</p>
<p>というわけなのでビューのテストは書かないで必要ならばインテグレーションテストのレイヤーに任せようと思っている。<br />
単体での動作を確実に確認しておきたいややこしい処理はモデルとかコントローラにだいたい集まってるはずだしね。</p>
<h5>ビューのテストでCSSセレクタが使える</h5>
<p>assert_tagでタグの指定をするのはけっこうめんどうだったが、RSpecのhave_tagマッチャではCSSセレクタが使えるのでそれなりに楽になった。</p>
<p>ビューのテストは今のところ書く気がないがストーリーテストでもhave_tagマッチャは使える。</p>
<h5>ヘルパーのテストをサポート</h5>
<p>Rails標準ではヘルパーを扱うテストはなかったが、RSpecではサポートしている。</p>
<p>従来のRailsでもヘルパーのテストを書く方法は紹介されていたりする（<a href="http://www.amazon.co.jp/exec/obidos/ASIN/4873113121/outdoorcook-22/ref=nosim/" title="amazletlink" name="amazletlink" target="_blank">Railsレシピ</a>など参照）が、そういう手法のノウハウがなくても最初から書けるようになっているというのはよいことだ。</p>
<p>ビューの気になる部分をヘルパーに切り出してテスト対象にするとかもありかも。</p>
<h5>インテグレーションテスト</h5>
<p>これはもともと書いてなかったのでよくわからない。</p>
<p>しかしRSpecのUser Stiriesはメンテするのがけっこうめんどくさい気がしている。<br />
テキストファイルに簡易なユースケースっぽいScenarioを書いてそれに沿ったStepを書くという形式なのだが、Scenarioの文言を変更するとStepの方も修正しないといかんというのがイマイチ微妙（文言をあわせないといかんのです）・・・<br />
慣れればそうでもないんだろうか。</p>
<p>簡単に書けないのならSeleniumとかに走った方が幸せになれるかもしれないな。Selenium on Railsとかもあることだし。<br />
ただまあSeleniumはSeleniumで実行に時間がかかるというネックを抱えているんだが。</p>
<p>インテグレーションテストのレベルになると何をテストして何をテストしないかの取捨選択が肝なんだろうか。</p>
<p>雑感はおまけ程度にするはずがなんか長くなってしまった。</p>
<h4>参考</h4>
<p><a href="http://rspec.info/documentation/rails/" target="_blank">RSpec-1.1.3: Spec::Rails</a></p>
<p><a href="http://jp.rubyist.net/magazine/?0021-Rspec" target="_blank">Rubyist Magazine &#8211; スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rails_test_and_rspec.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>カバレッジの厳密さにどこまでこだわるか</title>
		<link>http://brass.to/blog/coverage.html</link>
		<comments>http://brass.to/blog/coverage.html#comments</comments>
		<pubDate>Wed, 05 Mar 2008 11:36:10 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[rcov]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/coverage.html</guid>
		<description><![CDATA[rcovは行カバレッジのツールなので、次のようなコードでは問題なくカバレッジを判定できる。
@itemがnilであるケースがテストされていなければ2行目のカバレッジは赤だ。
if @item.nil?
  return  [...]]]></description>
			<content:encoded><![CDATA[<p>rcovは行カバレッジのツールなので、次のようなコードでは問題なくカバレッジを判定できる。<br />
@itemがnilであるケースがテストされていなければ2行目のカバレッジは赤だ。</p>
<pre><code>if @item.nil?
  return render(:nothing => true, :status => '404 Not Found')
end</code></pre>
<p>しかし次のようなコードでは if の結果がどちらに分岐してもカバーしているとみなされる。<br />
@itemがnilであるケースがテストされていなくてもカバレッジはパスする。</p>
<pre><code>return render(:nothing => true, :status => '404 Not Found') if @item.nil?</code></pre>
<p>ということなのでif修飾子を使うのはやめた方がよい。おわり。</p>
<p>.<br />
.<br />
.</p>
<p>というのはウソで、カバレッジの厳密さにこだわってコードの書き方を変える必要はないと思う。<br />
カバレッジは所詮目安なんだから。</p>
<p>あと100%である必要もないし、100%であることを強制するのはナンセンス。<br />
中身の薄いテストでも100%にするだけならできるわけなので。</p>
<p>でもまあTDDで開発してたら自然と100%になる気はするなぁ。<br />
100%にする必要はないと言ったけど、100%だったらやっぱり気持ちいいな。<br />
だからTDDは気持ちいい。</p>
<p>うむ、なんだかきれいにまとまった気がする。（ほんとか？）</p>
<h4>参考</h4>
<p><a href="http://www.ibm.com/developerworks/jp/java/library/j-cq01316/" target="_blank">コード品質を追求する: カバレッジ・レポートに騙されないために</a></p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/coverage.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSpec on Railsとrcovを組み合わせて使う</title>
		<link>http://brass.to/blog/rspec_on_rails_with_rcov.html</link>
		<comments>http://brass.to/blog/rspec_on_rails_with_rcov.html#comments</comments>
		<pubDate>Tue, 04 Mar 2008 05:16:22 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rcov]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rspec_on_rails_with_rcov.html</guid>
		<description><![CDATA[rcovでRSpecのテストカバレッジも出すことができる。
ぐーぐる先生の力を借りて過去の歴史を紐解くと先人たちの苦労の跡が忍ばれるのだが、そのおかげか今はRakeのコマンド一発で連携が可能。
rake spec:rco [...]]]></description>
			<content:encoded><![CDATA[<p>rcovでRSpecのテストカバレッジも出すことができる。<br />
ぐーぐる先生の力を借りて過去の歴史を紐解くと先人たちの苦労の跡が忍ばれるのだが、そのおかげか今はRakeのコマンド一発で連携が可能。</p>
<pre><code>rake spec:rcov</code></pre>
<p>すばらしい。</p>
<h4>spec/rcov.opts</h4>
<p>rake spec:rcovした時にrcovに与えるオプションはspec.optsで指定できる。</p>
<p>デフォルトの内容は以下。</p>
<pre><code>--exclude "spec/*,gems/*"
--rails </code></pre>
<p>他人の作ったライブラリなどカバレッジテストの対象外にしたいものは&#8211;excludeに追加するとよろしい。</p>
<h5>近頃のこと</h5>
<p><a href="http://www.cocacola.co.jp/products/lineup/canadadry04.html" target="_blank">コカ・コーラのカナダドライ ジンジャーエール エクストラ</a>が辛くてうまい。<br />
でもすぐ消えそうな予感もする。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rspec_on_rails_with_rcov.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSpec on Railsを試してみた。</title>
		<link>http://brass.to/blog/rspec_on_rails.html</link>
		<comments>http://brass.to/blog/rspec_on_rails.html#comments</comments>
		<pubDate>Sun, 10 Feb 2008 09:24:53 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rspec_on_rails.html</guid>
		<description><![CDATA[今回主に参考したのは以下のページ。
スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)
タイトルからしてジョジョ臭がプンプンしやがる。
それはさておき読み進めてTest:: [...]]]></description>
			<content:encoded><![CDATA[<p>今回主に参考したのは以下のページ。</p>
<p><a href="http://jp.rubyist.net/magazine/?0021-Rspec" target="_blank">スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)</a></p>
<p>タイトルからしてジョジョ臭がプンプンしやがる。<br />
それはさておき読み進めてTest::UnitとRSpecの違いを理解。</p>
<p>基本的にやってることは同じなのだが、テストを設計の一部として明確に意識させるために記法などを工夫している。<br />
Test::Unit が「テスティングフレームワーク」であるのに対して、Rspecは「統合テスティング環境」であることを目指している。</p>
<p>ということらしい。</p>
<h4>RSpecのインストール</h4>
<p>さてとにかく百聞は一見に如かず。<br />
早速使ってみるかとRSpecをRailsのプラグインとして入れようとした段。</p>
<pre><code>$ ruby script/plugin install http://rubyforge.org/var/svn/rspec/tags/REL_1_0_8/rspec

Plugin not found: ["http://rubyforge.org/var/svn/rspec/tags/REL_1_0_8/rspec"]</code></pre>
<p>む、インストールできない。<br />
なんだかファイルがないと言われる。</p>
<p>ぐーぐる先生に聞いてみた。</p>
<p><a href="http://www.rmake-labo.com/akasata/articles/show/253" target="_blank">RSpec をインストールしてみた &#8211; Akasata&#8217;s Page（あかさたのページ）</a></p>
<p>たどって本家サイト発見。<br />
いつも思うことだけれども本家サイトがサーチエンジンの検索結果の上位に来てないのは切ない。（※Google.com in Englishではちゃんとトップに来てた）</p>
<p><a href="http://rspec.info/documentation/rails/install.html" target="_blank">RSpec-1.1.2: Installation</a></p>
<p>本家サイトのドキュメントを見たところ現在は以下のURLで入れるのが正しい模様。</p>
<pre><code>$ ruby script/plugin install http://rspec.rubyforge.org/svn/tags/CURRENT/rspec
$ ruby script/plugin install http://rspec.rubyforge.org/svn/tags/CURRENT/rspec_on_rails</code></pre>
<p>インストール成功。<br />
ちなみに「CURRENT」の部分を「REL_1_1_2」とかにすると特定のバージョンを入れることができる。</p>
<h4>RSpecを動かしてみる</h4>
<p>次は実際動かしてみる。<br />
既存のRailsアプリのディレクトリでRSpecの環境をセットアップ。</p>
<pre><code>$ ruby script/generate rspec
$ script/generate rspec_model Item</code></pre>
<p>これでrspecのディレクトリができてテストの雛形などのファイルが作成される。<br />
モデルのファイルも作ろうとするが、すでにモデルはあるのでmodel/item.rbを上書きするか？と聞かれる。上書きしない。</p>
<p>さて何もまだテストを書いてないけどまず動かしてみたいので実行。</p>
<pre><code>$ ruby script/spec -c spec/models/item_spec.rb

script/spec:4:in `run': wrong number of arguments (5 for 1) (ArgumentError)
        from script/spec:4</code></pre>
<p>これは・・・なんだか動きません。<br />
しばらくいろいろためしてscript/specの引数を削ってみたりしたけれども、そんないい加減なことでは別のエラーが出ただけだった。<br />
さらっと試したいだけなのであんまり深追いする気力はない。</p>
<p>で、ちょっと休憩した後で方向転換して別の既存のRailsアプリで動かしてみると</p>
<pre><code>$ ruby script/spec -c spec/models/item_spec.rb
F

1)
'Item should be valid' FAILED
expected valid? to return true, got false
./spec/models/item_spec.rb:9:
script/spec:4:

Finished in 0.322841 seconds

1 example, 1 failure</code></pre>
<p>おお、ちゃんと動いた。</p>
<p>理由は不明。</p>
<p>動かなかった方はRails 1.2.6で動いた方はRails 2.0.3なんだけどその違いなんだろうか？<br />
とか思ったが、RSpecのバージョンを1.0.8とかにしてもやっぱりエラーになったので、バージョンとかではなく動かなかった方がなんかおかしいっぽいな。<br />
いろいろプラグインやライブラリを入れているせいだろうか・・・</p>
<p>とりあえず使えるようになったので新しく小さなアプリをRSpec使いながら作ってみようかな。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rspec_on_rails.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>rcovでRailsのカバレッジテスト</title>
		<link>http://brass.to/blog/rcov.html</link>
		<comments>http://brass.to/blog/rcov.html#comments</comments>
		<pubDate>Sat, 26 Jan 2008 00:08:13 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rcov]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/rcov.html</guid>
		<description><![CDATA[つくるぶガイドブログ: Rails + rcov でテストカバレッジを調べるを見てrcovを試してみたら面白かった。
前半コードを交えていろいろ書いてあるけど、普段からテストを普通に書いてるなら「rcov でテストカバレ [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tkrb.jp/guide/2008/01/rails_rcov.html" target="_blank">つくるぶガイドブログ: Rails + rcov でテストカバレッジを調べる</a>を見てrcovを試してみたら面白かった。</p>
<p>前半コードを交えていろいろ書いてあるけど、普段からテストを普通に書いてるなら「rcov でテストカバレッジを調べる」の節から読んだらいいと思う。</p>
<p>以下のコマンドでrcovをgemからインストールして</p>
<pre><code>sudo gem install rcov
</code></pre>
<p>以下のコマンドで実行。</p>
<pre><code>rcov -x /usr/local/lib/ruby --rails test/**/*_test.rb
</code></pre>
<p>「-x /usr/local/lib/ruby」で自分が作ったのではないgem等のテストを無視（パス指定が大雑把かもしれん）、「&#8211;rails」でRailsの余計なファイルを無視してくれるということだ。</p>
<p>これでさくっとテストのカバレッジを示したHTMLが出来上がる。<br />
実に簡単で、見て面白い。</p>
<p>アプリを作ってるときにテスト書くのをサボると後でテストを書くというのはけっこうモチベーション的にしんどいものがあるが、これを使いながらだったら書けそうだ。</p>
<p>ちなみにカバレッジによってテストされてないコード箇所は分かるが、適切なテストが書かれているかが保証されるわけではないし、そもそも必要なコードが書かれているかということも教えてくれないので過信は禁物。<br />
カバレッジが100%でもバグはあり得る。</p>
<p>とはいえ、テストの品質と作成効率を上げるのにかなり役立つツールであることは間違いない。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rcov.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
