# Testing best practices
> 原文:[https://docs.gitlab.com/ee/development/testing_guide/best_practices.html](https://docs.gitlab.com/ee/development/testing_guide/best_practices.html)
* [Test Design](#test-design)
* [Test speed](#test-speed)
* [RSpec](#rspec)
* [General guidelines](#general-guidelines)
* [Coverage](#coverage)
* [System / Feature tests](#system--feature-tests)
* [Debugging Capybara](#debugging-capybara)
* [Live debug](#live-debug)
* [Run `:js` spec in a visible browser](#run-js-spec-in-a-visible-browser)
* [Screenshots](#screenshots)
* [Fast unit tests](#fast-unit-tests)
* [`let` variables](#let-variables)
* [Common test setup](#common-test-setup)
* [Time-sensitive tests](#time-sensitive-tests)
* [Feature flags in tests](#feature-flags-in-tests)
* [`stub_feature_flags` vs `Feature.enable*`](#stub_feature_flags-vs-featureenable)
* [Stubbing gate](#stubbing-gate)
* [Pristine test environments](#pristine-test-environments)
* [SQL database](#sql-database)
* [Redis](#redis)
* [Background jobs / Sidekiq](#background-jobs--sidekiq)
* [DNS](#dns)
* [Filesystem](#filesystem)
* [Persistent in-memory application state](#persistent-in-memory-application-state)
* [Table-based / Parameterized tests](#table-based--parameterized-tests)
* [Prometheus tests](#prometheus-tests)
* [Matchers](#matchers)
* [`be_like_time`](#be_like_time)
* [`have_gitlab_http_status`](#have_gitlab_http_status)
* [Testing query performance](#testing-query-performance)
* [QueryRecorder](#queryrecorder)
* [GitalyClient](#gitalyclient)
* [Shared contexts](#shared-contexts)
* [Shared examples](#shared-examples)
* [Helpers](#helpers)
* [Factories](#factories)
* [Fixtures](#fixtures)
* [Repositories](#repositories)
* [Configuration](#configuration)
* [Test environment logging](#test-environment-logging)
# Testing best practices[](#testing-best-practices "Permalink")
## Test Design[](#test-design "Permalink")
在 manbetx 客戶端打不開的測試是頭等公民,而不是事后的想法. 在設計功能時,必須考慮測試的設計,這一點很重要.
在實現功能時,我們考慮以正確的方式開發正確的功能,這有助于我們將范圍縮小到可管理的水平. 在對功能進行測試時,我們必須考慮開發正確的測試,然后涵蓋測試可能失敗的*所有*重要方式,這可能很快將我們的范圍擴大到難以管理的水平.
測試啟發法可以幫助解決此問題. 它們簡明地解決了錯誤在我們的代碼中表現出來的許多常見方式. 在設計測試時,請花一些時間來回顧已知的測試啟發法,以告知我們的測試設計. 我們可以在" [測試工程"](https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-heuristics)部分的"手冊"中找到一些有用的啟發式方法.
## Test speed[](#test-speed "Permalink")
GitLab has a massive test suite that, without [parallelization](ci.html#test-suite-parallelization-on-the-ci), can take hours to run. It’s important that we make an effort to write tests that are accurate and effective *以及* fast.
關于測試性能,需要牢記以下幾點:
* `instance_double`和`spy`比`FactoryBot.build(...)`快
* `FactoryBot.build(...)`和`.build_stubbed`比`.create`更快.
* 當`build` , `build_stubbed` , `attributes_for` , `spy`或`instance_double`可以使用時,不要`create`對象. 數據庫持久性很慢!
* 除非*實際*需要測試有效,否則不要將功能標記為需要 JavaScript(通過 RSpec 中的`:js` ). 無頭瀏覽器測試很慢!
## RSpec[](#rspec "Permalink")
要運行 RSpec 測試:
```
# run test for a file
bin/rspec spec/models/project_spec.rb
# run test for the example on line 10 on that file
bin/rspec spec/models/project_spec.rb:10
# run tests matching the example name has that string
bin/rspec spec/models/project_spec.rb -e associations
# run all tests, will take hours for GitLab codebase!
bin/rspec
```
使用[Guard](https://github.com/guard/guard)連續監視更改,并僅運行匹配的測試:
```
bundle exec guard
```
一起使用 spring 和 guard 時,請改用`SPRING=1 bundle exec guard`來使用 spring.
使用[Factory Doctor](https://test-prof.evilmartians.io/#/factory_doctor.md)查找不必要的數據庫操作案例,這可能會導致測試緩慢.
```
# run test for path
FDOC=1 bin/rspec spec/[path]/[to]/[spec].rb
```
### General guidelines[](#general-guidelines "Permalink")
* 使用單個頂級`RSpec.describe ClassName`塊.
* 使用`.method`來描述類方法,并使用`#method`來描述實例方法.
* 使用`context`測試分支邏輯.
* 嘗試使測試的順序與類中的順序匹配.
* 嘗試遵循[四階段測試](https://thoughtbot.com/blog/four-phase-test)模式,使用換行符分隔各個階段.
* 使用`Gitlab.config.gitlab.host`而不是硬編碼`'localhost'`
* 不要斷言序列生成的屬性的絕對值(請參見[Gotchas](../gotchas.html#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute) ).
* 避免使用`expect_any_instance_of`或`allow_any_instance_of` (見[陷阱](../gotchas.html#do-not-assert-against-the-absolute-value-of-a-sequence-generated-attribute) ).
* 不要將`:each`參數提供給鉤子,因為它是默認值.
* 在鉤子`before`和`after` ,最好將它的作用域設置為`:context`不是`:all`
* 當使用作用在給定元素上的`execute_script` `evaluate_script("$('.js-foo').testSomething()")` (或`execute_script` )時,請事先使用 Capybara 匹配器(例如`find('.js-foo')` )以確保該元素實際存在.
* 使用`focus: true`可以隔離要運行的部分規范.
* 如果測試中有多個期望,請使用[`:aggregate_failures`](https://relishapp.com/rspec/rspec-core/docs/expectation-framework-integration/aggregating-failures) .
* 對于[空的測試描述塊](https://github.com/rubocop-hq/rspec-style-guide#it-and-specify) ,如果測試是不言自明的,請使用`specify`而不是`it do` .
* 當您需要一個實際上不存在的 ID / IID /訪問級別時,請使用`non_existing_record_id` / `non_existing_record_iid` / `non_existing_record_access_level` . 使用 123、1234 甚至 999 都很容易,因為在 CI 運行的情況下,這些 ID 實際上可能存在于數據庫中.
### Coverage[](#coverage "Permalink")
[`simplecov`](https://github.com/colszowka/simplecov)用于生成代碼測試覆蓋率報告. 它們是在 CI 上自動生成的,但在本地運行測試時不會自動生成. 要在計算機上運行規格文件時生成部分報告,請設置`SIMPLECOV`環境變量:
```
SIMPLECOV=1 bundle exec rspec spec/models/repository_spec.rb
```
覆蓋率報告會生成到應用程序根目錄下的`coverage`文件夾中,您可以在瀏覽器中打開這些報告,例如:
```
firefox coverage/index.html
```
使用覆蓋率報告來確保您的測試覆蓋 100%的代碼.
### System / Feature tests[](#system--feature-tests "Permalink")
**注意:**在編寫新的系統測試之前, [請考慮**不要**編寫一個](testing_levels.html#consider-not-writing-a-system-test) !
* Feature specs should be named `ROLE_ACTION_spec.rb`, such as `user_changes_password_spec.rb`.
* 使用描述成功和失敗路徑的方案標題.
* 避免方案標題未添加任何信息,例如"成功".
* 避免場景標題重復功能標題.
* Create only the necessary records in the database
* 測試一條幸福的道路和一條不太幸福的道路,僅此而已
* 所有其他可能的路徑均應通過單元測試或集成測試進行測試
* 測試頁面上顯示的內容,而不是 ActiveRecord 模型的內部. 例如,如果您要驗證是否已創建記錄,請添加期望其記錄顯示在頁面上的期望,而不是`Model.count`增加一.
* 可以查找 DOM 元素,但不要濫用它,因為它會使測試更加脆弱
#### Debugging Capybara[](#debugging-capybara "Permalink")
有時您可能需要通過觀察瀏覽器行為來調試 Capybara 測試.
#### Live debug[](#live-debug "Permalink")
您可以使用規范中的`live_debug`方法暫停 Capybara 并在瀏覽器中查看網站. 當前頁面將在默認瀏覽器中自動打開. 您可能需要先登錄(當前用戶的憑據顯示在終端中).
要恢復測試運行,請按任意鍵.
例如:
```
$ bin/rspec spec/features/auto_deploy_spec.rb:34
Running via Spring preloader in process 8999
Run options: include {:locations=>{"./spec/features/auto_deploy_spec.rb"=>[34]}}
Current example is paused for live debugging
The current user credentials are: user2 / 12345678
Press any key to resume the execution of the example!
Back to the example!
.
Finished in 34.51 seconds (files took 0.76702 seconds to load)
1 example, 0 failures
```
注意: `live_debug`僅在啟用 JavaScript 的規范上起作用.
#### Run `:js` spec in a visible browser[](#run-js-spec-in-a-visible-browser "Permalink")
使用`CHROME_HEADLESS=0`運行規范,例如:
```
CHROME_HEADLESS=0 bin/rspec some_spec.rb
```
測試將很快進行,但這將使您對正在發生的事情有所了解. 對`CHROME_HEADLESS=0`使用`live_debug`暫停打開的瀏覽器,并且不會再次打開該頁面. 這可用于調試和檢查元素.
您還可以添加`byebug`或`binding.pry`暫停執行,并[步通過](../pry_debugging.html#stepping)測試.
#### Screenshots[](#screenshots "Permalink")
我們使用`capybara-screenshot` gem 在失敗時自動截屏. 在 CI 中,您可以下載這些文件作為作業工件.
另外,您可以通過添加以下方法在測試中的任何時候手動獲取屏幕截圖. 請確保在不再需要它們時將其刪除! 有關更多信息,請參見[https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots](https://github.com/mattheworiordan/capybara-screenshot#manual-screenshots) .
在`:js`規范中添加`screenshot_and_save_page`以截圖 Capybara 看到的內容,并保存頁面源代碼.
在`:js`規范中添加`screenshot_and_open_image`以截圖 Capybara 看到的內容,并自動打開圖像.
由此創建的 HTML 轉儲缺少 CSS. 這導致它們看起來與實際應用程序截然不同. 有一個添加 CSS 的[小技巧](https://gitlab.com/gitlab-org/gitlab-foss/snippets/1718469) ,可簡化調試過程.
### Fast unit tests[](#fast-unit-tests "Permalink")
某些類與 Rails 完全隔離,您應該能夠測試它們,而不會因 Rails 環境和 Bundler 的`:default`組的 gem 加載而增加開銷. 在這些情況下,您可以在測試文件中`require 'fast_spec_helper'`而不是`require 'spec_helper'` ,并且由于以下原因,測試應該運行得非常快:
* 寶石加載被跳過
* Rails 應用啟動被跳過
* 跳過了 GitLab Shell 和 Gitaly 設置
* 測試存儲庫設置被跳過
`fast_spec_helper`還支持`lib/`目錄中的自動加載類. 這意味著只要您的類/模塊僅使用`lib/`目錄中的代碼,就無需顯式加載任何依賴項. `fast_spec_helper`還將加載所有 ActiveSupport 擴展,包括 Rails 環境中常用的核心擴展.
請注意,在某些情況下,當代碼使用 gems 或`lib/`沒有依賴項時,您可能仍必須使用`require_dependency`加載某些依賴項.
例如,如果要測試調用`Gitlab::UntrustedRegexp`類的代碼,該類在`Gitlab::UntrustedRegexp`使用`re2`庫,則應將`require_dependency 're2'`添加到需要`re2` gem 的庫文件中,以達到此要求明確,也可以將其添加到規范本身中,但最好使用前者.
加載使用`fast_spec_helper`測試大約需要一秒鐘,而不是常規`spec_helper`的 30+秒.
### `let` variables[](#let-variables "Permalink")
GitLab 的 RSpec 套件廣泛使用`let` (以及嚴格的非延遲版本`let!` )變量來減少重復. 但是,有時這有時要以[清楚為代價](https://thoughtbot.com/blog/lets-not) ,因此我們需要為以后的使用設置一些準則:
* `let!` 變量優于實例變量. `let`變量比`let!`可取`let!` 變量. 局部變量比`let`變量更可取.
* 使用`let`可以減少整個規格文件中的重復項.
* 不要使用`let`定義單個測試使用的變量; 在測試的`it`塊中將它們定義為局部變量.
* 不要在頂層`describe`塊中定義只用于更深層嵌套`context`或`describe`塊的`let`變量. 使定義盡可能靠近使用位置.
* 盡量避免將一個`let`變量的定義覆蓋另一個.
* 不要定義只供另一個定義使用的`let`變量. 請改用輔助方法.
* `let!` 變量應該只在需要與定義為了嚴格評估的情況下使用,否則`let`就足夠了. 請記住, `let`是惰性的,在被引用之前不會被評估.
### Common test setup[](#common-test-setup "Permalink")
在某些情況下,無需為每個示例再次創建相同的對象以進行測試. 例如,需要一個項目和該項目的訪客來測試同一項目上的問題,一個項目和一個用戶將對整個文件進行測試.
盡可能不要使用`before(:all)`或`before(:context)`實現此目的. 如果這樣做,您將需要手動清理數據,因為這些掛鉤在數據庫事務外部運行.
相反,這可以通過使用來實現[`let_it_be`](https://test-prof.evilmartians.io/#/let_it_be)變量和[`before_all`](https://test-prof.evilmartians.io/#/before_all)鉤從[`test-prof`的寶石](https://rubygems.org/gems/test-prof) .
```
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
before_all do
project.add_guest(user)
end
```
這將僅為此上下文創建一個`Project` , `User`和`ProjectMember` .
`let_it_be`和`before_all`在嵌套上下文中也可用. 使用事務回滾自動處理上下文后進行清理.
Note that if you modify an object defined inside a `let_it_be` block, then you will need to reload the object as needed, or specify the `reload` option to reload for every example.
```
let_it_be(:project, reload: true) { create(:project) }
```
您還可以指定`refind`選項以完全加載新對象.
```
let_it_be(:project, refind: true) { create(:project) }
```
### Time-sensitive tests[](#time-sensitive-tests "Permalink")
在基于 Ruby 的測試中可以使用[Timecop](https://github.com/travisjeffery/timecop)來驗證對時間敏感的事物. 任何鍛煉或驗證時間敏感的測試都應使用 Timecop 來防止瞬態測試失敗.
Example:
```
it 'is overdue' do
issue = build(:issue, due_date: Date.tomorrow)
Timecop.freeze(3.days.from_now) do
expect(issue).to be_overdue
end
end
```
### Feature flags in tests[](#feature-flags-in-tests "Permalink")
在基于 Ruby 的測試中,默認情況下所有功能標志都已啟用.
要在測試中禁用功能標記,請使用`stub_feature_flags`幫助器. 例如,要在測試中全局禁用`ci_live_trace`功能標志:
```
stub_feature_flags(ci_live_trace: false)
Feature.enabled?(:ci_live_trace) # => false
```
如果您希望設置一個僅對某些角色而不對其他角色啟用功能標志的測試,則可以在傳遞給助手的選項中指定此功能. 例如,要為特定項目啟用`ci_live_trace`功能標記:
```
project1, project2 = build_list(:project, 2)
# Feature will only be enabled for project1
stub_feature_flags(ci_live_trace: project1)
Feature.enabled?(:ci_live_trace) # => false
Feature.enabled?(:ci_live_trace, project1) # => true
Feature.enabled?(:ci_live_trace, project2) # => false
```
這代表了 FlipperGate 的實際行為:
1. 您可以啟用要啟用的指定角色的替代
2. 您可以禁用(刪除)指定角色的替代,并還原為默認狀態
3. 無法建模您明確禁用指定的參與者
```
Feature.enable(:my_feature)
Feature.disable(:my_feature, project1)
Feature.enabled?(:my_feature) # => true
Feature.enabled?(:my_feature, project1) # => true
```
```
Feature.disable(:my_feature2)
Feature.enable(:my_feature2, project1)
Feature.enabled?(:my_feature2) # => false
Feature.enabled?(:my_feature2, project1) # => true
```
#### `stub_feature_flags` vs `Feature.enable*`[](#stub_feature_flags-vs-featureenable "Permalink")
最好使用`stub_feature_flags`在測試環境中啟用功能標志. 該方法為簡單的用例提供了一個簡單且描述良好的界面.
但是,在某些情況下,需要測試更復雜的行為,例如功能標志百分比展示. 這可以使用`.enable_percentage_of_time`和`.enable_percentage_of_actors`來實現
```
# Good: feature needs to be explicitly disabled, as it is enabled by default if not defined
stub_feature_flags(my_feature: false)
stub_feature_flags(my_feature: true)
stub_feature_flags(my_feature: project)
stub_feature_flags(my_feature: [project, project2])
# Bad
Feature.enable(:my_feature_2)
# Good: enable my_feature for 50% of time
Feature.enable_percentage_of_time(:my_feature_3, 50)
# Good: enable my_feature for 50% of actors/gates/things
Feature.enable_percentage_of_actors(:my_feature_4, 50)
```
具有定義狀態的每個功能標志將在測試執行時間內保留:
```
Feature.persisted_names.include?('my_feature') => true
Feature.persisted_names.include?('my_feature_2') => true
Feature.persisted_names.include?('my_feature_3') => true
Feature.persisted_names.include?('my_feature_4') => true
```
#### Stubbing gate[](#stubbing-gate "Permalink")
要求將作為參數傳遞給`Feature.enabled?` 和`Feature.disabled?` 是包含`FeatureGate`的對象.
在規范中,您可以使用`stub_feature_flag_gate`方法,該方法可讓您快速使用自定義門:
```
gate = stub_feature_flag_gate('CustomActor')
stub_feature_flags(ci_live_trace: gate)
Feature.enabled?(:ci_live_trace) # => false
Feature.enabled?(:ci_live_trace, gate) # => true
```
### Pristine test environments[](#pristine-test-environments "Permalink")
單個 GitLab 測試執行的代碼可以訪問和修改許多數據項. 無需在測試運行之前進行仔細的準備,然后再進行清理,則測試可以更改數據,從而影響后續測試的行為. 應不惜一切代價避免這種情況! 幸運的是,現有的測試框架已經可以處理大多數情況.
當測試環境確實受到污染時,常見的結果就是[不穩定的測試](flaky_tests.html) . 污染通常表現為順序依賴性:運行規格 A,然后運行規格 B 會可靠地失敗,但是運行規格 B,然后運行規格 A 將可靠地成功. 在這些情況下,可以使用`rspec --bisect` (或規格文件的手動成對二`rspec --bisect` )來確定哪個規格有問題. 要解決此問題,需要對測試套件如何確保原始環境有一些了解. 繼續閱讀以發現有關每個數據存儲的更多信息!
#### SQL database[](#sql-database "Permalink")
這是由`database_cleaner` gem 為我們管理的. 每個規范都包含在一個事務中,一旦測試完成,該事務將回滾. 某些規范將在完成后針對每個表發出`DELETE FROM`查詢; 這樣可以從多個數據庫連接中查看創建的行,這對于在瀏覽器中運行的規范或遷移規范等非常重要.
使用這些策略而不是眾所周知的`TRUNCATE TABLES`方法的結果是,主鍵和其他序列**不會**在整個規范中重置. 因此,如果您在規范 A 中創建一個項目,然后在規范 B 中創建一個項目,則第一個將具有`id=1` ,而第二個將具有`id=2` .
這意味著規范**永遠**不應依賴 ID 或任何其他序列生成的列的值. 為避免意外沖突,規范還應避免手動指定此類列中的任何值. 而是將它們保留為未指定狀態,并在創建行后查找值.
#### Redis[](#redis "Permalink")
GitLab 在 Redis 中存儲了兩個主要的數據類別:緩存項和 Sidekiq 作業.
在大多數規范中,Rails 緩存實際上是一個內存存儲. 規格之間已替換了該代碼,因此對`Rails.cache.read`和`Rails.cache.write`調用是安全的. 但是,如果某個規范直接進行 Redis 調用,則應適當地使用`:clean_gitlab_redis_cache` , `:clean_gitlab_redis_shared_state`或`:clean_gitlab_redis_queues`特征對其進行標記.
#### Background jobs / Sidekiq[](#background-jobs--sidekiq "Permalink")
默認情況下,Sidekiq 作業會排隊到作業數組中,并且不會進行處理. 如果測試將 Sidekiq 作業排入隊列并需要對其進行處理,則可以使用`:sidekiq_inline`特性.
The `:sidekiq_might_not_need_inline` trait was added when [Sidekiq inline mode was changed to fake mode](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15479) to all the tests that needed Sidekiq to actually process jobs. Tests with this trait should be either fixed to not rely on Sidekiq processing jobs, or their `:sidekiq_might_not_need_inline` trait should be updated to `:sidekiq_inline` if the processing of background jobs is needed/expected.
**注意:** `perform_enqueued_jobs`的用法僅對測試延遲的郵件傳遞有用,因為我們的 Sidekiq 工作者不是從`ApplicationJob` / `ActiveJob::Base`繼承.
#### DNS[](#dns "Permalink")
DNS 請求在測試套件中普遍存在(截至[!22368](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22368) ),因為 DNS 可能會導致問題,具體取決于開發人員的本地網絡. 在`spec/support/dns.rb`有可用的 RSpec 標簽,如果您需要繞過 DNS 存根,則可以將其應用于測試,例如:
```
it "really connects to Prometheus", :permit_dns do
```
而且,如果需要更具體的控制,則可以在`spec/support/helpers/dns_helpers.rb`實現 DNS 阻止,并且可以在其他地方調用這些方法.
#### Filesystem[](#filesystem "Permalink")
文件系統數據可以大致分為"存儲庫"和"其他所有內容". 存儲庫存儲在`tmp/tests/repositories` . 在測試運行開始之前和測試運行結束之后,將清空此目錄. 在規格之間不清空它,因此在過程的整個生命周期中,創建的存儲庫都在此目錄中累積. 刪除它們很昂貴,但是除非精心管理,否則可能會導致污染.
為避免這種情況,在測試套件中啟用了[哈希存儲](../../administration/repository_storage_types.html) . 這意味著將為存儲庫提供一個唯一的路徑,該路徑取決于其項目的 ID. 由于在規范之間未重置項目 ID,因此可以確保每個規范在磁盤上獲得自己的存儲庫,并防止在規范之間可見更改.
如果規范手動指定了項目 ID,或直接檢查`tmp/tests/repositories/`目錄的狀態,則它應該在運行之前和之后清理該目錄. 通常,應完全避免這些模式.
鏈接到數據庫對象的其他文件類別(例如上載)通常以相同的方式進行管理. 在規范中啟用了散列存儲后,它們將在 ID 確定的位置寫入磁盤,因此不會發生沖突.
一些規范通過將`:legacy_storage`特征傳遞給`projects`工廠來禁用哈希存儲. 執行此操作的規范絕**不能**覆蓋項目或其任何組的`path` . 默認路徑包含項目 ID,因此不會發生沖突. 但是,如果兩個規范創建具有相同路徑的`:legacy_storage`項目,則它們將使用磁盤上的相同存儲庫并導致測試環境污染.
其他文件必須由規范手動管理. 例如,如果運行創建`tmp/test-file.csv`文件的代碼,則規范必須確保在清理過程中刪除了該文件.
#### Persistent in-memory application state[](#persistent-in-memory-application-state "Permalink")
給定`rspec`運行中的所有規范共享相同的 Ruby 進程,這意味著它們可以通過修改規范之間可訪問的 Ruby 對象相互影響. 實際上,這意味著全局變量和常量(包括 Ruby 類,模塊等).
全局變量通常不應修改. 如果絕對必要,則可以使用如下所示的塊來確保更改被回滾:
```
around(:each) do |example|
old_value = $0
begin
$0 = "new-value"
example.run
ensure
$0 = old_value
end
end
```
如果規范需要修改常量,則應使用`stub_const`幫助器以確保更改被回滾.
如果需要修改`ENV`常量的內容,則可以改用`stub_env`幫助器方法.
雖然大多數 Ruby **實例**不在規范之間共享,但**類**和**模塊**通常是共享的. 類和模塊實例變量,訪問器,類變量和其他有狀態習語應與全局變量一樣對待-除非必須修改,否則請勿對其進行修改! 特別是,最好使用期望值或依賴項注入以及存根,以避免進行修改. 如果沒有其他選擇,可以使用類似于上面的全局變量示例的`around`塊,但應盡可能避免這種情況.
### Table-based / Parameterized tests[](#table-based--parameterized-tests "Permalink")
這種測試風格用于執行一段具有廣泛輸入范圍的代碼. 通過一次指定測試用例,并在每個輸入和預期輸出表的旁邊,可以使您的測試更易于閱讀和緊湊.
我們使用[RSpec :: Parameterized](https://github.com/tomykaira/rspec-parameterized) gem. 一個簡短的示例,使用表語法并檢查 Ruby 相等性是否為一系列輸入,可能看起來像這樣:
```
describe "#==" do
using RSpec::Parameterized::TableSyntax
where(:a, :b, :result) do
1 | 1 | true
1 | 2 | false
true | true | true
true | false | false
end
with_them do
it { expect(a == b).to eq(result) }
it 'is isomorphic' do
expect(b == a).to eq(result)
end
end
end
```
**注意:**僅將簡單值用作`where`塊中的輸入. 使用 proc,有狀態對象,FactoryBot 創建的對象等可能導致[意外結果](https://github.com/tomykaira/rspec-parameterized/issues/8) .
### Prometheus tests[](#prometheus-tests "Permalink")
可以將 Prometheus 度量從一次測試運行保存到另一次測試. 為了確保在每個示例之前重置指標,請在 RSpec 測試中添加`:prometheus`標記.
### Matchers[](#matchers "Permalink")
應該創建自定義匹配器以闡明意圖和/或隱藏 RSpec 期望的復雜性. 它們應放在`spec/support/matchers/` . 如果匹配器僅適用于某種類型的規范(例如功能,請求等),則可以放在子文件夾中,但如果它們適用于多種類型的規范,則不應該放在子文件夾中.
#### `be_like_time`[](#be_like_time "Permalink")
從數據庫返回的時間的精度可能與 Ruby 中的時間對象不同,因此在規格比較時我們需要靈活的容差. 我們可以使用`be_like_time`來比較時間在彼此之間一秒之內.
Example:
```
expect(metrics.merged_at).to be_like_time(time)
```
#### `have_gitlab_http_status`[](#have_gitlab_http_status "Permalink")
`have_gitlab_http_status`使用`have_http_status`而不是`have_http_status`和`have_http_status` `expect(response.status).to` `have_http_status` ,因為只要狀態不匹配,前者還可以顯示響應主體. 每當某些測試開始中斷時,這將非常有用,我們很想知道為什么不編輯源代碼并重新運行測試.
每當它顯示 500 內部服務器錯誤時,此功能特別有用.
在數字表示形式`206` `:no_content`命名為 HTTP 的狀態,如`:no_content` . 請參閱[支持的狀態代碼](https://github.com/rack/rack/blob/f2d2df4016a906beec755b63b4edfcc07b58ee05/lib/rack/utils.rb#L490)列表.
Example:
```
expect(response).to have_gitlab_http_status(:ok)
```
### Testing query performance[](#testing-query-performance "Permalink")
測試查詢性能使我們能夠:
* 斷言代碼塊中不存在 N + 1 個問題.
* 確保代碼塊中的查詢數量不會被忽略.
#### QueryRecorder[](#queryrecorder "Permalink")
`QueryRecorder`允許分析和測試在給定代碼塊中執行的數據庫查詢的數量.
有關更多詳細信息,請參見[`QueryRecorder`](../query_recorder.html)部分.
#### GitalyClient[](#gitalyclient "Permalink")
`Gitlab::GitalyClient.get_request_count` allows tests of the number of Gitaly queries made by a given block of code:
有關更多詳細信息,請參見[`Gitaly Request Counts`](../gitaly.html#request-counts)部分.
### Shared contexts[](#shared-contexts "Permalink")
可以內聯聲明僅在一個規范文件中使用的共享上下文. 一個以上規范文件使用的任何共享上下文:
* 應該放在`spec/support/shared_contexts/` .
* 如果它們僅適用于某種類型的規范(例如功能,請求等),則可以放在子文件夾中,但如果它們適用于多種類型的規范,則不應放在子文件夾中.
每個文件應僅包含一個上下文并具有描述性名稱,例如`spec/support/shared_contexts/controllers/githubish_import_controller_shared_context.rb` .
### Shared examples[](#shared-examples "Permalink")
可以內聯聲明僅在一個規范文件中使用的共享示例. 多個規范文件使用的任何共享示例:
* 應該放在`spec/support/shared_examples/` .
* 如果它們僅適用于某種類型的規范(例如功能,請求等),則可以放在子文件夾中,但如果它們適用于多種類型的規范,則不應放在子文件夾中.
每個文件應僅包含一個上下文并具有描述性名稱,例如`spec/support/shared_examples/controllers/githubish_import_controller_shared_example.rb` .
### Helpers[](#helpers "Permalink")
幫助程序通常是提供一些隱藏特定 RSpec 示例復雜性的方法的模塊. 如果不希望與其他規范共享,則可以在 RSpec 文件中定義幫助程序. 否則,應將它們放在`spec/support/helpers/` . 如果助手僅適用于某種類型的規范(例如功能,請求等),則可以放在子文件夾中,但如果它們適用于多種類型的規范,則不應放在子文件夾中.
助手應遵循 Rails 的命名/命名空間約定. 例如`spec/support/helpers/cycle_analytics_helpers.rb`應該定義:
```
module Spec
module Support
module Helpers
module CycleAnalyticsHelpers
def create_commit_referencing_issue(issue, branch_name: random_git_name)
project.repository.add_branch(user, branch_name, 'master')
create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name)
end
end
end
end
end
```
助手不應更改 RSpec 配置. 例如,上述幫助器模塊不應包括:
```
RSpec.configure do |config|
config.include Spec::Support::Helpers::CycleAnalyticsHelpers
end
```
### Factories[](#factories "Permalink")
GitLab 使用[factory_bot](https://github.com/thoughtbot/factory_bot)替代測試夾具.
* 工廠定義存在于`spec/factories/` ,使用其對應模型的復數形式命名( `User`工廠在`users.rb`中定義).
* 每個文件應該只有一個頂級工廠定義.
* FactoryBot 方法混入了所有 RSpec 組. 這意味著您可以(并且應該)調用`create(...)`而不是`FactoryBot.create(...)` .
* 利用[特征](https://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md#traits)來清理定義和用法.
* 定義工廠時,請勿定義結果記錄通過驗證不需要的屬性.
* 從工廠實例化時,不要提供測試不需要的屬性.
* 工廠不必僅限于`ActiveRecord`對象. [參見示例](https://gitlab.com/gitlab-org/gitlab-foss/commit/0b8cefd3b2385a21cfed779bd659978c0402766d) .
### Fixtures[](#fixtures "Permalink")
所有固定裝置應放置在`spec/fixtures/` .
### Repositories[](#repositories "Permalink")
測試某些功能(例如,合并合并請求)需要在測試環境中具有某種狀態的 Git 存儲庫. GitLab 在某些常見情況下會維護[`gitlab-test`](https://gitlab.com/gitlab-org/gitlab-test)存儲庫-您可以確保該存儲庫的副本與`:repository`特性一起用于項目工廠:
```
let(:project) { create(:project, :repository) }
```
可以的話,請考慮使用`:custom_repo`特性而不是`:repository` . 這使您可以精確地指定哪些文件將出現在項目存儲庫的`master`分支中. 例如:
```
let(:project) do
create(
:project, :custom_repo,
files: {
'README.md' => 'Content here',
'foo/bar/baz.txt' => 'More content here'
}
)
end
```
這將創建一個包含兩個文件的存儲庫,這兩個文件具有默認權限和指定的內容.
### Configuration[](#configuration "Permalink")
RSpec 配置文件是更改 RSpec 配置的文件(即`RSpec.configure do |config|`塊). 它們應放在`spec/support/` .
每個文件都應與特定域相關,例如`spec/support/capybara.rb` , `spec/support/carrierwave.rb`等.
如果 helpers 模塊僅適用于某種規格,則應在`config.include`調用中添加修飾符. 例如,如果`spec/support/helpers/cycle_analytics_helpers.rb`僅適用于`:lib`和`type: :model` specs,則應編寫以下內容:
```
RSpec.configure do |config|
config.include Spec::Support::Helpers::CycleAnalyticsHelpers, :lib
config.include Spec::Support::Helpers::CycleAnalyticsHelpers, type: :model
end
```
If a configuration file only consists of `config.include`, you can add these `config.include` directly in `spec/spec_helper.rb`.
對于非常通用的幫助程序,請考慮將它們包括在`spec/support/rspec.rb`文件使用的`spec/fast_spec_helper.rb`文件中. 有關`spec/fast_spec_helper.rb`文件的更多詳細信息,請參見[快速單元測試](#fast-unit-tests) .
### Test environment logging[](#test-environment-logging "Permalink")
在運行測試時,會自動配置并啟動用于測試環境的服務,包括 Gitaly,Workhorse,Elasticsearch 和 Capybara. 在 CI 中運行時,或者如果需要安裝服務,則測試環境將記錄有關設置時間的信息,并產生如下日志消息:
```
==> Setting up Gitaly...
Gitaly set up in 31.459649 seconds...
==> Setting up GitLab Workhorse...
GitLab Workhorse set up in 29.695619 seconds...
fatal: update refs/heads/diff-files-symlink-to-image: invalid <newvalue>: 8cfca84
From https://gitlab.com/gitlab-org/gitlab-test
* [new branch] diff-files-image-to-symlink -> origin/diff-files-image-to-symlink
* [new branch] diff-files-symlink-to-image -> origin/diff-files-symlink-to-image
* [new branch] diff-files-symlink-to-text -> origin/diff-files-symlink-to-text
* [new branch] diff-files-text-to-symlink -> origin/diff-files-text-to-symlink
b80faa8..40232f7 snippet/multiple-files -> origin/snippet/multiple-files
* [new branch] testing/branch-with-#-hash -> origin/testing/branch-with-#-hash
==> Setting up GitLab Elasticsearch Indexer...
GitLab Elasticsearch Indexer set up in 26.514623 seconds...
```
當在本地運行并且不需要執行任何操作時,將忽略此信息. 如果您始終希望看到這些消息,請設置以下環境變量:
```
GITLAB_TESTING_LOG_LEVEL=debug
```
* * *
[Return to Testing documentation](index.html)
- GitLab Docs
- Installation
- Requirements
- GitLab cloud native Helm Chart
- Install GitLab with Docker
- Installation from source
- Install GitLab on Microsoft Azure
- Installing GitLab on Google Cloud Platform
- Installing GitLab on Amazon Web Services (AWS)
- Analytics
- Code Review Analytics
- Productivity Analytics
- Value Stream Analytics
- Kubernetes clusters
- Adding and removing Kubernetes clusters
- Adding EKS clusters
- Adding GKE clusters
- Group-level Kubernetes clusters
- Instance-level Kubernetes clusters
- Canary Deployments
- Cluster Environments
- Deploy Boards
- GitLab Managed Apps
- Crossplane configuration
- Cluster management project (alpha)
- Kubernetes Logs
- Runbooks
- Serverless
- Deploying AWS Lambda function using GitLab CI/CD
- Securing your deployed applications
- Groups
- Contribution Analytics
- Custom group-level project templates
- Epics
- Manage epics
- Group Import/Export
- Insights
- Issues Analytics
- Iterations
- Public access
- SAML SSO for GitLab.com groups
- SCIM provisioning using SAML SSO for GitLab.com groups
- Subgroups
- Roadmap
- Projects
- GitLab Secure
- Security Configuration
- Container Scanning
- Dependency Scanning
- Dependency List
- Static Application Security Testing (SAST)
- Secret Detection
- Dynamic Application Security Testing (DAST)
- GitLab Security Dashboard
- Offline environments
- Standalone Vulnerability pages
- Security scanner integration
- Badges
- Bulk editing issues and merge requests at the project level
- Code Owners
- Compliance
- License Compliance
- Compliance Dashboard
- Create a project
- Description templates
- Deploy Keys
- Deploy Tokens
- File finder
- Project integrations
- Integrations
- Atlassian Bamboo CI Service
- Bugzilla Service
- Custom Issue Tracker service
- Discord Notifications service
- Enabling emails on push
- GitHub project integration
- Hangouts Chat service
- Atlassian HipChat
- Irker IRC Gateway
- GitLab Jira integration
- Mattermost Notifications Service
- Mattermost slash commands
- Microsoft Teams service
- Mock CI Service
- Prometheus integration
- Redmine Service
- Slack Notifications Service
- Slack slash commands
- GitLab Slack application
- Webhooks
- YouTrack Service
- Insights
- Issues
- Crosslinking Issues
- Design Management
- Confidential issues
- Due dates
- Issue Boards
- Issue Data and Actions
- Labels
- Managing issues
- Milestones
- Multiple Assignees for Issues
- Related issues
- Service Desk
- Sorting and ordering issue lists
- Issue weight
- Associate a Zoom meeting with an issue
- Merge requests
- Allow collaboration on merge requests across forks
- Merge Request Approvals
- Browser Performance Testing
- How to create a merge request
- Cherry-pick changes
- Code Quality
- Load Performance Testing
- Merge Request dependencies
- Fast-forward merge requests
- Merge when pipeline succeeds
- Merge request conflict resolution
- Reverting changes
- Reviewing and managing merge requests
- Squash and merge
- Merge requests versions
- Draft merge requests
- Members of a project
- Migrating projects to a GitLab instance
- Import your project from Bitbucket Cloud to GitLab
- Import your project from Bitbucket Server to GitLab
- Migrating from ClearCase
- Migrating from CVS
- Import your project from FogBugz to GitLab
- Gemnasium
- Import your project from GitHub to GitLab
- Project importing from GitLab.com to your private GitLab instance
- Import your project from Gitea to GitLab
- Import your Jira project issues to GitLab
- Migrating from Perforce Helix
- Import Phabricator tasks into a GitLab project
- Import multiple repositories by uploading a manifest file
- Import project from repo by URL
- Migrating from SVN to GitLab
- Migrating from TFVC to Git
- Push Options
- Releases
- Repository
- Branches
- Git Attributes
- File Locking
- Git file blame
- Git file history
- Repository mirroring
- Protected branches
- Protected tags
- Push Rules
- Reduce repository size
- Signing commits with GPG
- Syntax Highlighting
- GitLab Web Editor
- Web IDE
- Requirements Management
- Project settings
- Project import/export
- Project access tokens (Alpha)
- Share Projects with other Groups
- Snippets
- Static Site Editor
- Wiki
- Project operations
- Monitor metrics for your CI/CD environment
- Set up alerts for Prometheus metrics
- Embedding metric charts within GitLab-flavored Markdown
- Embedding Grafana charts
- Using the Metrics Dashboard
- Dashboard YAML properties
- Metrics dashboard settings
- Panel types for dashboards
- Using Variables
- Templating variables for metrics dashboards
- Prometheus Metrics library
- Monitoring AWS Resources
- Monitoring HAProxy
- Monitoring Kubernetes
- Monitoring NGINX
- Monitoring NGINX Ingress Controller
- Monitoring NGINX Ingress Controller with VTS metrics
- Alert Management
- Error Tracking
- Tracing
- Incident Management
- GitLab Status Page
- Feature Flags
- GitLab CI/CD
- GitLab CI/CD pipeline configuration reference
- GitLab CI/CD include examples
- Introduction to CI/CD with GitLab
- Getting started with GitLab CI/CD
- How to enable or disable GitLab CI/CD
- Using SSH keys with GitLab CI/CD
- Migrating from CircleCI
- Migrating from Jenkins
- Auto DevOps
- Getting started with Auto DevOps
- Requirements for Auto DevOps
- Customizing Auto DevOps
- Stages of Auto DevOps
- Upgrading PostgreSQL for Auto DevOps
- Cache dependencies in GitLab CI/CD
- GitLab ChatOps
- Cloud deployment
- Docker integration
- Building Docker images with GitLab CI/CD
- Using Docker images
- Building images with kaniko and GitLab CI/CD
- GitLab CI/CD environment variables
- Predefined environment variables reference
- Where variables can be used
- Deprecated GitLab CI/CD variables
- Environments and deployments
- Protected Environments
- GitLab CI/CD Examples
- Test a Clojure application with GitLab CI/CD
- Using Dpl as deployment tool
- Testing a Phoenix application with GitLab CI/CD
- End-to-end testing with GitLab CI/CD and WebdriverIO
- DevOps and Game Dev with GitLab CI/CD
- Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD
- How to deploy Maven projects to Artifactory with GitLab CI/CD
- Testing PHP projects
- Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD
- Test and deploy Laravel applications with GitLab CI/CD and Envoy
- Test and deploy a Python application with GitLab CI/CD
- Test and deploy a Ruby application with GitLab CI/CD
- Test and deploy a Scala application to Heroku
- GitLab CI/CD for external repositories
- Using GitLab CI/CD with a Bitbucket Cloud repository
- Using GitLab CI/CD with a GitHub repository
- GitLab Pages
- GitLab Pages
- GitLab Pages domain names, URLs, and baseurls
- Create a GitLab Pages website from scratch
- Custom domains and SSL/TLS Certificates
- GitLab Pages integration with Let's Encrypt
- GitLab Pages Access Control
- Exploring GitLab Pages
- Incremental Rollouts with GitLab CI/CD
- Interactive Web Terminals
- Optimizing GitLab for large repositories
- Metrics Reports
- CI/CD pipelines
- Pipeline Architecture
- Directed Acyclic Graph
- Multi-project pipelines
- Parent-child pipelines
- Pipelines for Merge Requests
- Pipelines for Merged Results
- Merge Trains
- Job artifacts
- Pipeline schedules
- Pipeline settings
- Triggering pipelines through the API
- Review Apps
- Configuring GitLab Runners
- GitLab CI services examples
- Using MySQL
- Using PostgreSQL
- Using Redis
- Troubleshooting CI/CD
- GitLab Package Registry
- GitLab Container Registry
- Dependency Proxy
- GitLab Composer Repository
- GitLab Conan Repository
- GitLab Maven Repository
- GitLab NPM Registry
- GitLab NuGet Repository
- GitLab PyPi Repository
- API Docs
- API resources
- .gitignore API
- GitLab CI YMLs API
- Group and project access requests API
- Appearance API
- Applications API
- Audit Events API
- Avatar API
- Award Emoji API
- Project badges API
- Group badges API
- Branches API
- Broadcast Messages API
- Project clusters API
- Group clusters API
- Instance clusters API
- Commits API
- Container Registry API
- Custom Attributes API
- Dashboard annotations API
- Dependencies API
- Deploy Keys API
- Deployments API
- Discussions API
- Dockerfiles API
- Environments API
- Epics API
- Events
- Feature Flags API
- Feature flag user lists API
- Freeze Periods API
- Geo Nodes API
- Group Activity Analytics API
- Groups API
- Import API
- Issue Boards API
- Group Issue Boards API
- Issues API
- Epic Issues API
- Issues Statistics API
- Jobs API
- Keys API
- Labels API
- Group Labels API
- License
- Licenses API
- Issue links API
- Epic Links API
- Managed Licenses API
- Markdown API
- Group and project members API
- Merge request approvals API
- Merge requests API
- Project milestones API
- Group milestones API
- Namespaces API
- Notes API
- Notification settings API
- Packages API
- Pages domains API
- Pipeline schedules API
- Pipeline triggers API
- Pipelines API
- Project Aliases API
- Project import/export API
- Project repository storage moves API
- Project statistics API
- Project templates API
- Projects API
- Protected branches API
- Protected tags API
- Releases API
- Release links API
- Repositories API
- Repository files API
- Repository submodules API
- Resource label events API
- Resource milestone events API
- Resource weight events API
- Runners API
- SCIM API
- Search API
- Services API
- Application settings API
- Sidekiq Metrics API
- Snippets API
- Project snippets
- Application statistics API
- Suggest Changes API
- System hooks API
- Tags API
- Todos API
- Users API
- Project-level Variables API
- Group-level Variables API
- Version API
- Vulnerabilities API
- Vulnerability Findings API
- Wikis API
- GraphQL API
- Getting started with GitLab GraphQL API
- GraphQL API Resources
- API V3 to API V4
- Validate the .gitlab-ci.yml (API)
- User Docs
- Abuse reports
- User account
- Active sessions
- Deleting a User account
- Permissions
- Personal access tokens
- Profile preferences
- Threads
- GitLab and SSH keys
- GitLab integrations
- Git
- GitLab.com settings
- Infrastructure as code with Terraform and GitLab
- GitLab keyboard shortcuts
- GitLab Markdown
- AsciiDoc
- GitLab Notification Emails
- GitLab Quick Actions
- Autocomplete characters
- Reserved project and group names
- Search through GitLab
- Advanced Global Search
- Advanced Syntax Search
- Time Tracking
- GitLab To-Do List
- Administrator Docs
- Reference architectures
- Reference architecture: up to 1,000 users
- Reference architecture: up to 2,000 users
- Reference architecture: up to 3,000 users
- Reference architecture: up to 5,000 users
- Reference architecture: up to 10,000 users
- Reference architecture: up to 25,000 users
- Reference architecture: up to 50,000 users
- Troubleshooting a reference architecture set up
- Working with the bundled Consul service
- Configuring PostgreSQL for scaling
- Configuring GitLab application (Rails)
- Load Balancer for multi-node GitLab
- Configuring a Monitoring node for Scaling and High Availability
- NFS
- Working with the bundled PgBouncer service
- Configuring Redis for scaling
- Configuring Sidekiq
- Admin Area settings
- Continuous Integration and Deployment Admin settings
- Custom instance-level project templates
- Diff limits administration
- Enable and disable GitLab features deployed behind feature flags
- Geo nodes Admin Area
- GitLab Pages administration
- Health Check
- Job logs
- Labels administration
- Log system
- PlantUML & GitLab
- Repository checks
- Repository storage paths
- Repository storage types
- Account and limit settings
- Service templates
- System hooks
- Changing your time zone
- Uploads administration
- Abuse reports
- Activating and deactivating users
- Audit Events
- Blocking and unblocking users
- Broadcast Messages
- Elasticsearch integration
- Gitaly
- Gitaly Cluster
- Gitaly reference
- Monitoring GitLab
- Monitoring GitLab with Prometheus
- Performance Bar
- Usage statistics
- Object Storage
- Performing Operations in GitLab
- Cleaning up stale Redis sessions
- Fast lookup of authorized SSH keys in the database
- Filesystem Performance Benchmarking
- Moving repositories managed by GitLab
- Run multiple Sidekiq processes
- Sidekiq MemoryKiller
- Switching to Puma
- Understanding Unicorn and unicorn-worker-killer
- User lookup via OpenSSH's AuthorizedPrincipalsCommand
- GitLab Package Registry administration
- GitLab Container Registry administration
- Replication (Geo)
- Geo database replication
- Geo with external PostgreSQL instances
- Geo configuration
- Using a Geo Server
- Updating the Geo nodes
- Geo with Object storage
- Docker Registry for a secondary node
- Geo for multiple nodes
- Geo security review (Q&A)
- Location-aware Git remote URL with AWS Route53
- Tuning Geo
- Removing secondary Geo nodes
- Geo data types support
- Geo Frequently Asked Questions
- Geo Troubleshooting
- Geo validation tests
- Disaster Recovery (Geo)
- Disaster recovery for planned failover
- Bring a demoted primary node back online
- Automatic background verification
- Rake tasks
- Back up and restore GitLab
- Clean up
- Namespaces
- Maintenance Rake tasks
- Geo Rake Tasks
- GitHub import
- Import bare repositories
- Integrity check Rake task
- LDAP Rake tasks
- Listing repository directories
- Praefect Rake tasks
- Project import/export administration
- Repository storage Rake tasks
- Generate sample Prometheus data
- Uploads migrate Rake tasks
- Uploads sanitize Rake tasks
- User management
- Webhooks administration
- X.509 signatures
- Server hooks
- Static objects external storage
- Updating GitLab
- GitLab release and maintenance policy
- Security
- Password Storage
- Custom password length limits
- Restrict allowed SSH key technologies and minimum length
- Rate limits
- Webhooks and insecure internal web services
- Information exclusivity
- How to reset your root password
- How to unlock a locked user from the command line
- User File Uploads
- How we manage the TLS protocol CRIME vulnerability
- User email confirmation at sign-up
- Security of running jobs
- Proxying assets
- CI/CD Environment Variables
- Contributor and Development Docs
- Contribute to GitLab
- Community members & roles
- Implement design & UI elements
- Issues workflow
- Merge requests workflow
- Code Review Guidelines
- Style guides
- GitLab Architecture Overview
- CI/CD development documentation
- Database guides
- Database Review Guidelines
- Database Review Guidelines
- Migration Style Guide
- What requires downtime?
- Understanding EXPLAIN plans
- Rake tasks for developers
- Mass inserting Rails models
- GitLab Documentation guidelines
- Documentation Style Guide
- Documentation structure and template
- Documentation process
- Documentation site architecture
- Global navigation
- GitLab Docs monthly release process
- Telemetry Guide
- Usage Ping Guide
- Snowplow Guide
- Experiment Guide
- Feature flags in development of GitLab
- Feature flags process
- Developing with feature flags
- Feature flag controls
- Document features deployed behind feature flags
- Frontend Development Guidelines
- Accessibility & Readability
- Ajax
- Architecture
- Axios
- Design Patterns
- Frontend Development Process
- DropLab
- Emojis
- Filter
- Frontend FAQ
- GraphQL
- Icons and SVG Illustrations
- InputSetter
- Performance
- Principles
- Security
- Tooling
- Vuex
- Vue
- Geo (development)
- Geo self-service framework (alpha)
- Gitaly developers guide
- GitLab development style guides
- API style guide
- Go standards and style guidelines
- GraphQL API style guide
- Guidelines for shell commands in the GitLab codebase
- HTML style guide
- JavaScript style guide
- Migration Style Guide
- Newlines style guide
- Python Development Guidelines
- SCSS style guide
- Shell scripting standards and style guidelines
- Sidekiq debugging
- Sidekiq Style Guide
- SQL Query Guidelines
- Vue.js style guide
- Instrumenting Ruby code
- Testing standards and style guidelines
- Flaky tests
- Frontend testing standards and style guidelines
- GitLab tests in the Continuous Integration (CI) context
- Review Apps
- Smoke Tests
- Testing best practices
- Testing levels
- Testing Rails migrations at GitLab
- Testing Rake tasks
- End-to-end Testing
- Beginner's guide to writing end-to-end tests
- End-to-end testing Best Practices
- Dynamic Element Validation
- Flows in GitLab QA
- Page objects in GitLab QA
- Resource class in GitLab QA
- Style guide for writing end-to-end tests
- Testing with feature flags
- Translate GitLab to your language
- Internationalization for GitLab
- Translating GitLab
- Proofread Translations
- Merging translations from CrowdIn
- Value Stream Analytics development guide
- GitLab subscription
- Activate GitLab EE with a license