The README says:
Recommended usage of FactoryGirl.lint is to invoke this once before the test suite is run.
But doesn't that imply that even when running a single test, e.g. as part of TDD, every factory will be linted, causing a dramatic slowdown?
Agreed. The slowdown was brutally painful when invoked the way described here.
This is not ideal, but we ended up creating a lint_spec
file that serves only to invoke FactoryGirl.lint
.
# spec/lint_spec.rb
require "rails_helper"
RSpec.describe "Lint" do
it "FactoryGirl" do
FactoryGirl.lint
end
end
You are correct @andyw8. We actually removed that same usage from suspenders here: https://github.com/thoughtbot/suspenders/commit/0dbbc626e5da9f6ee94e1226487b4017cd2b8099 due to the exact same issue.
I'm going to open a PR to update the documentation to recommend running that in a separate task.
I edited a bit the example rake task you give to allow linting only specific factories.
# lib/tasks/factory_girl.rake
namespace :factory_girl do
desc 'Verify that FactoryGirl factories are valid'
task :lint, [:path] => :environment do |t, args|
if Rails.env.test?
begin
DatabaseCleaner.start
if args.path.present?
factories = FactoryGirl.factories.select do |factory|
factory.name.to_s =~ /#{args.path[0]}/
end
FactoryGirl.lint factories
else
FactoryGirl.lint
end
ensure
DatabaseCleaner.clean
end
else
system("bundle exec rake factory_girl:lint RAILS_ENV='test'")
end
end
end
It is particularly useful with guard-rake to watch factories and only lint the ones changing.
# Guardfile
guard :rake, task: 'factory_girl:lint' do
watch(%r{^spec/factories/(.+)s.rb$}) { |m| "#{m[1]}" }
end
This example assume that all inherited factories in the file contains their parent name in theirs (_e.g._ user, user_with_contacts, super_user, etc.).
Could be improved by using the @parent attribute from FactoryGirl instances I guess.
FWIW: the documentation for linting now has a similar example of a rake task.
Most helpful comment
Agreed. The slowdown was brutally painful when invoked the way described here.
This is not ideal, but we ended up creating a
lint_spec
file that serves only to invokeFactoryGirl.lint
.