factory_girl 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/README.textile +105 -0
- data/Rakefile +69 -0
- data/lib/factory_girl.rb +12 -0
- data/lib/factory_girl/attribute_proxy.rb +92 -0
- data/lib/factory_girl/factory.rb +216 -0
- data/lib/factory_girl/sequence.rb +17 -0
- data/test/attribute_proxy_test.rb +101 -0
- data/test/factory_test.rb +333 -0
- data/test/integration_test.rb +143 -0
- data/test/models.rb +32 -0
- data/test/sequence_test.rb +29 -0
- data/test/test_helper.rb +10 -0
- metadata +82 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 Joe Ferris and thoughtbot, inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
= factory_girl
|
2
|
+
|
3
|
+
written by Joe Ferris <jferris@thoughtbot.com>
|
4
|
+
thanks to Tammer Saleh, Dan Croak, and Jon Yurek of thoughtbot, inc.
|
5
|
+
Copyright 2008 Joe Ferris and thoughtbot, inc.
|
6
|
+
|
7
|
+
== Defining factories
|
8
|
+
|
9
|
+
# This will guess the User class
|
10
|
+
Factory.define :user do |u|
|
11
|
+
u.first_name 'John'
|
12
|
+
u.last_name 'Doe'
|
13
|
+
u.admin false
|
14
|
+
end
|
15
|
+
|
16
|
+
# This will use the User class (Admin would have been guessed)
|
17
|
+
Factory.define :admin, :class => User do |u|
|
18
|
+
u.first_name 'Admin'
|
19
|
+
u.last_name 'User'
|
20
|
+
u.admin true
|
21
|
+
end
|
22
|
+
|
23
|
+
It is recommended that you create a test/factories.rb file and define your
|
24
|
+
factories there. This file can be included from test_helper or directly from
|
25
|
+
your test files. Don't forget:
|
26
|
+
require 'factory_girl'
|
27
|
+
|
28
|
+
== Lazy Attributes
|
29
|
+
|
30
|
+
Most attributes can be added using static values that are evaluated when the
|
31
|
+
factory is defined, but some attributes (such as associations and other
|
32
|
+
attributes that must be dynamically generated) will need values assigned each
|
33
|
+
time an instance is generated. These "lazy" attributes can be added by passing
|
34
|
+
a block instead of a parameter:
|
35
|
+
|
36
|
+
Factory.define :user do |u|
|
37
|
+
# ...
|
38
|
+
u.activation_code { User.generate_activation_code }
|
39
|
+
end
|
40
|
+
|
41
|
+
== Dependent Attributes
|
42
|
+
|
43
|
+
Some attributes may need to be generated based on the values of other
|
44
|
+
attributes. This can be done by calling the attribute name on
|
45
|
+
Factory::AttributeProxy, which is yielded to lazy attribute blocks:
|
46
|
+
|
47
|
+
Factory.define :user do |u|
|
48
|
+
u.first_name 'Joe'
|
49
|
+
u.last_name 'Blow'
|
50
|
+
u.email {|a| "#{a.first_name}.#{a.last_name}@example.com".downcase }
|
51
|
+
end
|
52
|
+
|
53
|
+
Factory(:user, :last_name => 'Doe').email
|
54
|
+
# => "joe.doe@example.com"
|
55
|
+
|
56
|
+
== Associations
|
57
|
+
|
58
|
+
Associated instances can be generated by using the association method when
|
59
|
+
defining a lazy attribute:
|
60
|
+
|
61
|
+
Factory.define :post do |p|
|
62
|
+
# ...
|
63
|
+
p.author {|author| author.association(:user, :last_name => 'Writely') }
|
64
|
+
end
|
65
|
+
|
66
|
+
When using the association method, the same build strategy (build, create, or attributes_for) will be used for all generated instances:
|
67
|
+
|
68
|
+
# Builds and saves a User and a Post
|
69
|
+
post = Factory(:post)
|
70
|
+
post.new_record? # => false
|
71
|
+
post.author.new_record # => false
|
72
|
+
|
73
|
+
# Builds but does not save a User and a Post
|
74
|
+
Factory.build(:post)
|
75
|
+
post.new_record? # => true
|
76
|
+
post.author.new_record # => true
|
77
|
+
|
78
|
+
== Sequences
|
79
|
+
|
80
|
+
Unique values in a specific format (for example, e-mail addresses) can be
|
81
|
+
generated using sequences. Sequences are defined by calling Factory.sequence,
|
82
|
+
and values in a sequence are generated by calling Factory.next:
|
83
|
+
|
84
|
+
# Defines a new sequence
|
85
|
+
Factory.sequence :email do |n|
|
86
|
+
"person#{n}@example.com"
|
87
|
+
end
|
88
|
+
|
89
|
+
Factory.next :email
|
90
|
+
# => "person1@example.com"
|
91
|
+
|
92
|
+
Factory.next :email
|
93
|
+
# => "person2@example.com"
|
94
|
+
|
95
|
+
== Using factories
|
96
|
+
|
97
|
+
# Build and save a User instance
|
98
|
+
Factory(:user)
|
99
|
+
|
100
|
+
# Build a User instance and override the first_name property
|
101
|
+
Factory.build(:user, :first_name => 'Joe')
|
102
|
+
|
103
|
+
# Return an attributes Hash that can be used to build a User instance
|
104
|
+
attrs = Factory.attributes_for(:user)
|
105
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require 'date'
|
7
|
+
|
8
|
+
desc 'Default: run unit tests.'
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
desc 'Test the factory_girl plugin.'
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'lib'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = true
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Generate documentation for the factory_girl plugin.'
|
19
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
20
|
+
rdoc.rdoc_dir = 'rdoc'
|
21
|
+
rdoc.title = 'Factory Girl'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source' << "--main" << "README.textile"
|
23
|
+
rdoc.rdoc_files.include('README.textile')
|
24
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Update documentation on website'
|
28
|
+
task :sync_docs => 'rdoc' do
|
29
|
+
`rsync -ave ssh rdoc/ dev@dev.thoughtbot.com:/home/dev/www/dev.thoughtbot.com/factory_girl`
|
30
|
+
end
|
31
|
+
|
32
|
+
spec = Gem::Specification.new do |s|
|
33
|
+
s.name = %q{factory_girl}
|
34
|
+
s.version = "1.1"
|
35
|
+
s.summary = %q{factory_girl provides a framework and DSL for defining and
|
36
|
+
using model instance factories.}
|
37
|
+
s.description = %q{factory_girl provides a framework and DSL for defining and
|
38
|
+
using factories - less error-prone, more explicit, and
|
39
|
+
all-around easier to work with than fixtures.}
|
40
|
+
|
41
|
+
s.files = FileList['[A-Z]*', 'lib/**/*.rb', 'test/**/*.rb']
|
42
|
+
s.require_path = 'lib'
|
43
|
+
s.test_files = Dir[*['test/**/*_test.rb']]
|
44
|
+
|
45
|
+
s.has_rdoc = true
|
46
|
+
s.extra_rdoc_files = ["README.textile"]
|
47
|
+
s.rdoc_options = ['--line-numbers', '--inline-source', "--main", "README.textile"]
|
48
|
+
|
49
|
+
s.authors = ["Joe Ferris"]
|
50
|
+
s.email = %q{jferris@thoughtbot.com}
|
51
|
+
|
52
|
+
s.platform = Gem::Platform::RUBY
|
53
|
+
s.add_dependency(%q<activesupport>, [">= 1.0"])
|
54
|
+
end
|
55
|
+
|
56
|
+
Rake::GemPackageTask.new spec do |pkg|
|
57
|
+
pkg.need_tar = true
|
58
|
+
pkg.need_zip = true
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Clean files generated by rake tasks"
|
62
|
+
task :clobber => [:clobber_rdoc, :clobber_package]
|
63
|
+
|
64
|
+
desc "Generate a gemspec file"
|
65
|
+
task :gemspec do
|
66
|
+
File.open("#{spec.name}.gemspec", 'w') do |f|
|
67
|
+
f.write spec.to_ruby
|
68
|
+
end
|
69
|
+
end
|
data/lib/factory_girl.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'activesupport'
|
2
|
+
require 'factory_girl/factory'
|
3
|
+
require 'factory_girl/attribute_proxy'
|
4
|
+
require 'factory_girl/sequence'
|
5
|
+
|
6
|
+
# Shortcut for Factory.create.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# Factory(:user, :name => 'Joe')
|
10
|
+
def Factory (name, attrs = {})
|
11
|
+
Factory.create(name, attrs)
|
12
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class Factory
|
2
|
+
|
3
|
+
class AttributeProxy
|
4
|
+
|
5
|
+
attr_accessor :factory, :attribute_name, :strategy, :current_values #:nodoc:
|
6
|
+
|
7
|
+
def initialize (factory, attr, strategy, values) #:nodoc:
|
8
|
+
@factory = factory
|
9
|
+
@attribute_name = attr
|
10
|
+
@strategy = strategy
|
11
|
+
@current_values = values
|
12
|
+
end
|
13
|
+
|
14
|
+
# Generates an association using the current build strategy.
|
15
|
+
#
|
16
|
+
# Arguments:
|
17
|
+
# name: (Symbol)
|
18
|
+
# The name of the factory that should be used to generate this
|
19
|
+
# association.
|
20
|
+
# attributes: (Hash)
|
21
|
+
# A hash of attributes that should be overridden for this association.
|
22
|
+
#
|
23
|
+
# Returns:
|
24
|
+
# The generated association for the current build strategy. Note that
|
25
|
+
# assocaitions are not generated for the attributes_for strategy. Returns
|
26
|
+
# nil in this case.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
#
|
30
|
+
# Factory.define :user do |f|
|
31
|
+
# # ...
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# Factory.define :post do |f|
|
35
|
+
# # ...
|
36
|
+
# f.author {|a| a.association :user, :name => 'Joe' }
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# # Builds (but doesn't save) a Post and a User
|
40
|
+
# Factory.build(:post)
|
41
|
+
#
|
42
|
+
# # Builds and saves a User, builds a Post, assigns the User to the
|
43
|
+
# # author association, and saves the User.
|
44
|
+
# Factory.create(:post)
|
45
|
+
#
|
46
|
+
def association (name, attributes = {})
|
47
|
+
if strategy == :attributes_for
|
48
|
+
nil
|
49
|
+
else
|
50
|
+
Factory.send(strategy, name, attributes)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the value for specified attribute. A value will only be available
|
55
|
+
# if it was overridden when calling the factory, or if a value is added
|
56
|
+
# earlier in the definition of the factory.
|
57
|
+
#
|
58
|
+
# Arguments:
|
59
|
+
# attribute: (Symbol)
|
60
|
+
# The attribute whose value should be returned.
|
61
|
+
#
|
62
|
+
# Returns:
|
63
|
+
# The value of the requested attribute. (Object)
|
64
|
+
def value_for (attribute)
|
65
|
+
unless current_values.key?(attribute)
|
66
|
+
raise ArgumentError, "No such attribute: #{attribute.inspect}"
|
67
|
+
end
|
68
|
+
current_values[attribute]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Undefined methods are delegated to value_for, which means that:
|
72
|
+
#
|
73
|
+
# Factory.define :user do |f|
|
74
|
+
# f.first_name 'Ben'
|
75
|
+
# f.last_name {|a| a.value_for(:first_name) }
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# and:
|
79
|
+
#
|
80
|
+
# Factory.define :user do |f|
|
81
|
+
# f.first_name 'Ben'
|
82
|
+
# f.last_name {|a| a.first_name }
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# are equivilent.
|
86
|
+
def method_missing (name, *args, &block)
|
87
|
+
current_values[name]
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
class Factory
|
2
|
+
|
3
|
+
cattr_accessor :factories, :sequences #:nodoc:
|
4
|
+
self.factories = {}
|
5
|
+
self.sequences = {}
|
6
|
+
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
# Defines a new factory that can be used by the build strategies (create and
|
10
|
+
# build) to build new objects.
|
11
|
+
#
|
12
|
+
# Arguments:
|
13
|
+
# name: (Symbol)
|
14
|
+
# A unique name used to identify this factory.
|
15
|
+
# options: (Hash)
|
16
|
+
# class: the class that will be used when generating instances for this
|
17
|
+
# factory. If not specified, the class will be guessed from the
|
18
|
+
# factory name.
|
19
|
+
#
|
20
|
+
# Yields:
|
21
|
+
# The newly created factory (Factory)
|
22
|
+
def self.define (name, options = {})
|
23
|
+
instance = Factory.new(name, options)
|
24
|
+
yield(instance)
|
25
|
+
self.factories[name] = instance
|
26
|
+
end
|
27
|
+
|
28
|
+
# Defines a new sequence that can be used to generate unique values in a specific format.
|
29
|
+
#
|
30
|
+
# Arguments:
|
31
|
+
# name: (Symbol)
|
32
|
+
# A unique name for this sequence. This name will be referenced when
|
33
|
+
# calling next to generate new values from this sequence.
|
34
|
+
# block: (Proc)
|
35
|
+
# The code to generate each value in the sequence. This block will be
|
36
|
+
# called with a unique number each time a value in the sequence is to be
|
37
|
+
# generated. The block should return the generated value for the
|
38
|
+
# sequence.
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
#
|
42
|
+
# Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
|
43
|
+
def self.sequence (name, &block)
|
44
|
+
self.sequences[name] = Sequence.new(&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Generates and returns the next value in a sequence.
|
48
|
+
#
|
49
|
+
# Arguments:
|
50
|
+
# name: (Symbol)
|
51
|
+
# The name of the sequence that a value should be generated for.
|
52
|
+
#
|
53
|
+
# Returns:
|
54
|
+
# The next value in the sequence. (Object)
|
55
|
+
def self.next (sequence)
|
56
|
+
unless self.sequences.key?(sequence)
|
57
|
+
raise "No such sequence: #{sequence}"
|
58
|
+
end
|
59
|
+
|
60
|
+
self.sequences[sequence].next
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_class #:nodoc:
|
64
|
+
@build_class ||= @options[:class] || name.to_s.classify.constantize
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize (name, options = {}) #:nodoc:
|
68
|
+
options.assert_valid_keys(:class)
|
69
|
+
@name = name
|
70
|
+
@options = options
|
71
|
+
|
72
|
+
@static_attributes = {}
|
73
|
+
@lazy_attribute_blocks = {}
|
74
|
+
@lazy_attribute_names = []
|
75
|
+
end
|
76
|
+
|
77
|
+
# Adds an attribute that should be assigned on generated instances for this
|
78
|
+
# factory.
|
79
|
+
#
|
80
|
+
# This method should be called with either a value or block, but not both. If
|
81
|
+
# called with a block, the attribute will be generated "lazily," whenever an
|
82
|
+
# instance is generated. Lazy attribute blocks will not be called if that
|
83
|
+
# attribute is overriden for a specific instance.
|
84
|
+
#
|
85
|
+
# When defining lazy attributes, an instance of Factory::AttributeProxy will
|
86
|
+
# be yielded, allowing associations to be built using the correct build
|
87
|
+
# strategy.
|
88
|
+
#
|
89
|
+
# Arguments:
|
90
|
+
# name: (Symbol)
|
91
|
+
# The name of this attribute. This will be assigned using :"#{name}=" for
|
92
|
+
# generated instances.
|
93
|
+
# value: (Object)
|
94
|
+
# If no block is given, this value will be used for this attribute.
|
95
|
+
def add_attribute (name, value = nil, &block)
|
96
|
+
if block_given?
|
97
|
+
unless value.nil?
|
98
|
+
raise ArgumentError, "Both value and block given"
|
99
|
+
end
|
100
|
+
@lazy_attribute_blocks[name] = block
|
101
|
+
@lazy_attribute_names << name
|
102
|
+
else
|
103
|
+
@static_attributes[name] = value
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Calls add_attribute using the missing method name as the name of the
|
108
|
+
# attribute, so that:
|
109
|
+
#
|
110
|
+
# Factory.define :user do |f|
|
111
|
+
# f.name 'Billy Idol'
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# and:
|
115
|
+
#
|
116
|
+
# Factory.define :user do |f|
|
117
|
+
# f.add_attribute :user, 'Billy Idol'
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# are equivilent.
|
121
|
+
def method_missing (name, *args, &block)
|
122
|
+
add_attribute(name, *args, &block)
|
123
|
+
end
|
124
|
+
|
125
|
+
def attributes_for (attrs = {}) #:nodoc:
|
126
|
+
build_attributes_hash(attrs, :attributes_for)
|
127
|
+
end
|
128
|
+
|
129
|
+
def build (attrs = {}) #:nodoc:
|
130
|
+
build_instance(attrs, :build)
|
131
|
+
end
|
132
|
+
|
133
|
+
def create (attrs = {}) #:nodoc:
|
134
|
+
instance = build_instance(attrs, :create)
|
135
|
+
instance.save!
|
136
|
+
instance
|
137
|
+
end
|
138
|
+
|
139
|
+
class << self
|
140
|
+
|
141
|
+
# Generates and returns a Hash of attributes from this factory. Attributes
|
142
|
+
# can be individually overridden by passing in a Hash of attribute => value
|
143
|
+
# pairs.
|
144
|
+
#
|
145
|
+
# Arguments:
|
146
|
+
# attrs: (Hash)
|
147
|
+
# Attributes to overwrite for this set.
|
148
|
+
#
|
149
|
+
# Returns:
|
150
|
+
# A set of attributes that can be used to build an instance of the class
|
151
|
+
# this factory generates. (Hash)
|
152
|
+
def attributes_for (name, attrs = {})
|
153
|
+
factory_by_name(name).attributes_for(attrs)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Generates and returns an instance from this factory. Attributes can be
|
157
|
+
# individually overridden by passing in a Hash of attribute => value pairs.
|
158
|
+
#
|
159
|
+
# Arguments:
|
160
|
+
# attrs: (Hash)
|
161
|
+
# See attributes_for
|
162
|
+
#
|
163
|
+
# Returns:
|
164
|
+
# An instance of the class this factory generates, with generated
|
165
|
+
# attributes assigned.
|
166
|
+
def build (name, attrs = {})
|
167
|
+
factory_by_name(name).build(attrs)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Generates, saves, and returns an instance from this factory. Attributes can
|
171
|
+
# be individually overridden by passing in a Hash of attribute => value
|
172
|
+
# pairs.
|
173
|
+
#
|
174
|
+
# If the instance is not valid, an ActiveRecord::Invalid exception will be
|
175
|
+
# raised.
|
176
|
+
#
|
177
|
+
# Arguments:
|
178
|
+
# attrs: (Hash)
|
179
|
+
# See attributes_for
|
180
|
+
#
|
181
|
+
# Returns:
|
182
|
+
# A saved instance of the class this factory generates, with generated
|
183
|
+
# attributes assigned.
|
184
|
+
def create (name, attrs = {})
|
185
|
+
factory_by_name(name).create(attrs)
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
def factory_by_name (name)
|
191
|
+
factories[name] or raise ArgumentError.new("No such factory: #{name.inspect}")
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def build_attributes_hash (override, strategy)
|
199
|
+
result = @static_attributes.merge(override)
|
200
|
+
@lazy_attribute_names.each do |name|
|
201
|
+
proxy = AttributeProxy.new(self, name, strategy, result)
|
202
|
+
result[name] = @lazy_attribute_blocks[name].call(proxy) unless override.key?(name)
|
203
|
+
end
|
204
|
+
result
|
205
|
+
end
|
206
|
+
|
207
|
+
def build_instance (override, strategy)
|
208
|
+
instance = build_class.new
|
209
|
+
attrs = build_attributes_hash(override, strategy)
|
210
|
+
attrs.each do |attr, value|
|
211
|
+
instance.send(:"#{attr}=", value)
|
212
|
+
end
|
213
|
+
instance
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
class AttributeProxyTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "an association proxy" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@factory = mock('factory')
|
9
|
+
@attr = :user
|
10
|
+
@attrs = { :first_name => 'John' }
|
11
|
+
@strategy = :create
|
12
|
+
@proxy = Factory::AttributeProxy.new(@factory, @attr, @strategy, @attrs)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "have a factory" do
|
16
|
+
assert_equal @factory, @proxy.factory
|
17
|
+
end
|
18
|
+
|
19
|
+
should "have an attribute name" do
|
20
|
+
assert_equal @attr, @proxy.attribute_name
|
21
|
+
end
|
22
|
+
|
23
|
+
should "have a build strategy" do
|
24
|
+
assert_equal @strategy, @proxy.strategy
|
25
|
+
end
|
26
|
+
|
27
|
+
should "have attributes" do
|
28
|
+
assert_equal @attrs, @proxy.current_values
|
29
|
+
end
|
30
|
+
|
31
|
+
context "building an association" do
|
32
|
+
|
33
|
+
setup do
|
34
|
+
@association = mock('built-user')
|
35
|
+
@name = :user
|
36
|
+
@attribs = { :first_name => 'Billy' }
|
37
|
+
|
38
|
+
Factory.stubs(@strategy).returns(@association)
|
39
|
+
end
|
40
|
+
|
41
|
+
should "delegate to the appropriate method on Factory" do
|
42
|
+
Factory.expects(@strategy).with(@name, @attribs).returns(@association)
|
43
|
+
@proxy.association(@name, @attribs)
|
44
|
+
end
|
45
|
+
|
46
|
+
should "return the built association" do
|
47
|
+
assert_equal @association, @proxy.association(@name)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context "building an association using the attributes_for strategy" do
|
53
|
+
|
54
|
+
setup do
|
55
|
+
@strategy = :attributes_for
|
56
|
+
@proxy = Factory::AttributeProxy.new(@factory, @attr, @strategy, @attrs)
|
57
|
+
end
|
58
|
+
|
59
|
+
should "not build the association" do
|
60
|
+
Factory.expects(@strategy).never
|
61
|
+
@proxy.association(:user)
|
62
|
+
end
|
63
|
+
|
64
|
+
should "return nil for the association" do
|
65
|
+
Factory.stubs(@strategy).returns(:user)
|
66
|
+
assert_nil @proxy.association(:user)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
context "fetching the value of an attribute" do
|
72
|
+
|
73
|
+
setup do
|
74
|
+
@attr = :first_name
|
75
|
+
end
|
76
|
+
|
77
|
+
should "return the correct value" do
|
78
|
+
assert_equal @attrs[@attr], @proxy.value_for(@attr)
|
79
|
+
end
|
80
|
+
|
81
|
+
should "call value_for for undefined methods" do
|
82
|
+
assert_equal @attrs[@attr], @proxy.send(@attr)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
context "fetching the value of an undefined attribute" do
|
88
|
+
|
89
|
+
setup do
|
90
|
+
@attr = :beachball
|
91
|
+
end
|
92
|
+
|
93
|
+
should "raise an ArgumentError" do
|
94
|
+
assert_raise(ArgumentError) { @proxy.value_for(@attr) }
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,333 @@
|
|
1
|
+
require(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
class FactoryTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def self.should_instantiate_class
|
6
|
+
|
7
|
+
should "instantiate the build class" do
|
8
|
+
assert_kind_of @class, @instance
|
9
|
+
end
|
10
|
+
|
11
|
+
should "assign attributes on the instance" do
|
12
|
+
assert_equal @first_name, @instance.first_name
|
13
|
+
assert_equal @last_name, @instance.last_name
|
14
|
+
end
|
15
|
+
|
16
|
+
should "override attributes using the passed hash" do
|
17
|
+
@value = 'Davis'
|
18
|
+
@instance = @factory.build(:first_name => @value)
|
19
|
+
assert_equal @value, @instance.first_name
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
context "defining a factory" do
|
25
|
+
|
26
|
+
setup do
|
27
|
+
@name = :user
|
28
|
+
@factory = mock('factory')
|
29
|
+
@options = { :class => 'magic' }
|
30
|
+
Factory.stubs(:new).returns(@factory)
|
31
|
+
end
|
32
|
+
|
33
|
+
should "create a new factory using the specified name and options" do
|
34
|
+
Factory.expects(:new).with(@name, @options)
|
35
|
+
Factory.define(@name, @options) {|f| }
|
36
|
+
end
|
37
|
+
|
38
|
+
should "pass the factory do the block" do
|
39
|
+
yielded = nil
|
40
|
+
Factory.define(@name) do |y|
|
41
|
+
yielded = y
|
42
|
+
end
|
43
|
+
assert_equal @factory, yielded
|
44
|
+
end
|
45
|
+
|
46
|
+
should "add the factory to the list of factories" do
|
47
|
+
Factory.define(@name) {|f| }
|
48
|
+
assert_equal Factory.factories[@name],
|
49
|
+
@factory,
|
50
|
+
"Factories: #{Factory.factories.inspect}"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context "defining a sequence" do
|
56
|
+
|
57
|
+
setup do
|
58
|
+
@sequence = mock('sequence')
|
59
|
+
@name = :count
|
60
|
+
Factory::Sequence.stubs(:new).returns(@sequence)
|
61
|
+
end
|
62
|
+
|
63
|
+
should "create a new sequence" do
|
64
|
+
Factory::Sequence.expects(:new).with().returns(@sequence)
|
65
|
+
Factory.sequence(@name)
|
66
|
+
end
|
67
|
+
|
68
|
+
should "use the supplied block as the sequence generator" do
|
69
|
+
Factory::Sequence.stubs(:new).yields(1)
|
70
|
+
yielded = false
|
71
|
+
Factory.sequence(@name) {|n| yielded = true }
|
72
|
+
assert yielded
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
context "a factory" do
|
78
|
+
|
79
|
+
setup do
|
80
|
+
@name = :user
|
81
|
+
@class = User
|
82
|
+
@factory = Factory.new(@name)
|
83
|
+
end
|
84
|
+
|
85
|
+
should "have a name" do
|
86
|
+
assert_equal @name, @factory.name
|
87
|
+
end
|
88
|
+
|
89
|
+
should "have a build class" do
|
90
|
+
assert_equal @class, @factory.build_class
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when adding an attribute with a value parameter" do
|
94
|
+
|
95
|
+
setup do
|
96
|
+
@attr = :name
|
97
|
+
@value = 'Elvis lives!'
|
98
|
+
@factory.add_attribute(@attr, @value)
|
99
|
+
end
|
100
|
+
|
101
|
+
should "include that value in the generated attributes hash" do
|
102
|
+
assert_equal @value, @factory.attributes_for[@attr]
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when adding an attribute with a block" do
|
108
|
+
|
109
|
+
setup do
|
110
|
+
@attr = :name
|
111
|
+
@attrs = {}
|
112
|
+
@proxy = mock('attr-proxy')
|
113
|
+
Factory::AttributeProxy.stubs(:new).returns(@proxy)
|
114
|
+
end
|
115
|
+
|
116
|
+
should "not evaluate the block when the attribute is added" do
|
117
|
+
@factory.add_attribute(@attr) { flunk }
|
118
|
+
end
|
119
|
+
|
120
|
+
should "evaluate the block when attributes are generated" do
|
121
|
+
called = false
|
122
|
+
@factory.add_attribute(@attr) do
|
123
|
+
called = true
|
124
|
+
end
|
125
|
+
@factory.attributes_for
|
126
|
+
assert called
|
127
|
+
end
|
128
|
+
|
129
|
+
should "use the result of the block as the value of the attribute" do
|
130
|
+
value = "Watch out for snakes!"
|
131
|
+
@factory.add_attribute(@attr) { value }
|
132
|
+
assert_equal value, @factory.attributes_for[@attr]
|
133
|
+
end
|
134
|
+
|
135
|
+
should "build an attribute proxy" do
|
136
|
+
Factory::AttributeProxy.expects(:new).with(@factory, @attr, :attributes_for, @attrs)
|
137
|
+
@factory.add_attribute(@attr) {}
|
138
|
+
@factory.attributes_for
|
139
|
+
end
|
140
|
+
|
141
|
+
should "yield an attribute proxy to the block" do
|
142
|
+
yielded = nil
|
143
|
+
@factory.add_attribute(@attr) {|y| yielded = y }
|
144
|
+
@factory.attributes_for
|
145
|
+
assert_equal @proxy, yielded
|
146
|
+
end
|
147
|
+
|
148
|
+
context "when other attributes have previously been defined" do
|
149
|
+
|
150
|
+
setup do
|
151
|
+
@attr = :unimportant
|
152
|
+
@attrs = {
|
153
|
+
:one => 'whatever',
|
154
|
+
:another => 'soup'
|
155
|
+
}
|
156
|
+
@factory.add_attribute(:one, 'whatever')
|
157
|
+
@factory.add_attribute(:another) { 'soup' }
|
158
|
+
@factory.add_attribute(@attr) {}
|
159
|
+
end
|
160
|
+
|
161
|
+
should "provide previously set attributes" do
|
162
|
+
Factory::AttributeProxy.expects(:new).with(@factory, @attr, :attributes_for, @attrs)
|
163
|
+
@factory.attributes_for
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
should "add an attribute using the method name when passed an undefined method" do
|
171
|
+
@attr = :first_name
|
172
|
+
@value = 'Sugar'
|
173
|
+
@factory.send(@attr, @value)
|
174
|
+
assert_equal @value, @factory.attributes_for[@attr]
|
175
|
+
end
|
176
|
+
|
177
|
+
should "not allow attributes to be added with both a value parameter and a block" do
|
178
|
+
assert_raise(ArgumentError) do
|
179
|
+
@factory.add_attribute(:name, 'value') {}
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context "when overriding generated attributes with a hash" do
|
184
|
+
|
185
|
+
setup do
|
186
|
+
@attr = :name
|
187
|
+
@value = 'The price is right!'
|
188
|
+
@hash = { @attr => @value }
|
189
|
+
end
|
190
|
+
|
191
|
+
should "return the overridden value in the generated attributes" do
|
192
|
+
@factory.add_attribute(@attr, 'The price is wrong, Bob!')
|
193
|
+
assert_equal @value, @factory.attributes_for(@hash)[@attr]
|
194
|
+
end
|
195
|
+
|
196
|
+
should "not call a lazy attribute block for an overridden attribute" do
|
197
|
+
@factory.add_attribute(@attr) { flunk }
|
198
|
+
@factory.attributes_for(@hash)
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
should "guess the build class from the factory name" do
|
204
|
+
assert_equal User, @factory.build_class
|
205
|
+
end
|
206
|
+
|
207
|
+
context "when defined with a custom class" do
|
208
|
+
|
209
|
+
setup do
|
210
|
+
@class = User
|
211
|
+
@factory = Factory.new(:author, :class => @class)
|
212
|
+
end
|
213
|
+
|
214
|
+
should "use the specified class as the build class" do
|
215
|
+
assert_equal @class, @factory.build_class
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
context "with some attributes added" do
|
221
|
+
|
222
|
+
setup do
|
223
|
+
@first_name = 'Billy'
|
224
|
+
@last_name = 'Idol'
|
225
|
+
@email = 'test@something.com'
|
226
|
+
|
227
|
+
@factory.add_attribute(:first_name, @first_name)
|
228
|
+
@factory.add_attribute(:last_name, @last_name)
|
229
|
+
@factory.add_attribute(:email, @email)
|
230
|
+
end
|
231
|
+
|
232
|
+
context "when building an instance" do
|
233
|
+
|
234
|
+
setup do
|
235
|
+
@instance = @factory.build
|
236
|
+
end
|
237
|
+
|
238
|
+
should_instantiate_class
|
239
|
+
|
240
|
+
should "not save the instance" do
|
241
|
+
assert @instance.new_record?
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
context "when creating an instance" do
|
247
|
+
|
248
|
+
setup do
|
249
|
+
@instance = @factory.create
|
250
|
+
end
|
251
|
+
|
252
|
+
should_instantiate_class
|
253
|
+
|
254
|
+
should "save the instance" do
|
255
|
+
assert !@instance.new_record?
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
should "raise an ActiveRecord::RecordInvalid error for invalid instances" do
|
261
|
+
assert_raise(ActiveRecord::RecordInvalid) do
|
262
|
+
@factory.create(:first_name => nil)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
|
270
|
+
context "Factory class" do
|
271
|
+
|
272
|
+
setup do
|
273
|
+
@name = :user
|
274
|
+
@attrs = { :last_name => 'Override' }
|
275
|
+
@first_name = 'Johnny'
|
276
|
+
@last_name = 'Winter'
|
277
|
+
@class = User
|
278
|
+
|
279
|
+
Factory.define(@name) do |u|
|
280
|
+
u.first_name @first_name
|
281
|
+
u.last_name { @last_name }
|
282
|
+
u.email 'jwinter@guitar.org'
|
283
|
+
end
|
284
|
+
|
285
|
+
@factory = Factory.factories[@name]
|
286
|
+
end
|
287
|
+
|
288
|
+
[:build, :create, :attributes_for].each do |method|
|
289
|
+
|
290
|
+
should "delegate the #{method} method to the factory instance" do
|
291
|
+
@factory.expects(method).with(@attrs)
|
292
|
+
Factory.send(method, @name, @attrs)
|
293
|
+
end
|
294
|
+
|
295
|
+
should "raise an ArgumentError when #{method} is called with a nonexistant factory" do
|
296
|
+
assert_raise(ArgumentError) { Factory.send(method, :bogus) }
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
should "call the create method from the top-level Factory() method" do
|
302
|
+
@factory.expects(:create).with(@attrs)
|
303
|
+
Factory(@name, @attrs)
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
context "after defining a sequence" do
|
309
|
+
|
310
|
+
setup do
|
311
|
+
@sequence = mock('sequence')
|
312
|
+
@name = :test
|
313
|
+
@value = '1 2 5'
|
314
|
+
|
315
|
+
@sequence. stubs(:next).returns(@value)
|
316
|
+
Factory::Sequence.stubs(:new). returns(@sequence)
|
317
|
+
|
318
|
+
Factory.sequence(@name) {}
|
319
|
+
end
|
320
|
+
|
321
|
+
should "call next on the sequence when sent next" do
|
322
|
+
@sequence.expects(:next)
|
323
|
+
|
324
|
+
Factory.next(@name)
|
325
|
+
end
|
326
|
+
|
327
|
+
should "return the value from the sequence" do
|
328
|
+
assert_equal @value, Factory.next(@name)
|
329
|
+
end
|
330
|
+
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
class IntegrationTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Factory.define :user do |f|
|
7
|
+
f.first_name 'Jimi'
|
8
|
+
f.last_name 'Hendrix'
|
9
|
+
f.admin false
|
10
|
+
f.email {|a| "#{a.first_name}.#{a.last_name}@example.com".downcase }
|
11
|
+
end
|
12
|
+
|
13
|
+
Factory.define :post do |f|
|
14
|
+
f.title 'Test Post'
|
15
|
+
f.author {|a| a.association(:user) }
|
16
|
+
end
|
17
|
+
|
18
|
+
Factory.define :admin, :class => User do |f|
|
19
|
+
f.first_name 'Ben'
|
20
|
+
f.last_name 'Stein'
|
21
|
+
f.admin true
|
22
|
+
f.email { Factory.next(:email) }
|
23
|
+
end
|
24
|
+
|
25
|
+
Factory.sequence :email do |n|
|
26
|
+
"somebody#{n}@example.com"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def teardown
|
31
|
+
Factory.send(:class_variable_get, "@@factories").clear
|
32
|
+
end
|
33
|
+
|
34
|
+
context "a generated attributes hash" do
|
35
|
+
|
36
|
+
setup do
|
37
|
+
@attrs = Factory.attributes_for(:user, :first_name => 'Bill')
|
38
|
+
end
|
39
|
+
|
40
|
+
should "assign all attributes" do
|
41
|
+
assert_equal [:admin, :email, :first_name, :last_name],
|
42
|
+
@attrs.keys.sort {|a, b| a.to_s <=> b.to_s }
|
43
|
+
end
|
44
|
+
|
45
|
+
should "correctly assign lazy, dependent attributes" do
|
46
|
+
assert_equal "bill.hendrix@example.com", @attrs[:email]
|
47
|
+
end
|
48
|
+
|
49
|
+
should "override attrbutes" do
|
50
|
+
assert_equal 'Bill', @attrs[:first_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
should "not assign associations" do
|
54
|
+
assert_nil Factory.attributes_for(:post)[:author]
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
context "a built instance" do
|
60
|
+
|
61
|
+
setup do
|
62
|
+
@instance = Factory.build(:post)
|
63
|
+
end
|
64
|
+
|
65
|
+
should "not be saved" do
|
66
|
+
assert @instance.new_record?
|
67
|
+
end
|
68
|
+
|
69
|
+
should "assign associations" do
|
70
|
+
assert_kind_of User, @instance.author
|
71
|
+
end
|
72
|
+
|
73
|
+
should "not save associations" do
|
74
|
+
assert @instance.author.new_record?
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
context "a created instance" do
|
80
|
+
|
81
|
+
setup do
|
82
|
+
@instance = Factory.create(:post)
|
83
|
+
end
|
84
|
+
|
85
|
+
should "be saved" do
|
86
|
+
assert !@instance.new_record?
|
87
|
+
end
|
88
|
+
|
89
|
+
should "assign associations" do
|
90
|
+
assert_kind_of User, @instance.author
|
91
|
+
end
|
92
|
+
|
93
|
+
should "save associations" do
|
94
|
+
assert !@instance.author.new_record?
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
context "an instance generated by a factory with a custom class name" do
|
100
|
+
|
101
|
+
setup do
|
102
|
+
@instance = Factory.create(:admin)
|
103
|
+
end
|
104
|
+
|
105
|
+
should "use the correct class name" do
|
106
|
+
assert_kind_of User, @instance
|
107
|
+
end
|
108
|
+
|
109
|
+
should "use the correct factory definition" do
|
110
|
+
assert @instance.admin?
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
context "an attribute generated by a sequence" do
|
116
|
+
|
117
|
+
setup do
|
118
|
+
@email = Factory.attributes_for(:admin)[:email]
|
119
|
+
end
|
120
|
+
|
121
|
+
should "match the correct format" do
|
122
|
+
assert_match /^somebody\d+@example\.com$/, @email
|
123
|
+
end
|
124
|
+
|
125
|
+
context "after the attribute has already been generated once" do
|
126
|
+
|
127
|
+
setup do
|
128
|
+
@another_email = Factory.attributes_for(:admin)[:email]
|
129
|
+
end
|
130
|
+
|
131
|
+
should "match the correct format" do
|
132
|
+
assert_match /^somebody\d+@example\.com$/, @email
|
133
|
+
end
|
134
|
+
|
135
|
+
should "not be the same as the first generated value" do
|
136
|
+
assert_not_equal @email, @another_email
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
data/test/models.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
ActiveRecord::Base.establish_connection(
|
2
|
+
:adapter => 'sqlite3',
|
3
|
+
:database => File.join(File.dirname(__FILE__), 'test.db')
|
4
|
+
)
|
5
|
+
|
6
|
+
class CreateSchema < ActiveRecord::Migration
|
7
|
+
def self.up
|
8
|
+
create_table :users, :force => true do |t|
|
9
|
+
t.string :first_name
|
10
|
+
t.string :last_name
|
11
|
+
t.string :email
|
12
|
+
t.boolean :admin, :default => false
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table :posts, :force => true do |t|
|
16
|
+
t.string :title
|
17
|
+
t.integer :author_id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
CreateSchema.suppress_messages { CreateSchema.migrate(:up) }
|
23
|
+
|
24
|
+
class User < ActiveRecord::Base
|
25
|
+
validates_presence_of :first_name, :last_name, :email
|
26
|
+
has_many :posts, :foreign_key => 'author_id'
|
27
|
+
end
|
28
|
+
|
29
|
+
class Post < ActiveRecord::Base
|
30
|
+
validates_presence_of :title, :author_id
|
31
|
+
belongs_to :author, :class_name => 'User'
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
class SequenceTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "a sequence" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@sequence = Factory::Sequence.new {|n| "=#{n}" }
|
9
|
+
end
|
10
|
+
|
11
|
+
should "start with a value of 1" do
|
12
|
+
assert_equal "=1", @sequence.next
|
13
|
+
end
|
14
|
+
|
15
|
+
context "after being called" do
|
16
|
+
|
17
|
+
setup do
|
18
|
+
@sequence.next
|
19
|
+
end
|
20
|
+
|
21
|
+
should "use the next value" do
|
22
|
+
assert_equal "=2", @sequence.next
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: factory_girl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "1.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joe Ferris
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-06-06 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.0"
|
24
|
+
version:
|
25
|
+
description: factory_girl provides a framework and DSL for defining and using factories - less error-prone, more explicit, and all-around easier to work with than fixtures.
|
26
|
+
email: jferris@thoughtbot.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.textile
|
33
|
+
files:
|
34
|
+
- LICENSE
|
35
|
+
- Rakefile
|
36
|
+
- README.textile
|
37
|
+
- lib/factory_girl/attribute_proxy.rb
|
38
|
+
- lib/factory_girl/factory.rb
|
39
|
+
- lib/factory_girl/sequence.rb
|
40
|
+
- lib/factory_girl.rb
|
41
|
+
- test/attribute_proxy_test.rb
|
42
|
+
- test/factory_test.rb
|
43
|
+
- test/integration_test.rb
|
44
|
+
- test/models.rb
|
45
|
+
- test/sequence_test.rb
|
46
|
+
- test/test_helper.rb
|
47
|
+
has_rdoc: true
|
48
|
+
homepage:
|
49
|
+
licenses: []
|
50
|
+
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --line-numbers
|
54
|
+
- --inline-source
|
55
|
+
- --main
|
56
|
+
- README.textile
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
requirements: []
|
72
|
+
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.3.5
|
75
|
+
signing_key:
|
76
|
+
specification_version: 2
|
77
|
+
summary: factory_girl provides a framework and DSL for defining and using model instance factories.
|
78
|
+
test_files:
|
79
|
+
- test/attribute_proxy_test.rb
|
80
|
+
- test/factory_test.rb
|
81
|
+
- test/integration_test.rb
|
82
|
+
- test/sequence_test.rb
|