modelfactory 0.8.9 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +6 -2
- data/README.txt +50 -30
- data/Rakefile +5 -1
- data/lib/modelfactory.rb +2 -2
- data/lib/modelfactory/factory.rb +22 -10
- data/lib/modelfactory/version.rb +2 -2
- data/test/counter_test.rb +25 -0
- data/test/fixtures/category.rb +4 -0
- data/test/fixtures/schema.rb +5 -0
- data/test/fixtures/widget.rb +1 -1
- data/test/{model_factory_legacy_test.rb → legacy_test.rb} +0 -0
- data/test/modelfactory_test.rb +40 -0
- data/test/named_test.rb +35 -0
- data/test/relation_test.rb +57 -0
- metadata +34 -7
- data/test/model_factory_test.rb +0 -86
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -14,9 +14,13 @@ script/fixtures2factories
|
|
14
14
|
script/generate
|
15
15
|
script/txt2html
|
16
16
|
setup.rb
|
17
|
+
test/counter_test.rb
|
18
|
+
test/fixtures/category.rb
|
17
19
|
test/fixtures/schema.rb
|
18
20
|
test/fixtures/strict_widget.rb
|
19
21
|
test/fixtures/widget.rb
|
20
|
-
test/
|
21
|
-
test/
|
22
|
+
test/legacy_test.rb
|
23
|
+
test/modelfactory_test.rb
|
24
|
+
test/named_test.rb
|
25
|
+
test/relation_test.rb
|
22
26
|
test/test_helper.rb
|
data/README.txt
CHANGED
@@ -18,64 +18,84 @@ opaque ActiveRecord objects whose contents are unimportant.
|
|
18
18
|
require 'modelfactory'
|
19
19
|
|
20
20
|
ModelFactory.configuration do
|
21
|
-
default(User) do
|
22
|
-
|
23
|
-
|
21
|
+
default(User) do
|
22
|
+
name { "Factory User" }
|
23
|
+
email { "user@factory.ws" }
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
ModelFactory[User].create.name # => 'Factory User'
|
28
28
|
|
29
|
+
Defaults can be overriden on instance creation. By not specifying unimportant
|
30
|
+
values, the intention of your tests becomes clearer:
|
31
|
+
|
32
|
+
def test_welcome
|
33
|
+
user = ModelFactory[User].create(:name => 'bob')
|
34
|
+
assert_equal 'Welcome, bob!', user.welcome
|
35
|
+
end
|
36
|
+
|
29
37
|
If you don't care for the factory creation syntax, ModelFactory defines the
|
30
38
|
factory class method on ActiveRecord models. The following is equivalent
|
31
39
|
to ModelFactory[User].create:
|
32
40
|
|
33
41
|
User.factory.create
|
34
42
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
43
|
+
When you use a factory to create an instance, the save! and reload methods are
|
44
|
+
called before the instance is returned. This means instances must be valid after
|
45
|
+
being initialized by the factory, or an ActiveRecord validation error will be
|
46
|
+
raised.
|
47
|
+
|
48
|
+
class Widget < ActiveRecord::Base
|
49
|
+
validates_presence_of :name, :desc
|
50
|
+
end
|
51
|
+
|
52
|
+
ModelFactory.configure do
|
53
|
+
default(Widget) { name { 'widget' } }
|
54
|
+
end
|
55
|
+
|
56
|
+
# Raises an error because no desc was provided:
|
57
|
+
Widget.factory.create
|
58
|
+
|
59
|
+
# Doesn't raise, a desc is provided:
|
60
|
+
Widget.factory.create(:desc => 'widget desc')
|
61
|
+
|
62
|
+
# Doesn't raise, required values are defined in the default factory:
|
63
|
+
ModelFactory.configure do
|
64
|
+
default(Widget) do
|
65
|
+
name { 'widget' }
|
66
|
+
desc { 'widget desc' }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
Widget.factory.create
|
70
|
+
|
71
|
+
Since creating valid objects usually means having unique values, ModelFactory
|
72
|
+
keeps a counter for each type that increments when each new instance is
|
73
|
+
created. This counter is passed to model initialization blocks to make it
|
74
|
+
easier to generate unique values:
|
39
75
|
|
40
76
|
ModelFactory.configuration do
|
41
|
-
default(User) do
|
42
|
-
|
43
|
-
|
77
|
+
default(User) do
|
78
|
+
name {|i| "Factory User #{i}" }
|
79
|
+
email {|i| "user#{i}@factory.ws" }
|
44
80
|
end
|
45
81
|
end
|
46
82
|
|
47
83
|
User.factory.create.name # => 'Factory User 1'
|
48
84
|
User.factory.create.email # => 'user2@factory.ws'
|
49
85
|
|
50
|
-
Defaults can be overriden on instance creation. By not specifying unimportant
|
51
|
-
values, the intention of your tests becomes clearer:
|
52
|
-
|
53
|
-
def test_welcome
|
54
|
-
user = ModelFactory[User].create(:name => 'bob')
|
55
|
-
assert_equal 'Welcome, bob!', user.welcome
|
56
|
-
end
|
57
|
-
|
58
86
|
It's possible to configure named factories:
|
59
87
|
|
60
88
|
ModelFactory.configuration do
|
61
|
-
admin(User) do
|
62
|
-
|
63
|
-
|
89
|
+
admin(User) do
|
90
|
+
name {|i| "Admin User #{i}" }
|
91
|
+
admin { true }
|
64
92
|
end
|
65
93
|
end
|
66
94
|
|
67
95
|
User.factory.create_admin.admin # => true
|
68
96
|
|
69
97
|
Named factories do not inherit anything from the default, so you'll still need to
|
70
|
-
provide enough
|
71
|
-
|
72
|
-
=== A Note About Defaults
|
73
|
-
|
74
|
-
The purpose of default values is to generate valid instances, not to serve as
|
75
|
-
replacements for fixture data. When writing tests that use factory-generated
|
76
|
-
objects, it's important never to depend on default values in your test assertions.
|
77
|
-
If you depend on defaults in your tests they become more fragile and the intention
|
78
|
-
is harder to discern. Alway override values you care about when using factory objects.
|
98
|
+
provide enough data to allow the creation of valid objects.
|
79
99
|
|
80
100
|
== Installing ModelFactory
|
81
101
|
|
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'hoe'
|
3
|
+
require 'hanna/rdoctask'
|
3
4
|
$:.unshift(File.dirname(__FILE__) + "/lib")
|
4
5
|
require 'modelfactory/version'
|
5
6
|
|
@@ -15,7 +16,10 @@ Hoe.new('ModelFactory', ModelFactory::VERSION::STRING) do |p|
|
|
15
16
|
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
16
17
|
p.test_globs = ["test/**/*_test.rb"]
|
17
18
|
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
|
18
|
-
p.
|
19
|
+
p.extra_deps = %w[ activesupport ]
|
20
|
+
p.extra_dev_deps = %w[
|
21
|
+
activerecord mocha thoughtbot-shoulda sqlite3-ruby mislav-hanna
|
22
|
+
]
|
19
23
|
end
|
20
24
|
|
21
25
|
|
data/lib/modelfactory.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'active_record'
|
3
|
-
require 'modelfactory/factory'
|
4
|
-
require 'modelfactory/legacy'
|
3
|
+
require File.dirname(__FILE__) + '/modelfactory/factory'
|
4
|
+
require File.dirname(__FILE__) + '/modelfactory/legacy'
|
5
5
|
|
6
6
|
ActiveRecord::Base.class_eval do
|
7
7
|
def self.factory ; ModelFactory[self] ; end
|
data/lib/modelfactory/factory.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support' # instance_exec
|
2
|
+
|
1
3
|
module ModelFactory # :nodoc:
|
2
4
|
# This API allows you to instantiate models.
|
3
5
|
class Factory # :nodoc:
|
@@ -34,16 +36,7 @@ module ModelFactory # :nodoc:
|
|
34
36
|
|
35
37
|
def new_named(name, opt = {}, &block)
|
36
38
|
instance = @class.new
|
37
|
-
|
38
|
-
case @options[name].arity
|
39
|
-
when 2
|
40
|
-
@options[name].call(instance, next_counter) if @options[name]
|
41
|
-
else
|
42
|
-
@options[name].call(instance) if @options[name]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
opt.each {|k,v| instance.send("#{k}=", v) }
|
46
|
-
yield instance if block_given?
|
39
|
+
InstanceBuilder.new(instance, opt, next_counter, &@options[name])
|
47
40
|
instance
|
48
41
|
end
|
49
42
|
|
@@ -56,4 +49,23 @@ module ModelFactory # :nodoc:
|
|
56
49
|
|
57
50
|
end
|
58
51
|
|
52
|
+
class InstanceBuilder # :nodoc:
|
53
|
+
def initialize(instance, params, counter, &block)
|
54
|
+
@instance = instance
|
55
|
+
@params = params
|
56
|
+
@counter = counter
|
57
|
+
@params.each { |attr, value| @instance.send "#{attr}=", value }
|
58
|
+
instance_eval(&block) if block_given?
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_missing(method, &block)
|
62
|
+
if block_given? && !@params.key?(method.to_sym)
|
63
|
+
@instance.send "#{method}=",
|
64
|
+
(block.arity == 1) ?
|
65
|
+
@instance.instance_exec(@counter, &block) :
|
66
|
+
@instance.instance_eval(&block)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
59
71
|
end
|
data/lib/modelfactory/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/modelfactory'
|
3
|
+
|
4
|
+
class ModelFactoryTest < Test::Unit::TestCase
|
5
|
+
context "with a specified default that uses automatic numbering" do
|
6
|
+
setup do
|
7
|
+
ModelFactory.configure do
|
8
|
+
default(Widget) { price {|i| i } }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
should "start counting at 1 after configuration" do
|
13
|
+
assert_equal 1.0, Widget.factory.create.price
|
14
|
+
end
|
15
|
+
|
16
|
+
should "generate a unique sequence" do
|
17
|
+
w = []
|
18
|
+
3.times { w << Widget.factory.create.price }
|
19
|
+
assert_equal w.uniq, w
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
data/test/fixtures/schema.rb
CHANGED
data/test/fixtures/widget.rb
CHANGED
File without changes
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/modelfactory'
|
3
|
+
|
4
|
+
class ModelFactoryTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
should "not instantiate when using new" do
|
7
|
+
assert Widget.factory.new.new_record?
|
8
|
+
end
|
9
|
+
|
10
|
+
should "instantiate when using create" do
|
11
|
+
assert !Widget.factory.create.new_record?
|
12
|
+
end
|
13
|
+
|
14
|
+
should "raise on creation of invalid records" do
|
15
|
+
assert_raises(ActiveRecord::RecordInvalid) { StrictWidget.factory.create }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with a specified default" do
|
19
|
+
setup do
|
20
|
+
ModelFactory.configure do
|
21
|
+
default(Widget) { name {'foobaz' } }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
should "initialize defaults with no arguments" do
|
26
|
+
assert_equal 'foobaz', Widget.factory.create.name
|
27
|
+
end
|
28
|
+
|
29
|
+
should "initialize defaults with an unspecified argument" do
|
30
|
+
assert_equal 'foobaz', Widget.factory.create(:price => 4.0).name
|
31
|
+
end
|
32
|
+
|
33
|
+
should "initialize with an unspecified argument" do
|
34
|
+
assert_equal 4, Widget.factory.create(:price => 4.0).price
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
data/test/named_test.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/modelfactory'
|
3
|
+
|
4
|
+
class ModelFactoryTest < Test::Unit::TestCase
|
5
|
+
context "with a named factory" do
|
6
|
+
setup do
|
7
|
+
ModelFactory.configure do
|
8
|
+
default(Widget) { name { 'wubbo' } }
|
9
|
+
favorite(Widget) { name { 'foobaz' } }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
should "not apply named config to default" do
|
14
|
+
assert_equal 'wubbo', Widget.factory.create.name
|
15
|
+
end
|
16
|
+
|
17
|
+
should "not apply any config to unrecognized name" do
|
18
|
+
assert_equal nil, Widget.factory.create_emptyfoo.name
|
19
|
+
end
|
20
|
+
|
21
|
+
should "initialize defaults with no arguments" do
|
22
|
+
assert_equal 'foobaz', Widget.factory.create_favorite.name
|
23
|
+
end
|
24
|
+
|
25
|
+
should "initialize defaults with an unspecified argument" do
|
26
|
+
assert_equal 'foobaz', Widget.factory.create_favorite(:price => 4.0).name
|
27
|
+
end
|
28
|
+
|
29
|
+
should "initialize with an unspecified argument" do
|
30
|
+
assert_equal 4, Widget.factory.create_favorite(:price => 4.0).price
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/modelfactory'
|
3
|
+
|
4
|
+
class ModelFactoryTest < Test::Unit::TestCase
|
5
|
+
context "default refers to previously initialized value" do
|
6
|
+
setup do
|
7
|
+
ModelFactory.configure do
|
8
|
+
default(Category) do
|
9
|
+
name { "Factory Category" }
|
10
|
+
end
|
11
|
+
default(Widget) do
|
12
|
+
category { Category.factory.create }
|
13
|
+
name { "#{category.name} Widget" }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
should "refer to fields initialized by default block" do
|
19
|
+
assert_equal "Factory Category Widget", Widget.factory.create.name
|
20
|
+
end
|
21
|
+
|
22
|
+
should "refer to fields initialized on create" do
|
23
|
+
cat = Category.create(:name => 'Foobar')
|
24
|
+
assert_equal "Foobar Widget", Widget.factory.create(:category => cat).name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "initializing a belongs_to relation" do
|
29
|
+
setup do
|
30
|
+
ModelFactory.configure do
|
31
|
+
default(Category) do
|
32
|
+
name { "Factory Category" }
|
33
|
+
end
|
34
|
+
default(Widget) do
|
35
|
+
category { Category.factory.create }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
should "automatically create parent instance" do
|
41
|
+
old_count = Category.count
|
42
|
+
assert !Widget.factory.create.category.nil?
|
43
|
+
assert_equal old_count + 1, Category.count
|
44
|
+
end
|
45
|
+
|
46
|
+
should "do not create a parent when one is passed in" do
|
47
|
+
old_count = Category.count
|
48
|
+
Widget.factory.create(:category => nil)
|
49
|
+
assert_equal old_count, Category.count
|
50
|
+
end
|
51
|
+
|
52
|
+
should "do not assign a parent when nil is passed in" do
|
53
|
+
assert Widget.factory.create(:category => nil).category.nil?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: modelfactory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Balthrop
|
@@ -10,11 +10,21 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-06-04 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
|
-
name:
|
17
|
+
name: activesupport
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: activerecord
|
18
28
|
type: :development
|
19
29
|
version_requirement:
|
20
30
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -53,6 +63,16 @@ dependencies:
|
|
53
63
|
- !ruby/object:Gem::Version
|
54
64
|
version: "0"
|
55
65
|
version:
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: mislav-hanna
|
68
|
+
type: :development
|
69
|
+
version_requirement:
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "0"
|
75
|
+
version:
|
56
76
|
- !ruby/object:Gem::Dependency
|
57
77
|
name: hoe
|
58
78
|
type: :development
|
@@ -91,11 +111,15 @@ files:
|
|
91
111
|
- script/generate
|
92
112
|
- script/txt2html
|
93
113
|
- setup.rb
|
114
|
+
- test/counter_test.rb
|
115
|
+
- test/fixtures/category.rb
|
94
116
|
- test/fixtures/schema.rb
|
95
117
|
- test/fixtures/strict_widget.rb
|
96
118
|
- test/fixtures/widget.rb
|
97
|
-
- test/
|
98
|
-
- test/
|
119
|
+
- test/legacy_test.rb
|
120
|
+
- test/modelfactory_test.rb
|
121
|
+
- test/named_test.rb
|
122
|
+
- test/relation_test.rb
|
99
123
|
- test/test_helper.rb
|
100
124
|
has_rdoc: true
|
101
125
|
homepage: http://modelfactory.rubyforge.org/
|
@@ -125,5 +149,8 @@ signing_key:
|
|
125
149
|
specification_version: 2
|
126
150
|
summary: A replacement for fixtures.
|
127
151
|
test_files:
|
128
|
-
- test/
|
129
|
-
- test/
|
152
|
+
- test/counter_test.rb
|
153
|
+
- test/modelfactory_test.rb
|
154
|
+
- test/relation_test.rb
|
155
|
+
- test/legacy_test.rb
|
156
|
+
- test/named_test.rb
|
data/test/model_factory_test.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
require File.dirname(__FILE__) + '/../lib/modelfactory'
|
3
|
-
|
4
|
-
class ModelFactoryTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
should "not instantiate when using new" do
|
7
|
-
assert Widget.factory.new.new_record?
|
8
|
-
end
|
9
|
-
|
10
|
-
should "instantiate when using create" do
|
11
|
-
assert !Widget.factory.create.new_record?
|
12
|
-
end
|
13
|
-
|
14
|
-
should "raise on creation of invalid records" do
|
15
|
-
assert_raises(ActiveRecord::RecordInvalid) { StrictWidget.factory.create }
|
16
|
-
end
|
17
|
-
|
18
|
-
context "with a specified default that uses automatic numbering" do
|
19
|
-
setup do
|
20
|
-
ModelFactory.configure do
|
21
|
-
default(Widget) {|w, i| w.price = i }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
should "start counting at 1 after configuration" do
|
26
|
-
assert_equal 1.0, Widget.factory.create.price
|
27
|
-
end
|
28
|
-
|
29
|
-
should "generate a unique sequence" do
|
30
|
-
w = []
|
31
|
-
3.times { w << Widget.factory.create.price }
|
32
|
-
assert_equal w.uniq, w
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
context "with a specified default" do
|
37
|
-
setup do
|
38
|
-
ModelFactory.configure do
|
39
|
-
default(Widget) {|w| w.name = 'foobaz' }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
should "initialize defaults with no arguments" do
|
44
|
-
assert_equal 'foobaz', Widget.factory.create.name
|
45
|
-
end
|
46
|
-
|
47
|
-
should "initialize defaults with an unspecified argument" do
|
48
|
-
assert_equal 'foobaz', Widget.factory.create(:price => 4.0).name
|
49
|
-
end
|
50
|
-
|
51
|
-
should "initialize with an unspecified argument" do
|
52
|
-
assert_equal 4, Widget.factory.create(:price => 4.0).price
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context "with a named factory" do
|
57
|
-
setup do
|
58
|
-
ModelFactory.configure do
|
59
|
-
default(Widget) {|w| w.name = 'wubbo' }
|
60
|
-
favorite(Widget) {|w| w.name = 'foobaz' }
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
should "not apply named config to default" do
|
65
|
-
assert_equal 'wubbo', Widget.factory.create.name
|
66
|
-
end
|
67
|
-
|
68
|
-
should "not apply any config to unrecognized name" do
|
69
|
-
assert_equal nil, Widget.factory.create_emptyfoo.name
|
70
|
-
end
|
71
|
-
|
72
|
-
should "initialize defaults with no arguments" do
|
73
|
-
assert_equal 'foobaz', Widget.factory.create_favorite.name
|
74
|
-
end
|
75
|
-
|
76
|
-
should "initialize defaults with an unspecified argument" do
|
77
|
-
assert_equal 'foobaz', Widget.factory.create_favorite(:price => 4.0).name
|
78
|
-
end
|
79
|
-
|
80
|
-
should "initialize with an unspecified argument" do
|
81
|
-
assert_equal 4, Widget.factory.create_favorite(:price => 4.0).price
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
|