factory_girl 1.1.5 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README.rdoc +228 -0
  2. data/Rakefile +7 -5
  3. data/lib/factory_girl.rb +11 -4
  4. data/lib/factory_girl/aliases.rb +18 -7
  5. data/lib/factory_girl/attribute.rb +10 -20
  6. data/lib/factory_girl/attribute/association.rb +18 -0
  7. data/lib/factory_girl/attribute/dynamic.rb +17 -0
  8. data/lib/factory_girl/attribute/static.rb +17 -0
  9. data/lib/factory_girl/factory.rb +199 -119
  10. data/lib/factory_girl/proxy.rb +62 -0
  11. data/lib/factory_girl/proxy/attributes_for.rb +21 -0
  12. data/lib/factory_girl/proxy/build.rb +29 -0
  13. data/lib/factory_girl/proxy/create.rb +10 -0
  14. data/lib/factory_girl/proxy/stub.rb +28 -0
  15. data/lib/factory_girl/sequence.rb +2 -0
  16. data/lib/factory_girl/syntax.rb +12 -0
  17. data/lib/factory_girl/syntax/blueprint.rb +42 -0
  18. data/lib/factory_girl/syntax/generate.rb +68 -0
  19. data/lib/factory_girl/syntax/make.rb +39 -0
  20. data/lib/factory_girl/syntax/sham.rb +42 -0
  21. data/test/aliases_test.rb +1 -1
  22. data/test/association_attribute_test.rb +31 -0
  23. data/test/attribute_test.rb +8 -46
  24. data/test/attributes_for_strategy_test.rb +55 -0
  25. data/test/build_strategy_test.rb +79 -0
  26. data/test/create_strategy_test.rb +90 -0
  27. data/test/dynamic_attribute_test.rb +41 -0
  28. data/test/factory_test.rb +255 -243
  29. data/test/integration_test.rb +91 -3
  30. data/test/models.rb +1 -0
  31. data/test/sequence_test.rb +1 -1
  32. data/test/static_attribute_test.rb +33 -0
  33. data/test/strategy_test.rb +33 -0
  34. data/test/stub_strategy_test.rb +52 -0
  35. data/test/syntax/blueprint_test.rb +39 -0
  36. data/test/syntax/generate_test.rb +63 -0
  37. data/test/syntax/make_test.rb +39 -0
  38. data/test/syntax/sham_test.rb +40 -0
  39. data/test/test_helper.rb +1 -0
  40. metadata +42 -8
  41. data/README.textile +0 -151
  42. data/lib/factory_girl/attribute_proxy.rb +0 -92
  43. data/test/attribute_proxy_test.rb +0 -121
