Skip to content

GitLab Next

  • Menu
Projects Groups Snippets
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • GitLab GitLab
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 39,511
    • Issues 39,511
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 1,222
    • Merge requests 1,222
  • Requirements
    • Requirements
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
    • Value stream
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GitLab.org
  • GitLabGitLab
  • Issues
  • #262624

Closed
Open
Created Oct 06, 2020 by Peter Leitzen@splattael🔶Maintainer3 of 7 tasks completed3/7 tasks

Avoid usage of create/build in factory associations

Preamble

In #240929 (closed), we've changed FactoryBot's strategy to use the same build strategy as their parent object.

@engwan mentioned the following problem in #240929 (comment 422724486).

Problem

Our factories make use of create / build in associations, for example project's creator:

FactoryBot.define do
  factory :project, class: 'Project' do
    ...

    # Associations
    namespace
    creator { group ? create(:user) : namespace&.owner }

    ...
  end
end

group = FactoryBot.build(:group)
group.persisted? # => false

project = FactoryBot.build(:project, group: group)
project.persisted? # => false

# However:
project.creator.persisted? # => true

We are persisting a user record even if the build strategy is used. This behaviour potentially leads to a higher number of SQL queries which slows down our test suite.

Solution

Avoid the use of create / build in factory associations and prefer implicit or explicit association definitions.

To fix the example above we could use:

diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 091c9d5a245..87e4a8e355d 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -15,7 +15,7 @@ FactoryBot.define do
 
     # Associations
     namespace
-    creator { group ? create(:user) : namespace&.owner }
+    creator { group ? association(:user) : namespace&.owner }
 
     transient do
       # Nest Project Feature attributes

Proposed solution

  • Mention explicit/implicit associations in Testing best practices > Factories - !44447 (merged)
  • Create a 👮 to flag
    • create / build in factory associations - !44840 (merged)
      • prefer inline association definition such as association(:model)
      • Fix current occurrences - #267606 (closed)
    • create / build in after callbacks - ?
      • prefer plain assocations
    • create_list and build_list in factory associations - ?
      • prefer Array.new(x) { association(:model) } instead
      • Fix current occurrences - ?
  • Watch total amount of SQL queries go down in https://gitlab-org.gitlab.io/rspec_profiling_stats/ 🎉

Risks

We might see specs starting to fail if they assume that associations are always persisted.

In the case of the example above we are safe though. See !44429 (merged).

Edited Oct 16, 2020 by Peter Leitzen
Assignee
Assign to
Time tracking