In RSpec, how do you run examples in random order, and how do you replay the exact order of a failed run with --seed?
answer
- default order is defined
- config.order = :random or --order rand
- Randomized with seed ...
- --seed N means --order rand:N
- Kernel.srand config.seed for rand
basics
~20 sRSpec runs examples in defined order unless config.order = :random or --order rand is set. A random run ends by printing its seed, such as Randomized with seed 4821, and rspec --seed 4821 replays exactly that order.
solid answer
~40 sRandom ordering shuffles groups and examples so hidden dependencies between them surface. Turn it on with `config.order = :random` in `spec_helper.rb` or `--order rand` (alias `random`) on the command line or in `.rspec`. Each random run picks a seed and prints `Randomized with seed 4821` at the end. `rspec --seed 4821` is equivalent to `--order rand:4821` and reproduces the same order; a seed or order given on the command line or in `.rspec` wins over `config.order` in `spec_helper.rb`. The order is derived from the seed and each example's id, so rerunning a subset with the same seed keeps the survivors in the same relative order. RSpec never calls `srand` itself; add `Kernel.srand config.seed` so `rand`, `shuffle` and `sample` inside specs replay too.
code
bash · 9 lines$ rspec
...
Finished in 4.2 seconds
312 examples, 1 failure
Randomized with seed 4821
$ rspec --seed 4821 # same order, same failure
$ rspec --order defined # does it pass without shuffling?go deeper
Remember that RSpec's default is defined order, that config.order = :random turns shuffling on, and that the printed seed plus --seed replays a run.
Explain that --seed N equals --order rand:N, that command-line order wins over spec_helper, and why Kernel.srand config.seed is needed for random data.
Use the seed from a failing CI run, confirm it reproduces locally, and explain why a subset with the same seed keeps relative order, which enables bisecting.
Make random order the suite default so order coupling is found early, and make sure CI logs always surface the seed of a failed run.
## Defined order is the default Out of the box, rspec-core 3.13 runs example groups and examples in the order they are **defined**: files in load order, groups and examples top to bottom. That is predictable, and it is also how order dependencies hide: an example that only passes because an earlier one left a record in the database, a stubbed constant, or a memoised global behind will pass forever in defined order. ## Turning random order on Three equivalent switches exist: - `config.order = :random` in `spec_helper.rb` (suggested, commented out, in the template `rspec --init` writes); - `--order rand` or `--order random` on the command line; - the same `--order` line in `.rspec`. Other values are `defined`, `recently-modified` (most recently changed files first), and, since 3.13, the name of a custom strategy registered with `config.register_ordering`. When both are present, the command line and options files win: an `--order` or `--seed` option is forced, so a later `config.order =` in `spec_helper.rb` does not override it. ## Reading and replaying the seed Every random run chooses a seed (a random integer below 65,535 unless you give one) and prints it with the summary: ``` Randomized with seed 4821 ``` To replay that run: ``` rspec --seed 4821 ``` `--seed 4821` is documented as equivalent to `--order rand:4821`, so it also switches random ordering on even if the project normally runs in defined order. ## What gets shuffled, and what does not Random ordering is applied level by level, not across the whole suite at once: - top-level groups are ordered by the strategy; - inside a group, its own examples are ordered and run, then its nested groups, each ordered the same way; - examples from two different groups are never interleaved, so a `before(:context)` hook still runs once per group. A single group can opt out with metadata: `RSpec.describe Legacy::Importer, order: :defined do` keeps that group's examples in written order while the rest of the suite stays random. That is a documented escape hatch for code you cannot fix yet, not a fix; the dependency it hides is still there. ## How the shuffle is computed rspec-core does not use Ruby's global random generator for ordering. It sorts each list of groups or examples by a Jenkins hash of the seed concatenated with the item's id (such as `./spec/notifier_spec.rb[1:3]`). Two properties follow: 1. the same seed and the same set of examples always give the same order; 2. running a **subset** with the same seed keeps the surviving examples in the same relative order, which is what makes rerunning two ids, or `--bisect`, reproduce a failure. ## Seeding Ruby's own randomness RSpec deliberately never calls `srand`, so specs that use `rand`, `Array#shuffle` or `Array#sample` get fresh randomness each run. The template's suggestion ties that to the same seed: ```ruby RSpec.configure do |config| config.order = :random Kernel.srand config.seed end ``` With it, `--seed 4821` replays both the example order and the random data. ## Scenario: fails only in one order A suite passes on most runs and fails on a few, always with different seeds. The workflow: 1. copy the seed from the failing run's output, locally or from CI; 2. rerun with `rspec --seed <that seed>` and confirm the failure reproduces; 3. rerun the failing example alone with the same seed; if it passes, something that runs before it is leaking state; 4. hand the reproducing command to `--bisect` to find which example that is; 5. to prove the suite works when the leak is absent, run `rspec --order defined`. ## Common mistakes - Committing a fixed `config.seed = 1234`: every run then uses one order and the point of randomising is lost. - Expecting `--seed` to replay `rand` calls without `Kernel.srand config.seed`. - Reading the seed from a different run than the one that failed.
- Why does rspec --seed 4821 spec/notifier_spec.rb:42 spec/sms_spec.rb:10 still run those two examples in the order the full run used?rspec-core orders items by a hash of the seed plus each item's id, not by position in a shuffled list. Removing other examples does not change the survivors' hashes, so their relative order is identical. That is what lets you reproduce a failure with only the polluting example and the victim.
- A spec builds its data with Array#sample, and --seed 4821 does not reproduce a failure. What is missing?RSpec never seeds Ruby's global random generator, so `sample` draws different values each run even when the example order is replayed. Adding `Kernel.srand config.seed` in `spec_helper.rb`, as the generated template suggests, ties Ruby's `rand`, `shuffle` and `sample` to the same seed so both order and data replay.
The seed is like the shuffle number printed on a tournament draw: anyone who uses the same number gets the same pairings, and dropping a few players from the list leaves the others in the same relative order.
saying these in an interview costs you the question
- RSpec runs examples in random order by default
- --seed only takes effect if config.order = :random is also set
- RSpec seeds Kernel#rand from the ordering seed automatically
- running a subset with the same seed reshuffles the remaining examples
- config.order in spec_helper.rb overrides --order given on the command line