@@ -0,0 +1,62 @@
1
+ class Factory
2
+
3
+ class Proxy #:nodoc:
4
+ def initialize(klass)
5
+ end
6
+
7
+ def get(attribute)
8
+ nil
9
+ end
10
+
11
+ def set(attribute, value)
12
+ end
13
+
14
+ def associate(name, factory, attributes)
15
+ end
16
+
17
+ # Generates an association using the current build strategy.
18
+ #
19
+ # Arguments:
20
+ # name: (Symbol)
21
+ # The name of the factory that should be used to generate this
22
+ # association.
23
+ # attributes: (Hash)
24
+ # A hash of attributes that should be overridden for this association.
25
+ #
26
+ # Returns:
27
+ # The generated association for the current build strategy. Note that
28
+ # assocaitions are not generated for the attributes_for strategy. Returns
29
+ # nil in this case.
30
+ #
31
+ # Example:
32
+ #
33
+ # Factory.define :user do |f|
34
+ # # ...
35
+ # end
36
+ #
37
+ # Factory.define :post do |f|
38
+ # # ...
39
+ # f.author {|a| a.association :user, :name => 'Joe' }
40
+ # end
41
+ #
42
+ # # Builds (but doesn't save) a Post and a User
43
+ # Factory.build(:post)
44
+ #
45
+ # # Builds and saves a User, builds a Post, assigns the User to the
46
+ # # author association, and saves the User.
47
+ # Factory.create(:post)
48
+ #
49
+ def association(name, overrides = {})
50
+ nil
51
+ end
52
+
53
+ def method_missing(method, *args, &block)
54
+ get(method)
55
+ end
56
+
57
+ def result
58
+ raise NotImplementedError, "Strategies must return a result"
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,21 @@
1
+ class Factory
2
+ class Proxy #:nodoc:
3
+ class AttributesFor < Proxy #:nodoc:
4
+ def initialize(klass)
5
+ @hash = {}
6
+ end
7
+
8
+ def get(attribute)
9
+ @hash[attribute]
10
+ end
11
+
12
+ def set(attribute, value)
13
+ @hash[attribute] = value
14
+ end
15
+
16
+ def result
17
+ @hash
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ class Factory
2
+ class Proxy #:nodoc:
3
+ class Build < Proxy #:nodoc:
4
+ def initialize(klass)
5
+ @instance = klass.new
6
+ end
7
+
8
+ def get(attribute)
9
+ @instance.send(attribute)
10
+ end
11
+
12
+ def set(attribute, value)
13
+ @instance.send(:"#{attribute}=", value)
14
+ end
15
+
16
+ def associate(name, factory, attributes)
17
+ set(name, Factory.create(factory, attributes))
18
+ end
19
+
20
+ def association(factory, overrides = {})
21
+ Factory.create(factory, overrides)
22
+ end
23
+
24
+ def result
25
+ @instance
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ class Factory
2
+ class Proxy #:nodoc:
3
+ class Create < Build #:nodoc:
4
+ def result
5
+ @instance.save!
6
+ @instance
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,28 @@
1
+ class Factory
2
+ class Proxy
3
+ class Stub < Proxy #:nodoc:
4
+ def initialize(klass)
5
+ @mock = Object.new
6
+ end
7
+
8
+ def get(attribute)
9
+ @mock.send(attribute)
10
+ end
11
+
12
+ def set(attribute, value)
13
+ unless @mock.respond_to?("attribute=")
14
+ class << @mock; self end.send(:attr_accessor, attribute)
15
+ end
16
+ @mock.send("#{attribute}=", value)
17
+ end
18
+
19
+ def associate(name, factory, attributes)
20
+ set(name, nil)
21
+ end
22
+
23
+ def result
24
+ @mock
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,7 @@
1
1
  class Factory
2
2
 
3
+ # Sequences are defined using Factory.sequence. Sequence values are generated
4
+ # using next.
3
5
  class Sequence
4
6
 
5
7
  def initialize (&proc) #:nodoc:
