summaryrefslogtreecommitdiff
path: root/doc/development/testing_guide/best_practices.md
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-06-18 11:18:50 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-06-18 11:18:50 +0000
commit8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781 (patch)
treea77e7fe7a93de11213032ed4ab1f33a3db51b738 /doc/development/testing_guide/best_practices.md
parent00b35af3db1abfe813a778f643dad221aad51fca (diff)
downloadgitlab-ce-8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781.tar.gz
Add latest changes from gitlab-org/gitlab@13-1-stable-ee
Diffstat (limited to 'doc/development/testing_guide/best_practices.md')
-rw-r--r--doc/development/testing_guide/best_practices.md83
1 files changed, 72 insertions, 11 deletions
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index f0137e542cc..7bb8473117f 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -35,11 +35,18 @@ Here are some things to keep in mind regarding test performance:
To run RSpec tests:
```shell
-# run all tests
+# 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
-# run test for path
-bin/rspec spec/[path]/[to]/[spec].rb
```
Use [Guard](https://github.com/guard/guard) to continuously monitor for changes and only run matching tests:
@@ -59,7 +66,7 @@ FDOC=1 bin/rspec spec/[path]/[to]/[spec].rb
### General guidelines
-- Use a single, top-level `describe ClassName` block.
+- Use a single, top-level `RSpec.describe ClassName` block.
- Use `.method` to describe class methods and `#method` to describe instance
methods.
- Use `context` to test branching logic.
@@ -323,7 +330,7 @@ Feature.enabled?(:ci_live_trace) # => false
If you wish to set up a test where a feature flag is enabled only
for some actors and not others, you can specify this in options
passed to the helper. For example, to enable the `ci_live_trace`
-feature flag for a specifc project:
+feature flag for a specific project:
```ruby
project1, project2 = build_list(:project, 2)
@@ -340,7 +347,7 @@ This represents an actual behavior of FlipperGate:
1. You can enable an override for a specified actor to be enabled
1. You can disable (remove) an override for a specified actor,
- fallbacking to default state
+ falling back to default state
1. There's no way to model that you explicitly disable a specified actor
```ruby
@@ -357,6 +364,60 @@ Feature.enabled?(:my_feature2) # => false
Feature.enabled?(:my_feature2, project1) # => true
```
+#### `stub_feature_flags` vs `Feature.enable*`
+
+It is preferred to use `stub_feature_flags` for enabling feature flags
+in testing environment. This method provides a simple and well described
+interface for a simple use-cases.
+
+However, in some cases a more complex behaviors needs to be tested,
+like a feature flag percentage rollouts. This can be achieved using
+the `.enable_percentage_of_time` and `.enable_percentage_of_actors`
+
+```ruby
+# 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)
+```
+
+Each feature flag that has a defined state will be persisted
+for test execution time:
+
+```ruby
+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
+
+It is required that a gate that is passed as an argument to `Feature.enabled?`
+and `Feature.disabled?` is an object that includes `FeatureGate`.
+
+In specs you can use a `stub_feature_flag_gate` method that allows you to have
+quickly your custom gate:
+
+```ruby
+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
The code exercised by a single GitLab test may access and modify many items of
@@ -406,7 +467,7 @@ However, if a spec makes direct Redis calls, it should mark itself with the
#### Background jobs / Sidekiq
By default, Sidekiq jobs are enqueued into a jobs array and aren't processed.
-If a test enqueues Sidekiq jobs and need them to be processed, the
+If a test queues Sidekiq jobs and need them to be processed, the
`:sidekiq_inline` trait can be used.
The `:sidekiq_might_not_need_inline` trait was added when [Sidekiq inline mode was
@@ -662,7 +723,7 @@ module Spec
end
```
-Helpers should not change the RSpec config. For instance, the helpers module
+Helpers should not change the RSpec configuration. For instance, the helpers module
described above should not include:
```ruby
@@ -723,9 +784,9 @@ end
This will create a repository containing two files, with default permissions and
the specified content.
-### Config
+### Configuration
-RSpec config files are files that change the RSpec config (i.e.
+RSpec configuration files are files that change the RSpec configuration (i.e.
`RSpec.configure do |config|` blocks). They should be placed under
`spec/support/`.
@@ -744,7 +805,7 @@ RSpec.configure do |config|
end
```
-If a config file only consists of `config.include`, you can add these
+If a configuration file only consists of `config.include`, you can add these
`config.include` directly in `spec/spec_helper.rb`.
For very generic helpers, consider including them in the `spec/support/rspec.rb`