skip to content

In RSpec 3.13, what does rspec --init create, and which settings in the generated spec_helper.rb are actually switched on?

level: juniorimportance: should knowfreq 45%

answer

  1. two files, one of them hidden
  2. --require spec_helper
  3. three active settings
  4. the =begin block is off
  5. existing files are left alone

basics

~10 s

rspec --init writes .rspec, holding --require spec_helper, and spec/spec_helper.rb. Only three settings in that file are active; random order, :focus filtering, failure persistence and profiling sit in a commented-out =begin block.

solid answer

~40 s

`rspec --init` copies two templates and skips any file that already exists (it prints `exist` instead of `create`). `.rspec` is an **options file** read on every run; its one line, `--require spec_helper`, loads the configuration so individual spec files need no `require`. In `spec/spec_helper.rb` only three settings are live in RSpec 3.13: `include_chain_clauses_in_custom_matcher_descriptions = true`, `verify_partial_doubles = true` and `shared_context_metadata_behavior = :apply_to_host_groups`. Everything else it suggests, including `filter_run_when_matching :focus`, `example_status_persistence_file_path`, `disable_monkey_patching!`, `warnings = true`, `profile_examples = 10`, `order = :random` and `Kernel.srand config.seed`, is wrapped in `=begin`/`=end`. So a freshly initialised project runs examples in **defined order** with no `--only-failures` support until you uncomment that block.

code

bash · 10 lines
bash
$ rspec --init
  create   .rspec
  create   spec/spec_helper.rb

$ cat .rspec
--require spec_helper

$ rspec --init
   exist   .rspec
   exist   spec/spec_helper.rb

go deeper

for a junior

Recall the two files rspec --init creates and that .rspec's --require spec_helper is why spec files skip the require line.

for a middle

Know which three settings are live, that random order, focus and failure persistence are commented out, and where .rspec-local and ~/.rspec fit in the option precedence.

for a senior

When a suite behaves unexpectedly, check which options files and SPEC_OPTS are in play and whether the suggested block was ever uncommented.

for a principal

Decide which suggested settings become the team baseline, such as random order and persistence, and keep personal options out of the committed .rspec.

## What the command writes `rspec --init` is rspec-core's project generator. In RSpec 3.13 it copies exactly two template files into the current directory: 1. **`.rspec`**, an options file; 2. **`spec/spec_helper.rb`**, a configuration file, creating `spec/` if needed. For each file it prints `create .rspec` when it writes it, or `exist .rspec` when a file of that name is already there. It never overwrites, so re-running it on an existing project is harmless and also changes nothing. ## The .rspec options file `.rspec` holds command-line options, one or more per line, that rspec applies to every run from that directory. The generated one contains a single line: ``` --require spec_helper ``` That is why spec files in a project set up this way do not start with `require "spec_helper"`: rspec loads it before any spec file. RSpec reads options from several places and merges them, later sources overriding earlier ones for most options: | Source | Scope | |---|---| | `$XDG_CONFIG_HOME/rspec/options` or `~/.rspec` | the user, all projects | | `./.rspec` | the project, committed | | `./.rspec-local` | the developer, usually git-ignored | | command-line arguments | this run | | `SPEC_OPTS` environment variable | this run, set by a wrapper or CI | `--options PATH` replaces the file sources with one custom file. Options files are passed through ERB, and since 3.13 they may contain comments. ## What is live in spec_helper.rb The generated `spec_helper.rb` has an active part and a suggested part. Only these three settings run: | Setting | Effect | |---|---| | `expectations.include_chain_clauses_in_custom_matcher_descriptions = true` | custom matcher descriptions include chained clauses | | `mocks.verify_partial_doubles = true` | stubs on real objects are checked against real methods | | `shared_context_metadata_behavior = :apply_to_host_groups` | metadata on a shared context applies to groups that include it | The comments on the last two note that each will become the default in RSpec 4. ## What is suggested but switched off Everything else sits between `=begin` and `=end`, Ruby's block-comment markers, so none of it runs until you delete them: - `config.filter_run_when_matching :focus`, which enables focusing with `fit` and friends; - `config.example_status_persistence_file_path = "spec/examples.txt"`, which `--only-failures` needs; - `config.disable_monkey_patching!`, which removes the old global `describe` and the `should` syntax; - `config.warnings = true`; - the documentation formatter when a single file is run; - `config.profile_examples = 10`, the slowest-examples report; - `config.order = :random` and `Kernel.srand config.seed`. ## What disable_monkey_patching! would change One suggested line deserves a note because it changes how specs must be written. `config.disable_monkey_patching!` is documented as equivalent to: - `expose_dsl_globally = false`, so a top-level `describe` stops working and specs must call `RSpec.describe`; - the `:expect` syntax only for rspec-mocks and rspec-expectations, which removes the legacy `should` and `stub` forms; - `patch_marshal_to_support_partial_doubles = false`. The generated template already writes `RSpec.describe` in its examples, so uncommenting it costs nothing on a new project, while an older suite that still uses bare `describe` or `should` breaks until those are rewritten. ## Consequences worth stating in an interview 1. A new project runs examples in **defined order**. Random ordering is a suggestion, not a default. 2. `--only-failures` aborts with `To use --only-failures, you must first set config.example_status_persistence_file_path` until the persistence line is uncommented. 3. `fit` only narrows a run once `filter_run_when_matching :focus` is active. 4. The template is a starting point: most teams uncomment the whole block, then add the persistence file to `.gitignore`, as the template's own comment recommends. ## Common misreadings - "`rspec --init` turns on random order": the line is commented out. - "Every spec must `require \"spec_helper\"`": `.rspec` already requires it. - "`--init` resets an existing `.rspec`": it reports `exist` and leaves it untouched.

  • A developer wants documentation-format output locally without changing it for the team. Where should the option go?
    In `./.rspec-local`, which rspec reads after the project's `.rspec` and which is normally git-ignored, or in the user-level `~/.rspec` (or `$XDG_CONFIG_HOME/rspec/options`) to apply to every project. Putting `--format documentation` in the committed `.rspec` would change every teammate's and CI's output.
  • Why does a fresh RSpec project reject rspec --only-failures?
    `--only-failures` reads each example's last status from the file named by `config.example_status_persistence_file_path`. The generated `spec_helper.rb` suggests `spec/examples.txt` but leaves the line inside the `=begin`/`=end` block, so the setting is unset and rspec aborts with a message telling you to set it.

saying these in an interview costs you the question

  • rspec --init turns on random order for new projects
  • rspec --init overwrites an existing .rspec with the defaults
  • every spec file must require spec_helper itself even with the generated .rspec
  • the =begin block in spec_helper.rb is active configuration
  • the committed .rspec is the place for one developer's personal options