ryanb-factory_girl 1.1.2
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/Changelog +13 -0
- data/LICENSE +19 -0
- data/README.textile +125 -0
- data/Rakefile +68 -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 +72 -0
data/Changelog
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
1.1.2 (June 28, 2008)
|
2
|
+
Removing activespport dependency so there's no conflict with edge rails.
|
3
|
+
|
4
|
+
1.1.1 (June 23, 2008)
|
5
|
+
The attribute "name" no longer requires using #add_attribute
|
6
|
+
|
7
|
+
1.1.0 (June 3, 2008)
|
8
|
+
Added support for dependent attributes
|
9
|
+
Fixed the attributes_for build strategy to not build associations
|
10
|
+
Added support for sequences
|
11
|
+
|
12
|
+
1.0.0 (May 31, 208)
|
13
|
+
First version
|
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,125 @@
|
|
1
|
+
h1. factory_girl
|
2
|
+
|
3
|
+
Written by "Joe Ferris":mailto:jferris@thoughtbot.com.
|
4
|
+
|
5
|
+
Thanks to Tammer Saleh, Dan Croak, and Jon Yurek of thoughtbot, inc.
|
6
|
+
|
7
|
+
Copyright 2008 Joe Ferris and thoughtbot, inc.
|
8
|
+
|
9
|
+
h2. Download
|
10
|
+
|
11
|
+
Github: "Page":http://github.com/thoughtbot/factory_girl/tree/master "Clone":git://github.com/thoughtbot/factory_girl.git
|
12
|
+
|
13
|
+
Gem: <pre>gem install thoughtbot-factory_girl --source http://gems.github.com</pre>
|
14
|
+
|
15
|
+
h2. Defining factories
|
16
|
+
|
17
|
+
<pre><code># This will guess the User class
|
18
|
+
Factory.define :user do |u|
|
19
|
+
u.first_name 'John'
|
20
|
+
u.last_name 'Doe'
|
21
|
+
u.admin false
|
22
|
+
end
|
23
|
+
|
24
|
+
# This will use the User class (Admin would have been guessed)
|
25
|
+
Factory.define :admin, :class => User do |u|
|
26
|
+
u.first_name 'Admin'
|
27
|
+
u.last_name 'User'
|
28
|
+
u.admin true
|
29
|
+
end</code></pre>
|
30
|
+
|
31
|
+
|
32
|
+
It is recommended that you create a test/factories.rb file and define your
|
33
|
+
factories there. This file can be included from test_helper or directly from
|
34
|
+
your test files. Don't forget:
|
35
|
+
<pre><code>require 'factory_girl'</code></pre>
|
36
|
+
|
37
|
+
|
38
|
+
h2. Lazy Attributes
|
39
|
+
|
40
|
+
Most attributes can be added using static values that are evaluated when the
|
41
|
+
factory is defined, but some attributes (such as associations and other
|
42
|
+
attributes that must be dynamically generated) will need values assigned each
|
43
|
+
time an instance is generated. These "lazy" attributes can be added by passing
|
44
|
+
a block instead of a parameter:
|
45
|
+
|
46
|
+
<pre><code>Factory.define :user do |u|
|
47
|
+
# ...
|
48
|
+
u.activation_code { User.generate_activation_code }
|
49
|
+
end</code></pre>
|
50
|
+
|
51
|
+
|
52
|
+
h2. Dependent Attributes
|
53
|
+
|
54
|
+
Some attributes may need to be generated based on the values of other
|
55
|
+
attributes. This can be done by calling the attribute name on
|
56
|
+
Factory::AttributeProxy, which is yielded to lazy attribute blocks:
|
57
|
+
|
58
|
+
<pre><code>Factory.define :user do |u|
|
59
|
+
u.first_name 'Joe'
|
60
|
+
u.last_name 'Blow'
|
61
|
+
u.email {|a| "#{a.first_name}.#{a.last_name}@example.com".downcase }
|
62
|
+
end
|
63
|
+
|
64
|
+
Factory(:user, :last_name => 'Doe').email
|
65
|
+
# => "joe.doe@example.com"</code></pre>
|
66
|
+
|
67
|
+
|
68
|
+
h2. Associations
|
69
|
+
|
70
|
+
Associated instances can be generated by using the association method when
|
71
|
+
defining a lazy attribute:
|
72
|
+
|
73
|
+
<pre><code>Factory.define :post do |p|
|
74
|
+
# ...
|
75
|
+
p.author {|author| author.association(:user, :last_name => 'Writely') }
|
76
|
+
end</code></pre>
|
77
|
+
|
78
|
+
|
79
|
+
When using the association method, the same build strategy (build, create, or attributes_for) will be used for all generated instances:
|
80
|
+
|
81
|
+
<pre><code># Builds and saves a User and a Post
|
82
|
+
post = Factory(:post)
|
83
|
+
post.new_record? # => false
|
84
|
+
post.author.new_record # => false
|
85
|
+
|
86
|
+
# Builds but does not save a User and a Post
|
87
|
+
Factory.build(:post)
|
88
|
+
post.new_record? # => true
|
89
|
+
post.author.new_record # => true</code></pre>
|
90
|
+
|
91
|
+
|
92
|
+
h2. Sequences
|
93
|
+
|
94
|
+
Unique values in a specific format (for example, e-mail addresses) can be
|
95
|
+
generated using sequences. Sequences are defined by calling Factory.sequence,
|
96
|
+
and values in a sequence are generated by calling Factory.next:
|
97
|
+
|
98
|
+
<pre><code># Defines a new sequence
|
99
|
+
Factory.sequence :email do |n|
|
100
|
+
"person#{n}@example.com"
|
101
|
+
end
|
102
|
+
|
103
|
+
Factory.next :email
|
104
|
+
# => "person1@example.com"
|
105
|
+
|
106
|
+
Factory.next :email
|
107
|
+
# => "person2@example.com"</code></pre>
|
108
|
+
|
109
|
+
|
110
|
+
h2. Using factories
|
111
|
+
|
112
|
+
<pre><code># Build and save a User instance
|
113
|
+
Factory(:user)
|
114
|
+
|
115
|
+
# Build a User instance and override the first_name property
|
116
|
+
Factory.build(:user, :first_name => 'Joe')
|
117
|
+
|
118
|
+
# Return an attributes Hash that can be used to build a User instance
|
119
|
+
attrs = Factory.attributes_for(:user)</code></pre>
|
120
|
+
|
121
|
+
h2. More Information
|
122
|
+
|
123
|
+
"Our blog":http://giantrobots.thoughtbot.com
|
124
|
+
|
125
|
+
"factory_girl rdoc":http://dev.thoughtbot.com/factory_girl
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
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.2"
|
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
|
+
end
|
54
|
+
|
55
|
+
Rake::GemPackageTask.new spec do |pkg|
|
56
|
+
pkg.need_tar = true
|
57
|
+
pkg.need_zip = true
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Clean files generated by rake tasks"
|
61
|
+
task :clobber => [:clobber_rdoc, :clobber_package]
|
62
|
+
|
63
|
+
desc "Generate a gemspec file"
|
64
|
+
task :gemspec do
|
65
|
+
File.open("#{spec.name}.gemspec", 'w') do |f|
|
66
|
+
f.write spec.to_ruby
|
67
|
+
end
|
68
|
+
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 :factory_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] || factory_name.to_s.classify.constantize
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize (name, options = {}) #:nodoc:
|
68
|
+
options.assert_valid_keys(:class)
|
69
|
+
@factory_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 :name, '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 factory name" do
|
86
|
+
assert_equal @name, @factory.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,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ryanb-factory_girl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joe Ferris
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-06-28 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
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.
|
17
|
+
email: jferris@thoughtbot.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.textile
|
24
|
+
files:
|
25
|
+
- Changelog
|
26
|
+
- LICENSE
|
27
|
+
- Rakefile
|
28
|
+
- README.textile
|
29
|
+
- lib/factory_girl/attribute_proxy.rb
|
30
|
+
- lib/factory_girl/factory.rb
|
31
|
+
- lib/factory_girl/sequence.rb
|
32
|
+
- lib/factory_girl.rb
|
33
|
+
- test/attribute_proxy_test.rb
|
34
|
+
- test/factory_test.rb
|
35
|
+
- test/integration_test.rb
|
36
|
+
- test/models.rb
|
37
|
+
- test/sequence_test.rb
|
38
|
+
- test/test_helper.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage:
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --line-numbers
|
44
|
+
- --inline-source
|
45
|
+
- --main
|
46
|
+
- README.textile
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.2.0
|
65
|
+
signing_key:
|
66
|
+
specification_version: 2
|
67
|
+
summary: factory_girl provides a framework and DSL for defining and using model instance factories.
|
68
|
+
test_files:
|
69
|
+
- test/attribute_proxy_test.rb
|
70
|
+
- test/factory_test.rb
|
71
|
+
- test/integration_test.rb
|
72
|
+
- test/sequence_test.rb
|