@@ -0,0 +1,12 @@
1
+ class Factory
2
+ # Provides alternate syntaxes for factory_girl. If you don't like the default
3
+ # syntax for defining or using factories, look at one of the Factory::Syntax
4
+ # modules:
5
+ #
6
+ # * Factory::Syntax::Blueprint: definition syntax similar to Machinist
7
+ # * Factory::Syntax::Generate: usage syntax similar to Object Daddy
8
+ # * Factory::Syntax::Make: usage syntax similar to Machinist
9
+ # * Factory::Syntax::Sham: sequence syntax similar to Machinist
10
+ module Syntax
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ class Factory
2
+ module Syntax
3
+
4
+ # Extends ActiveRecord::Base to provide a make class method, which is an
5
+ # alternate syntax for defining factories.
6
+ #
7
+ # Usage:
8
+ #
9
+ # require 'factory_girl/syntax/blueprint'
10
+ #
11
+ # User.blueprint do
12
+ # name { 'Billy Bob' }
13
+ # email { 'billy@bob.example.com' }
14
+ # end
15
+ #
16
+ # Factory(:user, :name => 'Johnny')
17
+ #
18
+ # This syntax was derived from Pete Yandell's machinist.
19
+ module Blueprint
20
+ module ActiveRecord #:nodoc:
21
+
22
+ def self.included(base) # :nodoc:
23
+ base.extend ClassMethods
24
+ end
25
+
26
+ module ClassMethods #:nodoc:
27
+
28
+ def blueprint(&block)
29
+ instance = Factory.new(name.underscore, :class => self)
30
+ instance.instance_eval(&block)
31
+ Factory.factories[instance.factory_name] = instance
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ ActiveRecord::Base.send(:include, Factory::Syntax::Blueprint::ActiveRecord)
42
+
@@ -0,0 +1,68 @@
1
+ class Factory
2
+ module Syntax
3
+
4
+ # Extends ActiveRecord::Base to provide generation methods for factories.
5
+ #
6
+ # Usage:
7
+ #
8
+ # require 'factory_girl/syntax/generate'
9
+ #
10
+ # Factory.define :user do |factory|
11
+ # factory.name 'Billy Bob'
12
+ # factory.email 'billy@bob.example.com'
13
+ # end
14
+ #
15
+ # # Creates a saved instance without raising (same as saving the result
16
+ # # of Factory.build)
17
+ # User.generate(:name => 'Johnny')
18
+ #
19
+ # # Creates a saved instance and raises when invalid (same as
20
+ # # Factory.create)
21
+ # User.generate!
22
+ #
23
+ # # Creates an unsaved instance (same as Factory.build)
24
+ # User.spawn
25
+ #
26
+ # # Creates an instance and yields it to the passed block
27
+ # User.generate do |user|
28
+ # # ...do something with user...
29
+ # end
30
+ #
31
+ # This syntax was derived from Rick Bradley and Yossef Mendelssohn's
32
+ # object_daddy.
33
+ module Generate
34
+ module ActiveRecord #:nodoc:
35
+
36
+ def self.included(base) # :nodoc:
37
+ base.extend ClassMethods
38
+ end
39
+
40
+ module ClassMethods #:nodoc:
41
+
42
+ def generate(overrides = {}, &block)
43
+ instance = Factory.build(name.underscore, overrides)
44
+ instance.save
45
+ yield(instance) if block_given?
46
+ instance
47
+ end
48
+
49
+ def generate!(overrides = {}, &block)
50
+ instance = Factory.create(name.underscore, overrides)
51
+ yield(instance) if block_given?
52
+ instance
53
+ end
54
+
55
+ def spawn(overrides = {}, &block)
56
+ instance = Factory.build(name.underscore, overrides)
57
+ yield(instance) if block_given?
58
+ instance
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ ActiveRecord::Base.send(:include, Factory::Syntax::Generate::ActiveRecord)
@@ -0,0 +1,39 @@
1
+ class Factory
2
+ module Syntax
3
+
4
+ # Extends ActiveRecord::Base to provide a make class method, which is a
5
+ # shortcut for Factory.create.
6
+ #
7
+ # Usage:
8
+ #
9
+ # require 'factory_girl/syntax/make'
10
+ #
11
+ # Factory.define :user do |factory|
12
+ # factory.name 'Billy Bob'
13
+ # factory.email 'billy@bob.example.com'
14
+ # end
15
+ #
16
+ # User.make(:name => 'Johnny')
17
+ #
18
+ # This syntax was derived from Pete Yandell's machinist.
19
+ module Make
20
+ module ActiveRecord #:nodoc:
21
+
22
+ def self.included(base) # :nodoc:
23
+ base.extend ClassMethods
24
+ end
25
+
26
+ module ClassMethods #:nodoc:
27
+
28
+ def make(overrides = {})
29
+ Factory.create(name.underscore, overrides)
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ ActiveRecord::Base.send(:include, Factory::Syntax::Make::ActiveRecord)
@@ -0,0 +1,42 @@
1
+ class Factory
2
+ module Syntax
3
+
4
+ # Adds a Sham module, which provides an alternate interface to
5
+ # Factory::Sequence.
6
+ #
7
+ # Usage:
8
+ #
9
+ # require 'factory_girl/syntax/sham'
10
+ #
11
+ # Sham.email {|n| "somebody#{n}@example.com" }
12
+ #
13
+ # Factory.define :user do |factory|
14
+ # factory.email { Sham.email }
15
+ # end
16
+ #
17
+ # Note that you can also use Faker, but it is recommended that you simply
18
+ # use a sequence as in the above example, as factory_girl does not provide
19
+ # protection against duplication in randomized sequences, and a randomized
20
+ # value does not provide any tangible benefits over an ascending sequence.
21
+ #
22
+ # This syntax was derived from Pete Yandell's machinist.
23
+ module Sham
24
+ module Sham #:nodoc:
25
+ def self.method_missing(name, &block)
26
+ if block_given?
27
+ Factory.sequence(name, &block)
28
+ else
29
+ Factory.next(name)
30
+ end
31
+ end
32
+
33
+ # overrides name on Module
34
+ def self.name(&block)
35
+ method_missing('name', &block)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ include Factory::Syntax::Sham
@@ -1,4 +1,4 @@
1
- require(File.join(File.dirname(__FILE__), 'test_helper'))
1
+ require 'test_helper'
2
2
 
