Add FactoryGirl.lint to ensure all factories are valid

This commit adds FactoryGirl.lint, which iterates over each defined
factory, builds it, and ensures it is valid. If any factories are
invalid, an exception is raised and includes the names of each invalid
factory.
This commit is contained in:
Joshua Clayton 2014-02-07 10:09:20 -05:00
parent fea0ad12d9
commit 6a692fe711
3 changed files with 78 additions and 0 deletions

View File

@ -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,

View File

@ -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

View File

@ -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