modelfactory 0.8.9 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
-