factory_girl 3.1.1 → 3.2.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.
- data/.simplecov +4 -0
- data/GETTING_STARTED.md +147 -3
- data/Gemfile.lock +1 -1
- data/NEWS +8 -0
- data/features/support/env.rb +0 -1
- data/gemfiles/3.0.gemfile.lock +1 -1
- data/gemfiles/3.1.gemfile.lock +1 -1
- data/gemfiles/3.2.gemfile.lock +1 -1
- data/lib/factory_girl.rb +50 -7
- data/lib/factory_girl/attribute.rb +1 -1
- data/lib/factory_girl/attribute/association.rb +1 -1
- data/lib/factory_girl/attribute/dynamic.rb +1 -1
- data/lib/factory_girl/attribute/sequence.rb +1 -1
- data/lib/factory_girl/attribute/static.rb +1 -1
- data/lib/factory_girl/attribute_assigner.rb +12 -3
- data/lib/factory_girl/callback.rb +4 -1
- data/lib/factory_girl/{callback_runner.rb → callbacks_observer.rb} +1 -1
- data/lib/factory_girl/definition.rb +1 -1
- data/lib/factory_girl/definition_proxy.rb +4 -0
- data/lib/factory_girl/disallows_duplicates_registry.rb +17 -0
- data/lib/factory_girl/evaluator.rb +14 -11
- data/lib/factory_girl/factory.rb +5 -5
- data/lib/factory_girl/null_object.rb +14 -2
- data/lib/factory_girl/registry.rb +15 -23
- data/lib/factory_girl/reload.rb +2 -0
- data/lib/factory_girl/strategy_calculator.rb +1 -5
- data/lib/factory_girl/syntax.rb +1 -0
- data/lib/factory_girl/syntax/blueprint.rb +1 -0
- data/lib/factory_girl/syntax/generate.rb +6 -3
- data/lib/factory_girl/syntax/make.rb +4 -2
- data/lib/factory_girl/syntax/methods.rb +0 -81
- data/lib/factory_girl/syntax/sham.rb +1 -0
- data/lib/factory_girl/syntax/vintage.rb +0 -2
- data/lib/factory_girl/syntax_runner.rb +5 -0
- data/lib/factory_girl/version.rb +1 -1
- data/spec/acceptance/activesupport_instrumentation_spec.rb +49 -0
- data/spec/acceptance/build_stubbed_spec.rb +6 -6
- data/spec/acceptance/initialize_with_spec.rb +26 -0
- data/spec/acceptance/modify_factories_spec.rb +2 -2
- data/spec/acceptance/register_strategies_spec.rb +120 -0
- data/spec/acceptance/skip_create_spec.rb +19 -0
- data/spec/acceptance/syntax/blueprint_spec.rb +2 -0
- data/spec/acceptance/syntax/generate_spec.rb +2 -0
- data/spec/acceptance/syntax/make_spec.rb +2 -0
- data/spec/acceptance/syntax/vintage_spec.rb +2 -2
- data/spec/acceptance/syntax_methods_within_dynamic_attributes_spec.rb +41 -0
- data/spec/factory_girl/attribute/dynamic_spec.rb +6 -6
- data/spec/factory_girl/attribute_list_spec.rb +4 -4
- data/spec/factory_girl/callback_spec.rb +7 -7
- data/spec/factory_girl/definition_proxy_spec.rb +6 -6
- data/spec/factory_girl/disallows_duplicates_registry_spec.rb +44 -0
- data/spec/factory_girl/evaluator_class_definer_spec.rb +5 -5
- data/spec/factory_girl/factory_spec.rb +3 -3
- data/spec/factory_girl/null_object_spec.rb +18 -4
- data/spec/factory_girl/registry_spec.rb +30 -72
- data/spec/factory_girl/sequence_spec.rb +3 -2
- data/spec/factory_girl/strategy_calculator_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -1
- metadata +41 -28
@@ -1,6 +1,6 @@
|
|
1
1
|
module FactoryGirl
|
2
2
|
class Callback
|
3
|
-
attr_reader :name
|
3
|
+
attr_reader :name
|
4
4
|
|
5
5
|
def initialize(name, block)
|
6
6
|
@name = name.to_sym
|
@@ -21,6 +21,9 @@ module FactoryGirl
|
|
21
21
|
block == other.block
|
22
22
|
end
|
23
23
|
|
24
|
+
protected
|
25
|
+
attr_reader :block
|
26
|
+
|
24
27
|
private
|
25
28
|
|
26
29
|
def check_name
|
@@ -6,7 +6,7 @@ module FactoryGirl
|
|
6
6
|
@declarations = DeclarationList.new(name)
|
7
7
|
@callbacks = []
|
8
8
|
@defined_traits = []
|
9
|
-
@to_create =
|
9
|
+
@to_create = ->(instance) { instance.save! }
|
10
10
|
@base_traits = base_traits
|
11
11
|
@additional_traits = []
|
12
12
|
@constructor = nil
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FactoryGirl
|
2
|
+
class DisallowsDuplicatesRegistry
|
3
|
+
def initialize(component)
|
4
|
+
@component = component
|
5
|
+
end
|
6
|
+
|
7
|
+
delegate :clear, :each, :find, :[], :registered?, to: :@component
|
8
|
+
|
9
|
+
def register(name, item)
|
10
|
+
if registered?(name)
|
11
|
+
raise DuplicateDefinitionError, "#{@component.name} already registered: #{name}"
|
12
|
+
else
|
13
|
+
@component.register(name, item)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -17,24 +17,23 @@ module FactoryGirl
|
|
17
17
|
undef_method(method) unless method =~ /^__|initialize/
|
18
18
|
end
|
19
19
|
|
20
|
-
def initialize(build_strategy, overrides = {})
|
20
|
+
def initialize(build_class, build_strategy, overrides = {})
|
21
|
+
@build_class = build_class
|
21
22
|
@build_strategy = build_strategy
|
22
23
|
@overrides = overrides
|
23
24
|
@cached_attributes = overrides
|
24
25
|
|
25
26
|
@overrides.each do |name, value|
|
26
|
-
singleton_class.send :define_method, name,
|
27
|
+
singleton_class.send :define_method, name, -> { value }
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
31
|
+
delegate :new, to: :@build_class
|
32
|
+
|
30
33
|
def association(factory_name, overrides = {})
|
31
|
-
|
32
|
-
overrides[:strategy]
|
33
|
-
else
|
34
|
-
Strategy::Create
|
35
|
-
end
|
34
|
+
strategy_override = overrides.fetch(:strategy) { FactoryGirl.strategy_by_name(:create) }
|
36
35
|
|
37
|
-
build_strategy = StrategyCalculator.new(
|
36
|
+
build_strategy = StrategyCalculator.new(strategy_override).strategy
|
38
37
|
runner = FactoryRunner.new(factory_name, build_strategy, [overrides.except(:strategy)])
|
39
38
|
@build_strategy.association(runner)
|
40
39
|
end
|
@@ -47,12 +46,16 @@ module FactoryGirl
|
|
47
46
|
if @cached_attributes.key?(method_name)
|
48
47
|
@cached_attributes[method_name]
|
49
48
|
else
|
50
|
-
@instance.
|
49
|
+
if @instance.respond_to?(method_name)
|
50
|
+
@instance.send(method_name, *args, &block)
|
51
|
+
else
|
52
|
+
SyntaxRunner.new.send(method_name, *args, &block)
|
53
|
+
end
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
54
|
-
def
|
55
|
-
@overrides
|
57
|
+
def __override_names__
|
58
|
+
@overrides.keys
|
56
59
|
end
|
57
60
|
end
|
58
61
|
end
|
data/lib/factory_girl/factory.rb
CHANGED
@@ -27,16 +27,16 @@ module FactoryGirl
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def run(strategy_class, overrides, &block) #:nodoc:
|
30
|
-
block ||=
|
30
|
+
block ||= ->(result) { result }
|
31
31
|
compile
|
32
32
|
|
33
33
|
strategy = strategy_class.new
|
34
34
|
|
35
|
-
evaluator = evaluator_class.new(strategy, overrides.symbolize_keys)
|
36
|
-
attribute_assigner = AttributeAssigner.new(evaluator, &instance_builder)
|
35
|
+
evaluator = evaluator_class.new(build_class, strategy, overrides.symbolize_keys)
|
36
|
+
attribute_assigner = AttributeAssigner.new(evaluator, build_class, &instance_builder)
|
37
37
|
|
38
38
|
evaluation = Evaluation.new(attribute_assigner, to_create)
|
39
|
-
evaluation.add_observer(
|
39
|
+
evaluation.add_observer(CallbacksObserver.new(callbacks, evaluator))
|
40
40
|
|
41
41
|
strategy.result(evaluation).tap(&block)
|
42
42
|
end
|
@@ -136,7 +136,7 @@ module FactoryGirl
|
|
136
136
|
|
137
137
|
def instance_builder
|
138
138
|
build_class = self.build_class
|
139
|
-
constructor ||
|
139
|
+
constructor || -> { build_class.new }
|
140
140
|
end
|
141
141
|
|
142
142
|
def initialize_copy(source)
|
@@ -1,7 +1,19 @@
|
|
1
1
|
module FactoryGirl
|
2
2
|
class NullObject < ::BasicObject
|
3
|
-
def
|
4
|
-
|
3
|
+
def initialize(methods_to_respond_to)
|
4
|
+
@methods_to_respond_to = methods_to_respond_to.map(&:to_s)
|
5
|
+
end
|
6
|
+
|
7
|
+
def method_missing(name, *args, &block)
|
8
|
+
if respond_to?(name)
|
9
|
+
nil
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def respond_to?(method, include_private=false)
|
16
|
+
@methods_to_respond_to.include? method.to_s
|
5
17
|
end
|
6
18
|
end
|
7
19
|
end
|
@@ -2,45 +2,37 @@ module FactoryGirl
|
|
2
2
|
class Registry
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
+
attr_reader :name
|
6
|
+
|
5
7
|
def initialize(name)
|
6
8
|
@name = name
|
7
9
|
@items = {}
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
-
item
|
13
|
-
end
|
14
|
-
|
15
|
-
def find(name)
|
16
|
-
@items[name.to_sym] or raise ArgumentError.new("#{@name} not registered: #{name.to_s}")
|
12
|
+
def clear
|
13
|
+
@items.clear
|
17
14
|
end
|
18
15
|
|
19
16
|
def each(&block)
|
20
17
|
@items.values.uniq.each(&block)
|
21
18
|
end
|
22
19
|
|
23
|
-
def
|
24
|
-
|
20
|
+
def find(name)
|
21
|
+
if registered?(name)
|
22
|
+
@items[name.to_sym]
|
23
|
+
else
|
24
|
+
raise ArgumentError, "#{@name} not registered: #{name}"
|
25
|
+
end
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
-
@items.key?(name.to_sym)
|
29
|
-
end
|
28
|
+
alias :[] :find
|
30
29
|
|
31
|
-
def
|
32
|
-
@items.
|
30
|
+
def register(name, item)
|
31
|
+
@items[name.to_sym] = item
|
33
32
|
end
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
def add_as(name, item)
|
38
|
-
if registered?(name)
|
39
|
-
raise DuplicateDefinitionError, "#{@name} already registered: #{name}"
|
40
|
-
else
|
41
|
-
@items[name.to_sym] = item
|
42
|
-
end
|
34
|
+
def registered?(name)
|
35
|
+
@items.key?(name.to_sym)
|
43
36
|
end
|
44
37
|
end
|
45
38
|
end
|
46
|
-
|
data/lib/factory_girl/reload.rb
CHANGED
@@ -19,11 +19,7 @@ module FactoryGirl
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def strategy_name_to_object
|
22
|
-
|
23
|
-
when :build then Strategy::Build
|
24
|
-
when :create then Strategy::Create
|
25
|
-
else raise "unrecognized method #{@name_or_object}"
|
26
|
-
end
|
22
|
+
FactoryGirl.strategy_by_name(@name_or_object)
|
27
23
|
end
|
28
24
|
end
|
29
25
|
end
|
data/lib/factory_girl/syntax.rb
CHANGED
@@ -26,6 +26,7 @@ module FactoryGirl
|
|
26
26
|
module ClassMethods #:nodoc:
|
27
27
|
|
28
28
|
def blueprint(&block)
|
29
|
+
ActiveSupport::Deprecation.warn "Model.blueprint is deprecated; use the FactoryGirl.define syntax instead", caller
|
29
30
|
instance = Factory.new(name.underscore, class: self)
|
30
31
|
proxy = FactoryGirl::DefinitionProxy.new(instance)
|
31
32
|
proxy.instance_eval(&block)
|
@@ -42,20 +42,23 @@ module FactoryGirl
|
|
42
42
|
module ClassMethods #:nodoc:
|
43
43
|
|
44
44
|
def generate(overrides = {}, &block)
|
45
|
-
|
45
|
+
ActiveSupport::Deprecation.warn "Model.generate is deprecated; use the FactoryGirl.define syntax instead", caller
|
46
|
+
instance = FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:build), [overrides]).run
|
46
47
|
instance.save
|
47
48
|
yield(instance) if block_given?
|
48
49
|
instance
|
49
50
|
end
|
50
51
|
|
51
52
|
def generate!(overrides = {}, &block)
|
52
|
-
|
53
|
+
ActiveSupport::Deprecation.warn "Model.generate! is deprecated; use the FactoryGirl.define syntax instead", caller
|
54
|
+
instance = FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:create), [overrides]).run
|
53
55
|
yield(instance) if block_given?
|
54
56
|
instance
|
55
57
|
end
|
56
58
|
|
57
59
|
def spawn(overrides = {}, &block)
|
58
|
-
|
60
|
+
ActiveSupport::Deprecation.warn "Model.spawn is deprecated; use the FactoryGirl.define syntax instead", caller
|
61
|
+
instance = FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:build), [overrides]).run
|
59
62
|
yield(instance) if block_given?
|
60
63
|
instance
|
61
64
|
end
|
@@ -28,11 +28,13 @@ module FactoryGirl
|
|
28
28
|
module ClassMethods #:nodoc:
|
29
29
|
|
30
30
|
def make(overrides = {})
|
31
|
-
|
31
|
+
ActiveSupport::Deprecation.warn "Model.make is deprecated; use the FactoryGirl.define syntax instead", caller
|
32
|
+
FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:build), [overrides]).run
|
32
33
|
end
|
33
34
|
|
34
35
|
def make!(overrides = {})
|
35
|
-
|
36
|
+
ActiveSupport::Deprecation.warn "Model.make! is deprecated; use the FactoryGirl.define syntax instead", caller
|
37
|
+
FactoryRunner.new(name.underscore, FactoryGirl.strategy_by_name(:create), [overrides]).run
|
36
38
|
end
|
37
39
|
|
38
40
|
end
|
@@ -1,87 +1,6 @@
|
|
1
1
|
module FactoryGirl
|
2
2
|
module Syntax
|
3
3
|
module Methods
|
4
|
-
# Generates and returns a Hash of attributes from this factory. Attributes
|
5
|
-
# can be individually overridden by passing in a Hash of attribute => value
|
6
|
-
# pairs.
|
7
|
-
#
|
8
|
-
# Arguments:
|
9
|
-
# * name: +Symbol+ or +String+
|
10
|
-
# The name of the factory that should be used.
|
11
|
-
# * traits_and_overrides: +Array+
|
12
|
-
# [+*Array+] Traits to be applied
|
13
|
-
# [+Hash+] Attributes to overwrite for this set.
|
14
|
-
# * block:
|
15
|
-
# Yields the hash of attributes.
|
16
|
-
#
|
17
|
-
# Returns: +Hash+
|
18
|
-
# A set of attributes that can be used to build an instance of the class
|
19
|
-
# this factory generates.
|
20
|
-
def attributes_for(name, *traits_and_overrides, &block)
|
21
|
-
FactoryRunner.new(name, Strategy::AttributesFor, traits_and_overrides).run(&block)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Generates and returns an instance from this factory. Attributes can be
|
25
|
-
# individually overridden by passing in a Hash of attribute => value pairs.
|
26
|
-
#
|
27
|
-
# Arguments:
|
28
|
-
# * name: +Symbol+ or +String+
|
29
|
-
# The name of the factory that should be used.
|
30
|
-
# * traits_and_overrides: +Array+
|
31
|
-
# [+*Array+] Traits to be applied
|
32
|
-
# [+Hash+] Attributes to overwrite for this instance.
|
33
|
-
# * block:
|
34
|
-
# Yields the built instance.
|
35
|
-
#
|
36
|
-
# Returns: +Object+
|
37
|
-
# An instance of the class this factory generates, with generated attributes
|
38
|
-
# assigned.
|
39
|
-
def build(name, *traits_and_overrides, &block)
|
40
|
-
FactoryRunner.new(name, Strategy::Build, traits_and_overrides).run(&block)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Generates, saves, and returns an instance from this factory. Attributes can
|
44
|
-
# be individually overridden by passing in a Hash of attribute => value
|
45
|
-
# pairs.
|
46
|
-
#
|
47
|
-
# Instances are saved using the +save!+ method, so ActiveRecord models will
|
48
|
-
# raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets.
|
49
|
-
#
|
50
|
-
# Arguments:
|
51
|
-
# * name: +Symbol+ or +String+
|
52
|
-
# The name of the factory that should be used.
|
53
|
-
# * traits_and_overrides: +Array+
|
54
|
-
# [+*Array+] Traits to be applied
|
55
|
-
# [+Hash+] Attributes to overwrite for this instance.
|
56
|
-
# * block:
|
57
|
-
# Yields the created instance.
|
58
|
-
#
|
59
|
-
# Returns: +Object+
|
60
|
-
# A saved instance of the class this factory generates, with generated
|
61
|
-
# attributes assigned.
|
62
|
-
def create(name, *traits_and_overrides, &block)
|
63
|
-
FactoryRunner.new(name, Strategy::Create, traits_and_overrides).run(&block)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Generates and returns an object with all attributes from this factory
|
67
|
-
# stubbed out. Attributes can be individually overridden by passing in a Hash
|
68
|
-
# of attribute => value pairs.
|
69
|
-
#
|
70
|
-
# Arguments:
|
71
|
-
# * name: +Symbol+ or +String+
|
72
|
-
# The name of the factory that should be used.
|
73
|
-
# * traits_and_overrides: +Array+
|
74
|
-
# [+*Array+] Traits to be applied
|
75
|
-
# [+Hash+] Attributes to overwrite for this instance.
|
76
|
-
# * block
|
77
|
-
# Yields the stubbed object.
|
78
|
-
#
|
79
|
-
# Returns: +Object+
|
80
|
-
# An object with generated attributes stubbed out.
|
81
|
-
def build_stubbed(name, *traits_and_overrides, &block)
|
82
|
-
FactoryRunner.new(name, Strategy::Stub, traits_and_overrides).run(&block)
|
83
|
-
end
|
84
|
-
|
85
4
|
# Builds and returns multiple instances from this factory as an array. Attributes can be
|
86
5
|
# individually overridden by passing in a Hash of attribute => value pairs.
|
87
6
|
#
|
@@ -26,6 +26,7 @@ module FactoryGirl
|
|
26
26
|
module Sham #:nodoc:
|
27
27
|
def self.method_missing(name, *args, &block)
|
28
28
|
if block_given?
|
29
|
+
ActiveSupport::Deprecation.warn "Sham.sequence is deprecated; use the FactoryGirl.define syntax instead", caller
|
29
30
|
start_value = args.first
|
30
31
|
FactoryGirl.register_sequence(Sequence.new(name, start_value || 1, &block))
|
31
32
|
else
|
data/lib/factory_girl/version.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "using ActiveSupport::Instrumentation to track factory interaction" do
|
4
|
+
before do
|
5
|
+
define_model("User", email: :string)
|
6
|
+
FactoryGirl.define do
|
7
|
+
factory :user do
|
8
|
+
email "john@example.com"
|
9
|
+
|
10
|
+
factory :slow_user do
|
11
|
+
after_build { Kernel.sleep(0.1) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "tracks proper time of creating the record" do
|
19
|
+
time_to_execute = 0
|
20
|
+
callback = ->(name, start, finish, id, payload) { time_to_execute = finish - start }
|
21
|
+
ActiveSupport::Notifications.subscribed(callback, "factory_girl.run_factory") do
|
22
|
+
FactoryGirl.build(:slow_user)
|
23
|
+
end
|
24
|
+
|
25
|
+
time_to_execute.should be_within(0.01).of(0.1)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "builds the correct payload" do
|
29
|
+
tracked_invocations = {}
|
30
|
+
|
31
|
+
callback = ->(name, start, finish, id, payload) do
|
32
|
+
factory_name = payload[:name]
|
33
|
+
strategy_name = payload[:strategy]
|
34
|
+
tracked_invocations[factory_name] ||= {}
|
35
|
+
tracked_invocations[factory_name][strategy_name] ||= 0
|
36
|
+
tracked_invocations[factory_name][strategy_name] += 1
|
37
|
+
end
|
38
|
+
|
39
|
+
ActiveSupport::Notifications.subscribed(callback, "factory_girl.run_factory") do
|
40
|
+
FactoryGirl.build_list(:slow_user, 2)
|
41
|
+
FactoryGirl.build_list(:user, 5)
|
42
|
+
FactoryGirl.create_list(:user, 2)
|
43
|
+
FactoryGirl.attributes_for(:slow_user)
|
44
|
+
end
|
45
|
+
|
46
|
+
tracked_invocations[:slow_user].should == { build: 2, attributes_for: 1 }
|
47
|
+
tracked_invocations[:user].should == { build: 5, create: 2 }
|
48
|
+
end
|
49
|
+
end
|