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.5k
Tokyo Web Dev hiring discussion session
kyanny
0
13k
sbpayment.rbのご紹介
kyanny
0
2.1k
#AsiaDevNight
kyanny
0
160
Grape による API 実装 in action
kyanny
7
7.2k
<%= link_to "bundle", "update" %> - Make "bundle update" more fun to review
kyanny
2
5.2k
Web Developer Seminar
kyanny
0
1.9k
Heroku を利用した Quipper の開発事例紹介
kyanny
11
3.3k
Continuous gem dependency updating with Jenkins and Pull Request
kyanny
9
3.3k
Other Decks in Programming
See All in Programming
Java 25, Nuevas características
czelabueno
0
120
Deno Tunnel を使ってみた話
kamekyame
0
280
Flutter On-device AI로 완성하는 오프라인 앱, 박제창 @DevFest INCHEON 2025
itsmedreamwalker
1
170
DevFest Android in Korea 2025 - 개발자 커뮤니티를 통해 얻는 가치
wisemuji
0
180
gunshi
kazupon
1
130
AIエージェントの設計で注意するべきポイント6選
har1101
6
2.7k
Claude Codeの「Compacting Conversation」を体感50%減! CLAUDE.md + 8 Skills で挑むコンテキスト管理術
kmurahama
1
680
AIエンジニアリングのご紹介 / Introduction to AI Engineering
rkaga
8
3.5k
Cap'n Webについて
yusukebe
0
160
クラウドに依存しないS3を使った開発術
simesaba80
0
190
ゆくKotlin くるRust
exoego
1
180
はじめてのカスタムエージェント【GitHub Copilot Agent Mode編】
satoshi256kbyte
0
130
Featured
See All Featured
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
210
Marketing to machines
jonoalderson
1
4.5k
Agile that works and the tools we love
rasmusluckow
331
21k
Raft: Consensus for Rubyists
vanstee
141
7.3k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
720
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
98
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.8k
Between Models and Reality
mayunak
0
150
Fireside Chat
paigeccino
41
3.8k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
78
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:
[email protected]
bob: id: 2
email:
[email protected]
# 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:
[email protected]
bob: id: 2
email:
[email protected]
# 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 "
[email protected]
" end Factory.define(:bob) do
|u| u.email "
[email protected]
" 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