Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Head First Fixture Replacement
Search
Kensuke Nagae
March 21, 2012
Programming
1
2.9k
Head First Fixture Replacement
ペパボ社内の RSpec 勉強会で Fixture Replacement について発表したスライドです。
Kensuke Nagae
March 21, 2012
Tweet
Share
More Decks by Kensuke Nagae
See All by Kensuke Nagae
スタディサプリ開発チームのこれまでとこれから / StudySapuri Product Meetup #1
kyanny
0
2.3k
Tokyo Web Dev hiring discussion session
kyanny
0
13k
sbpayment.rbのご紹介
kyanny
0
2k
#AsiaDevNight
kyanny
0
120
Grape による API 実装 in action
kyanny
7
6.9k
<%= link_to "bundle", "update" %> - Make "bundle update" more fun to review
kyanny
2
4.9k
Web Developer Seminar
kyanny
0
1.8k
Heroku を利用した Quipper の開発事例紹介
kyanny
11
3.2k
Continuous gem dependency updating with Jenkins and Pull Request
kyanny
9
3.1k
Other Decks in Programming
See All in Programming
CDKを使ったPagerDuty連携インフラのテンプレート化
shibuya_shogo
0
110
『テスト書いた方が開発が早いじゃん』を解き明かす #phpcon_nagoya
o0h
PRO
9
2.5k
Serverless Rust: Your Low-Risk Entry Point to Rust in Production (and the benefits are huge)
lmammino
1
160
たのしいSocketのしくみ / Socket Under a Microscope
coe401_
8
1.4k
Djangoにおける複数ユーザー種別認証の設計アプローチ@DjangoCongress JP 2025
delhi09
PRO
4
500
読まないコードリーディング術
hisaju
0
110
新宿駅構内を三人称視点で探索してみる
satoshi7190
2
120
[JAWS DAYS 2025] 最近の DB の競合解決の仕組みが分かった気になってみた
maroon1st
0
140
第3回関東Kaggler会_AtCoderはKaggleの役に立つ
chettub
3
1.2k
Formの複雑さに立ち向かう
bmthd
1
940
責務と認知負荷を整える! 抽象レベルを意識した関心の分離
yahiru
8
1.5k
color-scheme: light dark; を完全に理解する
uhyo
7
500
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7k
Designing Experiences People Love
moore
140
23k
Reflections from 52 weeks, 52 projects
jeffersonlam
348
20k
Building an army of robots
kneath
303
45k
Scaling GitHub
holman
459
140k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
4
380
BBQ
matthewcrist
87
9.5k
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
Thoughts on Productivity
jonyablonski
69
4.5k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
30
4.6k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.3k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
27
1.6k
Transcript
Head First Fixture Replacement @kyanny
Disclaimer: Samples Are Not Smartest, Not Enough, Not Exactly Correct
Test Environment then Fixture then Fixture Replacement
Test Environment
Test Suite Requires Isolate Environment
Unified Environment
User.create assert User.count == 1 # SUCCESS
User.create # Oops! Someone Create User # POST /users/create assert
User.count == 1 # FAIL
Isolate Environment
mysql> show databases; +--------------------+ | Database | +--------------------+ | development
| | test | | production | +--------------------+
User.create # For Development Environment # POST /users/create assert User.count
== 1 # SUCCESS
Fixture
Fixture == Dummy Data for Tests
: ( user = User.create user.albums << Album.create user.albums <<
Album.create user.albums << Album.create assert user.albums.count >= 3
# fixtures/users.yml alice: id: 1 email: alice@example.com bob: id: 2
email: bob@example.com
# fixtures/albums.yml one: user_id: 1 two: user_id: 1 three: user_id:
1
: ) fixtures :users fixtures :albums user = users(:alice) assert
user.albums.count >= 3
But... DRY
Fixture is Too Difficult To Maintain
Complex Association
# User has_many :bookmarks has_many :pages, :through => :bookmarks #
Page has_many :bookmarks has_many :users, :through => :bookmarks # Bookmark belongs_to :user belongs_to: page
# fixtures/users.yml alice: id: 1 email: alice@example.com bob: id: 2
email: bob@example.com
# fixtures/pages.yml twitter: id: 1 url: http://twitter.com/ facebook: id: 2
url: http://facebook.com/
# fixtures/bookmarks.yml alice_twitter: user_id: 1 page_id: 1 bob_facebook: user_id: 2
page_id: 1 # Oops! Wrong id
bob = users(:bob) assert bob.pages.first.url == "http://facebook.com/" # FAIL
Complex Data
# fixtures/photos.yml one: album_id: 1 exif: | --- width: 1024
height: 768 f_number: 280/100
Fixture is Too Difficult To Maintain
Fixture Replacement
Fixture Replacement == Skeleton of Dummy Data for Tests
Fixture == Data itself Fixture Replacement == Skeleton of Data
# factories/users.rb Factory.define(:album) do |a| a.title "Album Title" a.password "Album
Password" end album = Factory.create(:album) album = Factory.create(:album, :title => "Happy Wedding")
# factories/users.rb Factory.define(:alice) do |u| u.email "alice@example.com" end Factory.define(:bob) do
|u| u.email "bob@example.com" end
# factories/users.rb Factory.sequence(:email) do |n| "user_#{n}@example.com" end Factory.define(:user) do |u|
u.email { Factory.next(:email) } end
Flexible
# factories/pages.rb Factory.define(:twitter) do |p| p.url "http://twitter.com/" end Factory.define(:facebook) do
|p| p.url "http://facebook.com/" end
# factories/users.rb Factory.define(:alice) do |u| u.pages {[ Factory(:twitter) ]} end
Factory.define(:bob) do |u| u.pages {[ Factory(:facebook) ]} end
bob = Factory.create(:bob) assert bob.pages.first.url == "http://facebook.com/" # SUCCESS
But... Flexible
Fixture Replacement is Not a Silver Bullet
Children w/ Independent Parent
# factories/albums.rb Factory.define(:album) do |a| a.user { Factory(:user) } end
Factory.define(:paid) do |a| a.user { Factory(:user) } end
3.times do album = Factory.create(:album) end paid = Factory.create(:paid) user
= paid.user assert user.albums.count == 4 # FAIL
user = Factory.create(:user) 3.times do Factory(:album, :user => user) end
Factory(:paid, :user => user) assert user.albums.count == 4 # SUCCESS
Not DRY
Proposal: Fixture w/ Fixture Replacement
Test Context Arrangement Recipebook
First, Use Fixture. Complex, Then Use Fixture Replacement.
# fixtures/users.yml alice: id: 1 bob: id: 2
# fixtures/albums.yml one: user_id: 1 two: user_id: 1 three: user_id:
1 four: user_id: 1
fixtures :all user = users(:alice) assert user.albums.count == 4 #
SUCCESS
# factories/photos.rb exif = { :width => 1024, :height =>
768 } Factory.define(:photo) do |p| p.exif { exif.to_yaml } end
photo = Factory.create(:photo) assert photo.exif[:width] == 1024 # SUCCESS
Use The Right Tool In The Right Place
http://www.func09. com/wordpress/archives/532 http://eblog.drecom.jp/entry/14 http://www.slideshare.net/moro/test- context-arrangement-recipebook http://d.hatena.ne. jp/a666666/20110220/1298135559
end
Kensuke Nagae blog.kyanny.me @kyanny