3
3
  class AliasesTest < Test::Unit::TestCase
4
4
 
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+
3
+ class AssociationAttributeTest < Test::Unit::TestCase
4
+
5
+ context "an association" do
6
+ setup do
7
+ @name = :author
8
+ @factory = :user
9
+ @overrides = { :first_name => 'John' }
10
+ @attr = Factory::Attribute::Association.new(@name,
11
+ @factory,
12
+ @overrides)
13
+ end
14
+
15
+ should "have a name" do
16
+ assert_equal @name, @attr.name
17
+ end
18
+
19
+ should "tell the proxy to associate when being added to a proxy" do
20
+ proxy = mock('proxy')
21
+ proxy.expects(:associate).with(@name, @factory, @overrides)
22
+ @attr.add_to(proxy)
23
+ end
24
+ end
25
+
26
+ should "convert names to symbols" do
27
+ assert_equal :name,
28
+ Factory::Attribute::Association.new('name', :user, {}).name
29
+ end
30
+
31
+ end
@@ -1,70 +1,32 @@
1
- require(File.join(File.dirname(__FILE__), 'test_helper'))
1
+ require 'test_helper'
2
2
 
3
3
  class AttributeTest < Test::Unit::TestCase
4
4
 
5
- def setup
6
- @proxy = mock('attribute-proxy')
7
- end
8
-
9
5
  context "an attribute" do
10
-
11
6
  setup do
12
7
  @name = :user
13
- @attr = Factory::Attribute.new(@name, 'test', nil)
8
+ @attr = Factory::Attribute.new(@name)
14
9
  end
15
10
 
16
11
  should "have a name" do
17
12
  assert_equal @name, @attr.name
18
13
  end
19
14
 
20
- end
21
-
22
- context "an attribute with a static value" do
23
-
24
- setup do
25
- @value = 'test'
26
- @attr = Factory::Attribute.new(:user, @value, nil)
27
- end
28
-
29
- should "return the value" do
30
- assert_equal @value, @attr.value(@proxy)
15
+ should "do nothing when being added to a proxy" do
16
+ @proxy = mock('proxy')
17
+ @proxy.expects(:set).never
18
+ @attr.add_to(@proxy)
31
19
  end
32
-
33
- end
34
-
35
- context "an attribute with a lazy value" do
36
-
37
- setup do
38
- @block = lambda { 'value' }
39
- @attr = Factory::Attribute.new(:user, nil, @block)
40
- end
41
-
42
- should "call the block to return a value" do
43
- assert_equal 'value', @attr.value(@proxy)
44
- end
45
-
46
- should "yield the attribute proxy to the block" do
47
- @block = lambda {|a| a }
48
- @attr = Factory::Attribute.new(:user, nil, @block)
49
- assert_equal @proxy, @attr.value(@proxy)
50
- end
51
-
52
20
  end
53
21
 
54
22
  should "raise an error when defining an attribute writer" do
55
23
  assert_raise Factory::AttributeDefinitionError do
56
- Factory::Attribute.new('test=', nil, nil)
57
- end
58
- end
59
-
60
- should "not allow attributes to be added with both a value parameter and a block" do
61
- assert_raise(Factory::AttributeDefinitionError) do
62
- Factory::Attribute.new(:name, 'value', lambda {})
24
+ Factory::Attribute.new('test=')
63
25
  end
64
26
  end
65
27
 
66
28
  should "convert names to symbols" do
67
- assert_equal :name, Factory::Attribute.new('name', nil, nil).name
29
+ assert_equal :name, Factory::Attribute.new('name').name
68
30
  end
69
31
 
70
32
  end