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_categoryin its top-leveldescribe(feature_category: :continuous_integration). Enforced by RuboCop copRSpec/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 whenEE_ENABLED=1(default in this repo). - Use
let_it_be(fromtest-prof) instead ofletfor objects that don't change between examples. :freeze_timeand:travel_tofromActiveSupport::Testing::TimeHelpersare preferred overTimecop.- 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.rbRun a single example:
bin/rspec spec/services/projects/create_service_spec.rb:42Jest 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.
MockAdapterfor axios;MockGraphQLhelpers for Apollo.setImmediateandflushPromisesto 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 testIntegration 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.rbThe 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 thegitlab-rspec_flakygem. - Test failures triage:
scripts/failed_tests.rbsummarizes failures across parallel jobs.
Database test setup
The first time you run RSpec, the database needs to be set up:
bin/rake db:test:prepareFor multi-database tests, use:
bin/rake db:reset:allEE-only specs may require EE_ENABLED=1:
EE_ENABLED=1 bin/rspec ee/spec/...Mocking external services
WebMockblocks all real HTTP by default; usestub_request.Gitalycalls are stubbed withstub_gitaly_callshelpers inspec/support/.Sidekiqjobs run inline by default; useSidekiq::Testing.fake!to enqueue without executing.ClickHouseis stubbed withstub_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>/ |
Related
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.