Open-Source Wikis

/

GitLab

/

How to contribute

/

Testing

gitlab-org/gitlab

Testing

GitLab uses many test frameworks. The right one depends on the layer you're touching.

Test pyramid

Layer Framework Source location Run command
Ruby unit and integration RSpec spec/, ee/spec/ bin/rspec
Frontend unit Jest spec/frontend/, ee/spec/frontend/ yarn jest
Frontend integration (MSW) Jest + MSW spec/frontend_integration/ yarn jest:integration
Frontend contract Jest spec/frontend/contract/ yarn jest:contract
End-to-end Capybara + Selenium qa/qa/specs/ bin/qa Test::Instance::All
Workhorse Go Go testing workhorse/ make test (in workhorse/)
Frontend visual snapshots Jest spec/frontend/snapshots yarn jest:snapshots
Performance / regression RSpec + custom spec/benchmarks/ RSpec
Database migration RSpec spec/migrations/, spec/lib/gitlab/database/ RSpec

RSpec patterns

Specs are split across:

  • spec/ — FOSS specs.
  • ee/spec/ — EE specs and EE-only behavior.
  • qa/spec/ — unit tests for the QA framework itself (not e2e tests).

Important conventions:

  • Each spec file declares feature_category in its top-level describe (feature_category: :continuous_integration). Enforced by RuboCop cop RSpec/FeatureCategory.
  • Database tests use the :js, :request_store, :redis, and similar metadata to opt into shared state.
  • EE-only behavior lives in ee/spec/ and is run only when EE_ENABLED=1 (default in this repo).
  • Use let_it_be (from test-prof) instead of let for objects that don't change between examples.
  • :freeze_time and :travel_to from ActiveSupport::Testing::TimeHelpers are preferred over Timecop.
  • Use stub_feature_flags(my_flag: true) to control feature flags in tests.

Run a single file:

bin/rspec spec/services/projects/create_service_spec.rb

Run a single example:

bin/rspec spec/services/projects/create_service_spec.rb:42

Jest patterns

Frontend tests live under spec/frontend/ mirroring app/assets/javascripts/. Several Jest configs exist:

  • jest.config.js — main runner.
  • jest.config.integration.js — integration tests with full app store/Apollo wiring.
  • jest.config.contract.js — Pact-based API contract tests.
  • jest.config.msw_integration.js — Mock Service Worker integration tests.
  • jest.config.snapshots.js — Vue snapshot tests.
  • jest.config.scripts.js — tests for build scripts.

Conventions:

  • Vue Test Utils for component mounting.
  • MockAdapter for axios; MockGraphQL helpers for Apollo.
  • setImmediate and flushPromises to wait for async UI updates.
  • Snapshot files are checked in; review diffs carefully.

Workhorse tests

cd workhorse
make test          # full suite
make test-race     # with race detector
go test ./internal/upload -run TestRequestBody   # single test

Integration tests need GITALY_ADDRESS set; when in doubt, run the unit tests only with go test ./internal/....

QA / E2E

The qa/ directory contains both the Capybara-based test framework and the test cases. Two execution targets:

  • Static instance test: GDK or any live GitLab.
  • Omnibus: ephemeral Docker GitLab spun up in CI.

Run a single E2E from a GDK instance:

bin/qa Test::Instance::All http://gdk.test:3000 --tag smoke -- spec/features/login_spec.rb

The QA suite is selectively triggered in MR pipelines via the package-and-qa manual job, and runs nightly against the main branch.

Running the right subset

CI uses a test-file-finder mapping (tests.yml and the tff system in tooling/) to run only the specs affected by your changes. Locally, scripts/run-fast-specs.sh reproduces a fast subset.

For migrations: spec/migrations/<migration_timestamp>_<class_name>_spec.rb and spec/lib/gitlab/database/migration_helpers/.

Coverage and flakiness

  • Coverage reports come from SimpleCov (scripts/merge-simplecov) and Cobertura.
  • Flaky tests are tracked via scripts/flaky_examples/ and the gitlab-rspec_flaky gem.
  • Test failures triage: scripts/failed_tests.rb summarizes failures across parallel jobs.

Database test setup

The first time you run RSpec, the database needs to be set up:

bin/rake db:test:prepare

For multi-database tests, use:

bin/rake db:reset:all

EE-only specs may require EE_ENABLED=1:

EE_ENABLED=1 bin/rspec ee/spec/...

Mocking external services

  • WebMock blocks all real HTTP by default; use stub_request.
  • Gitaly calls are stubbed with stub_gitaly_calls helpers in spec/support/.
  • Sidekiq jobs run inline by default; use Sidekiq::Testing.fake! to enqueue without executing.
  • ClickHouse is stubbed with stub_click_house_query.

When to write what

Change Recommended test
Pure Ruby logic in services/ or lib/ Unit RSpec
ActiveRecord scope or association Model spec
Permission rule Policy spec under spec/policies/
GraphQL mutation/query Request spec under spec/requests/api/graphql/
REST endpoint Request spec under spec/requests/api/
Vue component Jest component spec
Vuex/Pinia store action Jest store spec
User-facing feature Feature spec under spec/features/ (system test)
Migration Migration spec under spec/migrations/
Workhorse handler Go test in workhorse/internal/<pkg>/
  • Debugging — debugging failing tests.
  • Tooling — RSpec / Jest plugins and helpers.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Testing – GitLab wiki | Factory