diff --git a/lib/factory_girl.rb b/lib/factory_girl.rb index 92bb8b5..6fb8481 100644 --- a/lib/factory_girl.rb +++ b/lib/factory_girl.rb @@ -54,6 +54,26 @@ module FactoryGirl @configuration = nil end + def self.lint + invalid_factories = FactoryGirl.factories.select do |factory| + built_factory = FactoryGirl.build(factory.name) + + if built_factory.respond_to?(:valid?) + !built_factory.valid? + end + end + + if invalid_factories.any? + error_message = <<-ERROR_MESSAGE.strip +The following factories are invalid: + +#{invalid_factories.map {|factory| "* #{factory.name}" }.join("\n")} + ERROR_MESSAGE + + raise InvalidFactoryError, error_message + end + end + class << self delegate :factories, :sequences, :traits, :callbacks, :strategies, :callback_names, :to_create, :skip_create, :initialize_with, :constructor, :duplicate_attribute_assignment_from_initialize_with, diff --git a/lib/factory_girl/errors.rb b/lib/factory_girl/errors.rb index c0aa100..5c0956d 100644 --- a/lib/factory_girl/errors.rb +++ b/lib/factory_girl/errors.rb @@ -19,4 +19,7 @@ module FactoryGirl # Raised when a method is defined in a factory or trait with arguments class MethodDefinitionError < RuntimeError; end + + # Raised when any factory is considered invalid + class InvalidFactoryError < RuntimeError; end end diff --git a/spec/acceptance/lint_spec.rb b/spec/acceptance/lint_spec.rb new file mode 100644 index 0000000..3315ed3 --- /dev/null +++ b/spec/acceptance/lint_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe 'FactoryGirl.lint' do + it 'raises when a factory is invalid' do + define_model 'User', name: :string do + validates :name, presence: true + end + + define_model 'AlwaysValid' + + FactoryGirl.define do + factory :user do + factory :admin_user + end + + factory :always_valid + end + + error_message = <<-ERROR_MESSAGE.strip +The following factories are invalid: + +* user +* admin_user + ERROR_MESSAGE + + expect do + FactoryGirl.lint + end.to raise_error FactoryGirl::InvalidFactoryError, error_message + end + + it 'does not raise when all factories are valid' do + define_model 'User', name: :string do + validates :name, presence: true + end + + FactoryGirl.define do + factory :user do + name 'assigned' + end + end + + expect { FactoryGirl.lint }.not_to raise_error + end + + it 'supports models which do not respond to #valid?' do + define_class 'Thing' + + FactoryGirl.define do + factory :thing + end + + expect(Thing.new).not_to respond_to(:valid?) + expect { FactoryGirl.lint }.not_to raise_error + end +end