factory_boy 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc ADDED
@@ -0,0 +1,110 @@
1
+ == Overview
2
+ Factory_boy aims to avoid slow unit tests due to usage of create/find fixtures in database, with factory_girl for example.
3
+ Factory_boy can be used as factory_girl except that factories are not created in database.
4
+ ActiveRecord::Base find method is stubbed to return fixtures (plants) you have instanciate.
5
+ Differenciate find :all, :first, :last, but doesn't do the work of find with sql conditions.
6
+ Anyway we don't think it's important for unit test, if some find calls with sql conditions, :include ... etc have to be
7
+ tested, report it in integration tests is a better idea.
8
+
9
+ See some examples below.
10
+ You can see also unit tests / code for deeper comprehension.
11
+
12
+ == Basic Usage
13
+
14
+ Define your Plants (=~ Factories if factory_girl) in test/plants.rb
15
+
16
+ Example :
17
+
18
+ Plant.define :user do |user|
19
+ user.name="Bart"
20
+ user.age=800
21
+ end
22
+
23
+ Get it with :
24
+
25
+ user = Plant(:user)
26
+
27
+
28
+ <b>Example of tests :</b>
29
+
30
+
31
+ def test___1
32
+ user = Plant(:user)
33
+ assert_equal user, User.find #OK
34
+ assert_equal user, User.find(:first) #OK
35
+ assert_equal user, User.find(:last) #OK
36
+ end
37
+
38
+
39
+ def test___2
40
+ 2.times { Plant(:user) }
41
+ assert_equal 2, User.find(:all).size #OK
42
+ end
43
+
44
+
45
+ <b>You can also create a particular plant of user like that:</b>
46
+
47
+ user = Plant(:user, :name => "Marie", :age => age)
48
+
49
+ == Specification of the class of the fixture definition
50
+
51
+ Plant.define :admin, :class => User do |user|
52
+ user.name = "Bart"
53
+ user.age = 800
54
+ end
55
+
56
+ == Associations
57
+
58
+ Assign fixtures to association in definition of plant :
59
+
60
+ Plant.define :profile do |profile|
61
+ profile.password = "BREIZH!"
62
+ end
63
+
64
+ Plant.define :adress do |adress|
65
+ adress.number = 12
66
+ adress.street = "rue de Brest"
67
+ end
68
+
69
+ Plant.define :user do |user|
70
+ user.name = "Bart"
71
+ user.age = 800
72
+ user.profile = Plant.association(:profile)
73
+ user.adresses = [Plant.association(:adress)]
74
+ end
75
+
76
+
77
+
78
+ == Definitions with dependent attributes
79
+
80
+ If you want to use the value of another attribute in definition, do like that :
81
+
82
+ Plant.define :user do |user|
83
+ user.name = "Marie"
84
+ user.adresses = [Adress.new(:street => "Rue de #{user.name}")]
85
+ end
86
+
87
+
88
+ == Sequences
89
+
90
+ As with factory_girl you are able to use sequences, like that :
91
+
92
+ Plant.sequence :email do |n|
93
+ "incognito#{n}@kantena.com"
94
+ end
95
+
96
+ Plant.next(:email) # => "incognito1@kantena.com"
97
+ Plant.next(:email) # => "incognito2@kantena.com"
98
+
99
+
100
+ == Dependencies
101
+
102
+ No dependency.
103
+ Not tested with rails 3
104
+
105
+
106
+ == Notes
107
+
108
+
109
+
110
+ <b>Report Bugs here , on github</b>
@@ -0,0 +1 @@
1
+ require 'plant'
data/lib/plant.rb ADDED
@@ -0,0 +1,90 @@
1
+ require 'rubygems'
2
+ require 'active_support/inflector'
3
+ require 'stubber'
4
+ require 'setup'
5
+
6
+ module Plant
7
+
8
+ @@plants = {}
9
+ @@pool = {}
10
+ @@map = {}
11
+ @@sequences = {}
12
+ @@stubbed = []
13
+
14
+ def self.define symbol, args={}
15
+ klass = args[:class] || symbol.to_s.camelize.constantize
16
+ instance = klass.new
17
+ yield instance if block_given?
18
+ add_plant(klass, instance)
19
+ add_plant(symbol, instance) if args[:class]
20
+ stubs(instance.class)
21
+ end
22
+
23
+ def self.stubs klass
24
+ unless @@stubbed.include?(klass)
25
+ Plant::Stubber.stubs_find(klass)
26
+ @@stubbed << klass
27
+ end
28
+ end
29
+
30
+ def self.unstub_find_for_each_class
31
+ @@stubbed.each {|klass| Plant::Stubber.unstubs_find_for(klass)}
32
+ @@stubbed = []
33
+ end
34
+
35
+ def self.all
36
+ @@pool
37
+ end
38
+
39
+ def self.add_plant klass, instance
40
+ @@plants[klass] = instance
41
+ end
42
+
43
+ def self.plants
44
+ @@plants
45
+ end
46
+
47
+ def self.reload
48
+ load "#{RAILS_ROOT}/test/plants.rb" if Plant.plants.empty?
49
+ end
50
+
51
+ def self.pool symbol
52
+ instance = plants[symbol] || plants[symbol.to_s.camelize.constantize]
53
+ yield instance if block_given?
54
+ @@pool[instance.class] ||= []
55
+ @@pool[instance.class] << instance
56
+ instance
57
+ end
58
+
59
+ def self.destroy
60
+ @@pool = {}
61
+ @@plants = {}
62
+ @@map = {}
63
+ @@sequences = {}
64
+ @@stubbed = []
65
+ end
66
+
67
+ def self.sequence symbol, &proc
68
+ @@sequences[symbol] = {:lambda => proc, :index => 0}
69
+ end
70
+
71
+ def self.next symbol
72
+ @@sequences[symbol][:lambda].call(@@sequences[symbol][:index] += 1)
73
+ end
74
+
75
+ def self.association symbol
76
+ Plant.pool(symbol)
77
+ end
78
+
79
+ end
80
+
81
+ def Plant symbol, args={}
82
+ Plant.reload
83
+ Plant.pool(symbol) do |instance|
84
+ args.each {|key, value| instance.send(key.to_s + '=', value)}
85
+ end
86
+ end
87
+
88
+
89
+
90
+
data/lib/setup.rb ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'mocha' #must put there even if mocha is not used ... else mocha override these aliasings when it's required in test file.
3
+ rescue LoadError
4
+ end
5
+
6
+ module Test
7
+ module Unit
8
+ class TestCase
9
+ alias_method :original_run, :run
10
+
11
+ def run(result,&block)
12
+ Plant.destroy
13
+ original_run(result,&block)
14
+ Plant.unstub_find_for_each_class
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ if defined?(ActiveSupport::TestCase)
21
+ module ActiveSupport
22
+ class TestCase
23
+ alias_method :original_run, :run
24
+
25
+ def run(result,&block)
26
+ Plant.destroy
27
+ original_run(result,&block)
28
+ Plant.unstub_find_for_each_class
29
+ end
30
+ end
31
+ end
32
+ end
data/lib/stubber.rb ADDED
@@ -0,0 +1,36 @@
1
+ module Plant
2
+ module Stubber
3
+
4
+ def self.stubs_find klass
5
+ class << klass
6
+ alias_method :original_find, :find
7
+
8
+ def find *args
9
+ case args.first
10
+ when :first then Plant::Stubber.find_all(self.name.constantize).first
11
+ when :last then Plant::Stubber.find_all(self.name.constantize).last
12
+ when :all then Plant::Stubber.find_all(self.name.constantize)
13
+ else Plant::Stubber.find(self.name.constantize)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.unstubs_find_for klass
20
+ class << klass
21
+ undef_method :find
22
+ alias_method :find, :original_find
23
+ end
24
+ end
25
+
26
+ def self.find_all klass
27
+ Plant.all[klass] || []
28
+ end
29
+
30
+ def self.find klass
31
+ return nil unless Plant.all[klass]
32
+ Plant.all[klass].size == 1 ? Plant.all[klass].first : Plant.all[klass]
33
+ end
34
+
35
+ end
36
+ end
data/test/help_test.rb ADDED
@@ -0,0 +1,9 @@
1
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(__FILE__), '../') )
2
+
3
+ require 'test/unit'
4
+ require 'plant'
5
+ require 'models/adress'
6
+ require 'models/user'
7
+ require 'models/profile'
8
+ require 'models/customer'
9
+ require 'mocha'
@@ -0,0 +1,12 @@
1
+ class Adress
2
+ attr_accessor :number, :street
3
+
4
+ def initialize args={}
5
+ @street = args[:street]
6
+ @number = args[:number]
7
+ end
8
+
9
+ def self.find *args
10
+ "original_find"
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ class Customer
2
+ attr_accessor :name
3
+
4
+ def self.find *args
5
+ "original_find"
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ class Profile
2
+
3
+ attr_accessor :password
4
+
5
+ def self.find *args
6
+ "original_find"
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class User
2
+
3
+ attr_accessor :name, :age, :adresses, :profile
4
+
5
+ def self.find *args
6
+ "original_find"
7
+ end
8
+ end
data/test/plants.rb ADDED
@@ -0,0 +1,23 @@
1
+ Plant.sequence :email do |n|
2
+ "incognito#{n}@kantena.com"
3
+ end
4
+
5
+ Plant.define :profile do |profile|
6
+ profile.password = "BREIZH!"
7
+ end
8
+
9
+ Plant.define :adress do |adress|
10
+ adress.number = 17
11
+ adress.street = "rue royale"
12
+ end
13
+
14
+ Plant.define :user do |user|
15
+ user.name = "Zorro"
16
+ user.age = 800
17
+ user.profile = Plant.association(:profile)
18
+ user.adresses = [Plant.association(:adress)]
19
+ end
20
+
21
+ Plant.define :customer do |customer|
22
+ end
23
+
@@ -0,0 +1,110 @@
1
+ require 'help_test'
2
+
3
+ class PlantTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ assert_find_is_unstubbed_for_each_class
7
+ Plant(:customer)
8
+ end
9
+
10
+ def test_define_simple_definition
11
+ assert customer = Plant(:customer)
12
+ assert_nil customer.name
13
+ end
14
+
15
+ def test_define_assign_attributes
16
+ user = Plant(:user)
17
+ assert_equal "Zorro", user.name
18
+ assert_equal 800, user.age
19
+ end
20
+
21
+ def test_define_stubs_find_without_parameter
22
+ user = Plant(:user)
23
+ assert_equal user, User.find
24
+ end
25
+
26
+ def test_define_stubs_find_with_array_result
27
+ 2.times { Plant(:user) }
28
+ assert_equal 2, User.find(:all).size
29
+ end
30
+
31
+ def test_define_with_association_has_one
32
+ user = Plant(:user)
33
+ profile = Profile.find
34
+ assert_equal profile, user.profile
35
+ end
36
+
37
+ def test_define_with_association_has_many
38
+ user = Plant(:user)
39
+ assert adresses = user.adresses
40
+ adress = Adress.find
41
+ assert_equal adress, user.adresses.first
42
+ end
43
+
44
+ def test_stubs_find_with_option_all
45
+ user = Plant(:user)
46
+ users = User.find(:all)
47
+ assert_equal [user], users
48
+ end
49
+
50
+ def test_find_all_must_return_an_empty_array_if_no_object
51
+ users = User.find(:all)
52
+ assert_equal [], users
53
+ end
54
+
55
+ def test_stubs_find_with_option_first
56
+ users = 3.times.map { Plant(:user) }
57
+ assert_equal users.first, User.find(:first)
58
+ end
59
+
60
+ def test_stubs_find_with_option_last
61
+ users = 3.times.map { Plant(:user) }
62
+ assert_equal users.last, User.find(:last)
63
+ end
64
+
65
+ def test_mocha_is_not_overidden_with_plant_setup
66
+ Plant.expects(:pool).once
67
+ Plant(:user)
68
+ end
69
+
70
+ def test_create_plant_with_hash_for_values
71
+ adress = Plant(:adress)
72
+ user = Plant(:user, :name => "Marie", :adresses => [adress])
73
+ assert_equal "Marie", user.name
74
+ assert_equal adress, user.adresses.first
75
+ end
76
+
77
+ def test_define_with_class_option
78
+ Plant.define :marie, :class => User do |peter|
79
+ peter.name = "Marie"
80
+ peter.adresses = [Adress.new(:street => "Rue de Brest")]
81
+ end
82
+ marie = Plant(:marie)
83
+ assert_equal "Marie", marie.name
84
+ assert_equal "Rue de Brest", marie.adresses.first.street
85
+ end
86
+
87
+ def test_plants_are_reloaded_and_4_plants_are_defined
88
+ assert_equal 4, Plant.plants.size
89
+ end
90
+
91
+ def test_define_with_dependent_attribute
92
+ Plant.define :user do |user|
93
+ user.name = "Marie"
94
+ user.adresses = [Adress.new(:street => "Rue de #{user.name}")]
95
+ end
96
+ assert_equal "Rue de Marie", Plant(:user).adresses.first.street
97
+ end
98
+
99
+ def test_plant_sequences
100
+ assert_equal "incognito1@kantena.com", Plant.next(:email)
101
+ assert_equal "incognito2@kantena.com", Plant.next(:email)
102
+ end
103
+
104
+ private
105
+
106
+ def assert_find_is_unstubbed_for_each_class
107
+ [Adress, Customer, Profile, User].each {|klass| assert_equal "original_find", klass.find }
108
+ end
109
+
110
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: factory_boy
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 1
10
+ version: 1.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Philippe Cantin
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-01 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Factory Girl with database accesses stubbed
23
+ email:
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.rdoc
30
+ files:
31
+ - lib/factory_boy.rb
32
+ - lib/plant.rb
33
+ - lib/setup.rb
34
+ - lib/stubber.rb
35
+ - README.rdoc
36
+ - test/help_test.rb
37
+ - test/models/adress.rb
38
+ - test/models/customer.rb
39
+ - test/models/profile.rb
40
+ - test/models/user.rb
41
+ - test/plants.rb
42
+ - test/test_plant.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/anoiaque/factory_boy
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options: []
49
+
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.7
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Create fixtures for unit testing as in Factory Girl but without database usage.
77
+ test_files:
78
+ - test/help_test.rb
79
+ - test/models/adress.rb
80
+ - test/models/customer.rb
81
+ - test/models/profile.rb
82
+ - test/models/user.rb
83
+ - test/plants.rb
84
+ - test/test_plant.rb