<?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>func09 &#187; rspec</title>
	<atom:link href="http://www.func09.com/wordpress/archives/tag/rspec/feed" rel="self" type="application/rss+xml" />
	<link>http://www.func09.com/wordpress</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Mon, 06 Feb 2012 04:25:55 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>[rails]has_manyなフィクスチャを書くのに疲れたらFactory Girlがオススメ！</title>
		<link>http://www.func09.com/wordpress/archives/532</link>
		<comments>http://www.func09.com/wordpress/archives/532#comments</comments>
		<pubDate>Sat, 25 Apr 2009 16:12:39 +0000</pubDate>
		<dc:creator>haga</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[日記]]></category>
		<category><![CDATA[factorygirl]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>

		<guid isPermaLink="false">http://www.func09.com/wordpress/?p=532</guid>
		<description><![CDATA[フィクスチャはメンテナンスしづらい 書籍The Rails Wayの中には「皆フィクスチャが嫌い」という項目があります（次の項目は「フィクスチャはそれほど悪くない」ですが）。 フィクスチャが嫌われる最大の原因は「メンテナ [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.func09.com/wordpress/wp-content/uploads/2009/04/factorygirl.jpg" alt="factorygirl" title="factorygirl" width="568" height="160" class="alignnone size-full wp-image-557" /></p>

<h2>フィクスチャはメンテナンスしづらい</h2>

<p>書籍<a href="http://www.amazon.co.jp/o/ASIN/4798116998">The Rails Way</a>の中には「皆フィクスチャが嫌い」という項目があります（次の項目は「フィクスチャはそれほど悪くない」ですが）。</p>

<p>フィクスチャが嫌われる最大の原因は「メンテナンスが難しい」という事でしょう。<br />
中間テーブルを必要とする多対多の関連をフィクスチャにしようと思ってうんざりした経験は誰にもでもあると思います。</p>

<p>Fixtureのhas_manyでこんな書き方したい<br />
<a href="http://www.func09.com/wordpress/archives/369">http://www.func09.com/wordpress/archives/369</a></p>

<h2>フィクスチャの代わりにFactoryGirlを使ってみる</h2>

<p><a href="http://www.thoughtbot.com/projects/factory_girl/">Factory Girl</a>はRailsのテストにおいてfixtureの代替となるツールです。<br />
つまりテスト時のモデルデータを用意するための仕組みです。<br />
<a href="http://www.thoughtbot.com/projects/factory_girl/">Factory Girl</a>はフィクスチャと違い、Rubyのスクリプトで直接データを定義していきます。</p>

<p>特徴としては</p>

<ul>
<li>Rubyコードで定義（YAMLやCSVではない）</li>
<li>関連のメンテナンスが楽</li>
<li>定義の継承もできる</li>
<li>同じ定義から連続的なデータを生成できる（シーケンス）</li>
</ul>

<p>Rubyコードで実データを作る感覚でテストデータを定義するので、フィクスチャと違い中間テーブルのメンテナンスから解放されます。
<span id="more-532"></span></p>

<h2>インストール</h2>

<p>インストールはgemで簡単にインストールできます。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sudo gem install thoughtbot-factory_girl --source http://gems.github.com</div></div>

<p>config/environment.rbに依存するgemとして登録しておくと、テスト実行時に自動でFactory Girlがロードされるので便利です。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">config.gem &quot;thoughtbot-factory_girl&quot;, :lib =&gt; &quot;factory_girl&quot;, :source =&gt; &quot;http://gems.github.com&quot;</div></div>

<h2>実際にサンプルを作ってみる</h2>

<p>定義の継承やシーケンスといった機能も便利なのですが、とりあえず<strong>最大のメリットである複雑な関連をシンプルに定義できる</strong>という事を簡単なサンプルで証明したいと思います。</p>

<p>User,Page,Bookmarkという３つのモデルで簡単なブックマークアプリを作ります。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># app/models/user.rb<br />
class User &lt; ActiveRecord::Base<br />
&nbsp; # name:string<br />
&nbsp; has_many :bookmarks<br />
&nbsp; has_many :pages, :through =&gt; :bookmarks<br />
end<br />
<br />
# app/models/page.rb<br />
class Page &lt; ActiveRecord::Base<br />
&nbsp; # title:string<br />
&nbsp; # url:string<br />
&nbsp; has_many :bookmarks<br />
&nbsp; has_many :users, :through =&gt; :bookmarks<br />
end<br />
<br />
# app/models/bookmark.rb<br />
class Bookmark &lt; ActiveRecord::Base<br />
&nbsp; # user_id:integer<br />
&nbsp; # page_id:integer<br />
&nbsp; belongs_to :user<br />
&nbsp; belongs_to :page<br />
end</div></div>

<p>UserとPageがBookmarkを中間テーブルとして多対多の関係になっています。</p>

<h2>ファクトリーを定義する</h2>

<p>Factory Girlは特定のクラスに対して名前を付けて雛形を定義することができます。</p>

<p>spec/factories.rbというファイルを作成し（rspecを使う場合）、次のように記述します</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Factory.define :bob, :class =&gt; User do |f|<br />
&nbsp; f.name &quot;bob&quot;<br />
end<br />
<br />
Factory.define :mike, :class =&gt; User do |f|<br />
&nbsp; f.name &quot;mike&quot;<br />
end<br />
<br />
Factory.define :yahoo, :class =&gt; Page do |f|<br />
&nbsp; f.title &quot;Yahoo!&quot;<br />
&nbsp; f.url &quot;http://www.yahoo.com/&quot;<br />
end<br />
<br />
Factory.define :google, :class =&gt; Page do |f|<br />
&nbsp; f.title &quot;Google&quot;<br />
&nbsp; f.url &quot;http://www.google.com/&quot;<br />
end</div></div>

<p>specもしくはtestディレクトリにfactories.rbというファイルか、factories/というディレクトリ内にrbファイルを配置すれば、自動的にFactoryGirlで定義が利用可能となります。</p>

<p>FactoryGirlは<b>Factory.define(name,options)</b>メソッドでテスト用のモデルインスタンスを作成する工場を定義していきます。</p>

<p>nameにはユニークな定義名を、optionsにはHashを渡します。とりあえず:classオプションがモデルクラスを指定することだけ覚えておきましょう。</p>

<p>ブロック引数に渡したfはfactoryインスタンスです。モデルに指定したattributeの雛形を定義しておきます。</p>

<p>ここではbobとmikeというユーザー、yahooとgoogleというページを定義しました。</p>

<h2>テストから利用する</h2>

<p>では実際にテストコードからFactoryGirlを利用してみます。
先ほど定義したファクトリーを使ってインスタンス化する場合は</p>

<ul>
<li>Factory.create(name)</li>
<li>Factory.build(name)</li>
</ul>

<p>を使います。createは保存したインスタンスを、buildは保存前のインスタンスを返すようになっていて、createはデフォルトの場合、次のようなショートハンドが使えます。</p>

<ul>
<li>Factory(name)</li>
</ul>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># spec/models/user_spec.rb<br />
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')<br />
describe User do<br />
&nbsp; it &quot;正常に保存できること&quot; do<br />
&nbsp; &nbsp; @user = Factory.build(:bob)<br />
&nbsp; &nbsp; @user.save.should be_true<br />
&nbsp; end<br />
end</div></div>

<p>テストを実行すると、ちゃんと動いているのがわかります。
Factory.buildで取得できるオブジェクトはスタブやモックではなく、れっきとしたモデルクラスのインスタンスなので当然saveなどのメソッドが使えます。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">User<br />
- 正常に保存できること<br />
<br />
Finished in 0.067948 seconds<br />
<br />
1 example, 0 failures</div></div>

<h2>関連を定義する</h2>

<p>ここまでは普通のフィクスチャでも当然できますので、フィクスチャだったら面倒くさい多対多の関連を定義します。</p>

<p>bobが２つのブックマークを、mikeが１つのブックマークを持っていることをFactory Girlで書くにはどうすれば良いでしょうか？</p>

<p>そのためのテストコードを追加しておきましょう。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">it &quot;ボブはブックマークを２つ持っていること&quot; do<br />
&nbsp; @bob = Factory(:bob)<br />
&nbsp; @bob.should have(2).bookmarks<br />
end<br />
<br />
it &quot;マイクはブックマークを１つ持っていること&quot; do<br />
&nbsp; @mike = Factory(:mike)<br />
&nbsp; @mike.should have(1).bookmarks<br />
end</div></div>

<p>テストが赤で失敗するのを確認したら、ファクトリーの定義を修正します。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#spec/factories.rb<br />
Factory.define :bob, :class =&gt; User do |f|<br />
&nbsp; f.name &quot;bob&quot;<br />
&nbsp; f.pages {<br />
&nbsp; &nbsp; [Factory(:google),Factory(:yahoo)]<br />
&nbsp; }<br />
end<br />
<br />
Factory.define :mike, :class =&gt; User do |f|<br />
&nbsp; f.name &quot;mike&quot;<br />
&nbsp; f.pages {<br />
&nbsp; &nbsp; [Factory(:google)]<br />
&nbsp; }<br />
end</div></div>

<p>これでOKです。簡単でしょ？どのユーザーがどのページを持っているか？直感的に書けることと、中間テーブルであるブックマークについて何も書かれていないことに注目してください。</p>

<p>それぞれのUserが持っているpagesを配列で指定しています。
この時、{}というブロックで渡すとFactoryGirlは遅延処理と見なしてくれるので、実際にpagesが呼ばれるまで定義は反映されません。</p>

<p>配列にはFactory(name)で、定義したファクトリーからインスタンスを生成します。</p>

<p>これでテストがグリーンになることを確認できました。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">User<br />
- 正常に保存できること<br />
- ボブはブックマークを２つ持っていること<br />
- マイクはブックマークを１つ持っていること<br />
<br />
Finished in 0.152733 seconds<br />
<br />
3 examples, 0 failures</div></div>

<h2>最後に</h2>

<p>どうでしょうか？FactoryGIrl。
最近よく名前を聞くのに日本語で使い方を説明しているサイトが見つからなかったので、駆け足で使い方を説明してみました。</p>

<p>フィクスチャはやっぱり便利なところもあるので、使いたいのだけれど関連が絡んでくると一気にモチベーションが下がりますよね。
FactoryGirlはちょっと冗長だけれど、無理なく関連を管理できるので、これまでフィクスチャに悩まされてきた人にはおすすめです。</p>

<ul>
<li>サンプル on Github

<ul>
<li><a href="http://github.com/func09/bookmark-factorygirl-sample/tree/master">http://github.com/func09/bookmark-factorygirl-sample/tree/master</a></li>
</ul></li>
</ul>

<h2>参考</h2>

<ul>
<li><a href="http://railscasts.com/episodes/158-factories-not-fixtures">http://railscasts.com/episodes/158-factories-not-fixtures</a></li>
<li><a href="http://www.thoughtbot.com/projects/factory_girl/">http://www.thoughtbot.com/projects/factory_girl/</a></li>
<li><a href="http://github.com/thoughtbot/factory_girl/tree/master">http://github.com/thoughtbot/factory_girl/tree/master</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.func09.com/wordpress/archives/532/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>テストでスタブの掛け方に悩み中</title>
		<link>http://www.func09.com/wordpress/archives/530</link>
		<comments>http://www.func09.com/wordpress/archives/530#comments</comments>
		<pubDate>Thu, 23 Apr 2009 18:01:03 +0000</pubDate>
		<dc:creator>haga</dc:creator>
				<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.func09.com/wordpress/?p=530</guid>
		<description><![CDATA[例えばActiveRecordで新規作成したタイミングでリモートにアクセスするような処理があったとして class Item &#60; ActiveRecord::Base &#160; before_create :d [...]]]></description>
			<content:encoded><![CDATA[<p>例えばActiveRecordで新規作成したタイミングでリモートにアクセスするような処理があったとして</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Item &lt; ActiveRecord::Base<br />
&nbsp; before_create :do_something_with_remote<br />
&nbsp; def do_something_with_remote<br />
&nbsp; &nbsp; open(self.url)<br />
&nbsp; end<br />
end</div></div>

<p>この場合、テストの時はItem#do_something_with_remoteをスタブにするよね。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">item = Item.new :url =&gt; 'http://www.example.com'<br />
item.stub! :do_something_with_remote</div></div>

<p>本当はこんな感じでかけたい</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Item.stub_instance_method(:do_something_with_remote)</div></div>

<p>stubはそのオブジェクトにしか使えない？インスタンスメソッドまで影響するスタブはどう書けば良い？</p>

<p>&#8211;</p>

<p>Fixtureの代わりにFactoryGirlを使い始めた。
これがなかなかシンプルで使い勝手が良いんだけど、関連を設定する時に上記のような作りの場合にちょっと困っている。
Factory.defineの中でインスタンスのメソッドにstubを設定できればいいんだよな。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Factory.define :item, :class =&gt; Item do |item|<br />
&nbsp; item.stub!(:do_something_with_remote)<br />
end</div></div>

<p>明日改造できるかソースコードを見てみる。
Factory.stubはあるんだし、できないことはないよな。</p>

<p>今は時間がないのでスペックヘルパーで</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Item<br />
&nbsp; def do_something_remote;end<br />
end</div></div>

<p>みたいに上書きして対処しているが・・・駄目だよな。<br />
FactoryGirlに関してはノウハウが溜まったら書くかも。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.func09.com/wordpress/archives/530/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>rspec-railsでテスト結果を見やすくする</title>
		<link>http://www.func09.com/wordpress/archives/475</link>
		<comments>http://www.func09.com/wordpress/archives/475#comments</comments>
		<pubDate>Mon, 30 Mar 2009 10:14:34 +0000</pubDate>
		<dc:creator>haga</dc:creator>
				<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[日記]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.func09.com/wordpress/?p=475</guid>
		<description><![CDATA[はじめに The Rails Wayを読了しました。 Railsの本は出版されたら大抵買って読むようにしているのですがその中でもかなり良著だったと思います。 これから読む人はRailsアジャイルによるWebアプリケーショ [...]]]></description>
			<content:encoded><![CDATA[<h2>はじめに</h2>

<p>The Rails Wayを読了しました。
Railsの本は出版されたら大抵買って読むようにしているのですがその中でもかなり良著だったと思います。
これから読む人はRailsアジャイルによるWebアプリケーション入門の後くらいに読むと良いですね。</p>

<p>さて、Rails Wayの素敵な点はテストに結構なページを割いているという点です。
Rails標準のテストとRspecによるテストにそれぞれ章だててあり、ページ数にすると60Pを超えます。
本当はRspecだけで一冊書いてほしいくらいなんですが、それでも今日本語で読める本としては一番多いと思います。</p>

<h2>Rspecの結果表示</h2>

<p>rake specでもscript/autospecでもいいんですが、何も考えずに使っていると下の画像のようになります。</p>

<p><img src="http://www.func09.com/wordpress/wp-content/uploads/2009/03/e9d34049a45293d49131e67dcf884f90.jpeg" alt="e9d34049a45293d49131e67dcf884f90" title="e9d34049a45293d49131e67dcf884f90" width="558" height="192" class="alignnone size-full wp-image-479" /></p>

<p>ま、これでもいいっちゃいいんですが
フォーマットを買えてリスト表示（specdoc）にしたいなぁと思いました。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">spec -cfs spec/hoge_spec.rb</div></div>

<p>こうオプションを渡した時みたいにね。</p>

<h2>spec/spec.opts</h2>

<p>specフォルダの中にspec.optsというファイルがあります。こいつの内容を見ると</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--colour<br />
--format progress<br />
--loadby mtime<br />
--reverse</div></div>

<p>おー、見覚えのある文字列が。。specコマンドに渡せるオプションをここに書けばフォーマットも変えることができそう。</p>

<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--colour<br />
--format specdoc<br />
--loadby mtime<br />
--reverse</div></div>

<p>こう書き換えたら・・</p>

<p><img src="http://www.func09.com/wordpress/wp-content/uploads/2009/03/9271e70b85e8ca0f662ca3ee02a50f17.jpeg" alt="9271e70b85e8ca0f662ca3ee02a50f17" title="9271e70b85e8ca0f662ca3ee02a50f17" width="554" height="422" class="alignnone size-full wp-image-478" /></p>

<p>こうなりました。</p>

<p>こっちの方がいいっすね。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.func09.com/wordpress/archives/475/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

