Slide 1

Slide 1 text

Head First Fixture Replacement @kyanny

Slide 2

Slide 2 text

Disclaimer: Samples Are Not Smartest, Not Enough, Not Exactly Correct

Slide 3

Slide 3 text

Test Environment then Fixture then Fixture Replacement

Slide 4

Slide 4 text

Test Environment

Slide 5

Slide 5 text

Test Suite Requires Isolate Environment

Slide 6

Slide 6 text

Unified Environment

Slide 7

Slide 7 text

User.create assert User.count == 1 # SUCCESS

Slide 8

Slide 8 text

User.create # Oops! Someone Create User # POST /users/create assert User.count == 1 # FAIL

Slide 9

Slide 9 text

Isolate Environment

Slide 10

Slide 10 text

mysql> show databases; +--------------------+ | Database | +--------------------+ | development | | test | | production | +--------------------+

Slide 11

Slide 11 text

User.create # For Development Environment # POST /users/create assert User.count == 1 # SUCCESS

Slide 12

Slide 12 text

Fixture

Slide 13

Slide 13 text

Fixture == Dummy Data for Tests

Slide 14

Slide 14 text

: ( user = User.create user.albums << Album.create user.albums << Album.create user.albums << Album.create assert user.albums.count >= 3

Slide 15

Slide 15 text

# fixtures/users.yml alice: id: 1 email: [email protected] bob: id: 2 email: [email protected]

Slide 16

Slide 16 text

# fixtures/albums.yml one: user_id: 1 two: user_id: 1 three: user_id: 1

Slide 17

Slide 17 text

: ) fixtures :users fixtures :albums user = users(:alice) assert user.albums.count >= 3

Slide 18

Slide 18 text

But... DRY

Slide 19

Slide 19 text

Fixture is Too Difficult To Maintain

Slide 20

Slide 20 text

Complex Association

Slide 21

Slide 21 text

# 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

Slide 22

Slide 22 text

# fixtures/users.yml alice: id: 1 email: [email protected] bob: id: 2 email: [email protected]

Slide 23

Slide 23 text

# fixtures/pages.yml twitter: id: 1 url: http://twitter.com/ facebook: id: 2 url: http://facebook.com/

Slide 24

Slide 24 text

# fixtures/bookmarks.yml alice_twitter: user_id: 1 page_id: 1 bob_facebook: user_id: 2 page_id: 1 # Oops! Wrong id

Slide 25

Slide 25 text

bob = users(:bob) assert bob.pages.first.url == "http://facebook.com/" # FAIL

Slide 26

Slide 26 text

Complex Data

Slide 27

Slide 27 text

# fixtures/photos.yml one: album_id: 1 exif: | --- width: 1024 height: 768 f_number: 280/100

Slide 28

Slide 28 text

Fixture is Too Difficult To Maintain

Slide 29

Slide 29 text

Fixture Replacement

Slide 30

Slide 30 text

Fixture Replacement == Skeleton of Dummy Data for Tests

Slide 31

Slide 31 text

Fixture == Data itself Fixture Replacement == Skeleton of Data

Slide 32

Slide 32 text

# 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")

Slide 33

Slide 33 text

# factories/users.rb Factory.define(:alice) do |u| u.email "[email protected]" end Factory.define(:bob) do |u| u.email "[email protected]" end

Slide 34

Slide 34 text

# factories/users.rb Factory.sequence(:email) do |n| "user_#{n}@example.com" end Factory.define(:user) do |u| u.email { Factory.next(:email) } end

Slide 35

Slide 35 text

Flexible

Slide 36

Slide 36 text

# 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

Slide 37

Slide 37 text

# factories/users.rb Factory.define(:alice) do |u| u.pages {[ Factory(:twitter) ]} end Factory.define(:bob) do |u| u.pages {[ Factory(:facebook) ]} end

Slide 38

Slide 38 text

bob = Factory.create(:bob) assert bob.pages.first.url == "http://facebook.com/" # SUCCESS

Slide 39

Slide 39 text

But... Flexible

Slide 40

Slide 40 text

Fixture Replacement is Not a Silver Bullet

Slide 41

Slide 41 text

Children w/ Independent Parent

Slide 42

Slide 42 text

# factories/albums.rb Factory.define(:album) do |a| a.user { Factory(:user) } end Factory.define(:paid) do |a| a.user { Factory(:user) } end

Slide 43

Slide 43 text

3.times do album = Factory.create(:album) end paid = Factory.create(:paid) user = paid.user assert user.albums.count == 4 # FAIL

Slide 44

Slide 44 text

user = Factory.create(:user) 3.times do Factory(:album, :user => user) end Factory(:paid, :user => user) assert user.albums.count == 4 # SUCCESS

Slide 45

Slide 45 text

Not DRY

Slide 46

Slide 46 text

Proposal: Fixture w/ Fixture Replacement

Slide 47

Slide 47 text

Test Context Arrangement Recipebook

Slide 48

Slide 48 text

First, Use Fixture. Complex, Then Use Fixture Replacement.

Slide 49

Slide 49 text

# fixtures/users.yml alice: id: 1 bob: id: 2

Slide 50

Slide 50 text

# fixtures/albums.yml one: user_id: 1 two: user_id: 1 three: user_id: 1 four: user_id: 1

Slide 51

Slide 51 text

fixtures :all user = users(:alice) assert user.albums.count == 4 # SUCCESS

Slide 52

Slide 52 text

# factories/photos.rb exif = { :width => 1024, :height => 768 } Factory.define(:photo) do |p| p.exif { exif.to_yaml } end

Slide 53

Slide 53 text

photo = Factory.create(:photo) assert photo.exif[:width] == 1024 # SUCCESS

Slide 54

Slide 54 text

Use The Right Tool In The Right Place

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

end

Slide 57

Slide 57 text

Kensuke Nagae blog.kyanny.me @kyanny