modelfactory 0.8.9 → 0.9.0

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.
@@ -1,3 +1,7 @@
1
+ == 0.9.0 2009-06-04
2
+ * More API changes
3
+ * Built-in counters for generating values
4
+
1
5
  == 0.8.9 2009-05-19
2
6
  * Renamed the required lib to 'modelfactory'
3
7
  * Completely redesigned API, see the documentation in README.txt
@@ -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/model_factory_legacy_test.rb
21
- test/model_factory_test.rb
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 |m|
22
- m.name = "Factory User"
23
- m.email = "user@factory.ws"
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
- Since factory-created instances are meant to be valid, you will probably
36
- need a way to generate unique values. ModelFactory keeps a counter for each
37
- type that increments when each new instance is created. This counter is passed
38
- to configuration blocks to make it easier to generate unique values:
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 |m, i|
42
- m.name = "Factory User #{i}"
43
- m.email = "user#{i}@factory.ws"
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 |m, i|
62
- m.name = "Admin User #{i}"
63
- m.admin = true
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 to data to allow the creation of valid objects.
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.extra_dev_deps = ['active_record', 'mocha', 'thoughtbot-shoulda', 'sqlite3-ruby']
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
 
@@ -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
@@ -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
- if @options[name]
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
@@ -1,8 +1,8 @@
1
1
  module ModelFactory #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 8
5
- TINY = 9
4
+ MINOR = 9
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -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
+
@@ -0,0 +1,4 @@
1
+ class Category < ActiveRecord::Base
2
+ has_many :widgets
3
+ end
4
+
@@ -3,6 +3,11 @@ ActiveRecord::Schema.define do
3
3
  t.string "name"
4
4
  t.decimal "price"
5
5
  t.string "type"
6
+ t.integer "category_id"
7
+ end
8
+
9
+ create_table "categories", :force => true do |t|
10
+ t.string "name"
6
11
  end
7
12
  end
8
13
 
@@ -1,4 +1,4 @@
1
-
2
1
  class Widget < ActiveRecord::Base
2
+ belongs_to :category
3
3
  end
4
4
 
@@ -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
+
@@ -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.8.9
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-05-19 00:00:00 -07:00
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: active_record
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/model_factory_legacy_test.rb
98
- - test/model_factory_test.rb
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/model_factory_test.rb
129
- - test/model_factory_legacy_test.rb
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
@@ -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
-