Skip to content

Commit

Permalink
Merge pull request #1025 from rspec/overriding-ordering-in-example-gr…
Browse files Browse the repository at this point in the history
…oups

Example groups can override the default ordering
  • Loading branch information
myronmarston committed Oct 1, 2013
2 parents ad3b428 + df880f0 commit 2ecfec8
Show file tree
Hide file tree
Showing 20 changed files with 663 additions and 350 deletions.
18 changes: 7 additions & 11 deletions features/command_line/order.feature
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
Feature: --order (new in rspec-core-2.8)

Use the `--order` option to tell RSpec how to order the files, groups, and
examples. Options are `default` and `rand`:
examples. Options are `defined` and `rand`:

Default is:
`defined` is the default, which executes groups and examples in the
order they are defined as the spec files are loaded.

* files are ordered based on the underlying file system's order (typically
case-sensitive alpha on *nix OS's and case-insenstive alpha in Windows)
* groups/examples are loaded in the order in which they are declared

Use `rand` to randomize the order of files, groups within files, and
examples within groups.*
Use `rand` to randomize the order of groups and examples within groups.*

* Nested groups are always run from top-level to bottom-level in order to avoid
executing `before(:all)` and `after(:all)` hooks more than once, but the order
of groups at each level is randomized.

You can also specify a seed
You can also specify a seed:

<h3>Examples</h3>

--order default
--order defined
--order rand
--order rand:123
--seed 123 # same as --order rand:123

The `default` option is only necessary when you have `--order rand` stored in a
The `defined` option is only necessary when you have `--order rand` stored in a
config file (e.g. `.rspec`) and you want to override it from the command line.
4 changes: 2 additions & 2 deletions features/command_line/require_option.feature
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ Feature: --require option
super
end
def puts(message)
[@file, __getobj__].each { |out| out.puts message }
def puts(*args)
[@file, __getobj__].each { |out| out.puts(*args) }
end
def close
Expand Down
93 changes: 93 additions & 0 deletions features/configuration/overriding_global_ordering.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
Feature: Overriding global ordering

You can customize how RSpec orders examples and example groups.
For an individual group, you can control it by tagging it with
`:order` metadata:

* `:defined` runs the examples (and sub groups) in defined order.
* `:random` runs them in random order.

If you have more specialized needs, you can register your own ordering
using the `register_ordering` configuration option. If you register
an ordering as `:global`, it will be the global default, used by all
groups that do not have `:order` metadata (and by RSpec to order the
top-level groups).

Scenario: running a specific examples group in order
Given a file named "order_dependent_spec.rb" with:
"""ruby
describe "examples only pass when they are run in order", :order => :defined do
before(:all) { @list = [] }
it "passes when run first" do
@list << 1
expect(@list).to eq([1])
end
it "passes when run second" do
@list << 2
expect(@list).to eq([1, 2])
end
it "passes when run third" do
@list << 3
expect(@list).to eq([1, 2, 3])
end
end
"""

When I run `rspec order_dependent_spec.rb --order random:1`
Then the examples should all pass

Scenario: Registering a custom ordering
Given a file named "register_custom_ordering_spec.rb" with:
"""ruby
RSpec.configure do |rspec|
rspec.register_ordering(:reverse) do |items|
items.reverse
end
end
describe "A group that must run in reverse order", :order => :reverse do
before(:all) { @list = [] }
it "passes when run second" do
@list << 2
expect(@list).to eq([1, 2])
end
it "passes when run first" do
@list << 1
expect(@list).to eq([1])
end
end
"""
When I run `rspec register_custom_ordering_spec.rb`
Then the examples should all pass

Scenario: Using a custom global ordering
Given a file named "register_global_ordering_spec.rb" with:
"""ruby
RSpec.configure do |rspec|
rspec.register_ordering(:global) do |items|
items.reverse
end
end
describe "A group without :order metadata" do
before(:all) { @list = [] }
it "passes when run second" do
@list << 2
expect(@list).to eq([1, 2])
end
it "passes when run first" do
@list << 1
expect(@list).to eq([1])
end
end
"""
When I run `rspec register_global_ordering_spec.rb`
Then the examples should all pass

2 changes: 1 addition & 1 deletion lib/rspec/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
require_rspec['core/flat_map']
require_rspec['core/filter_manager']
require_rspec['core/dsl']
require_rspec['core/extensions/ordered']
require_rspec['core/deprecation']
require_rspec['core/reporter']

Expand All @@ -24,6 +23,7 @@
require_rspec['core/metadata']
require_rspec['core/pending']
require_rspec['core/formatters']
require_rspec['core/ordering']

require_rspec['core/world']
require_rspec['core/configuration']
Expand Down
4 changes: 2 additions & 2 deletions lib/rspec/core/command_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ def run(err, out)
@configuration.load_spec_files
@world.announce_filters

@configuration.reporter.report(@world.example_count, @configuration.randomize? ? @configuration.seed : nil) do |reporter|
@configuration.reporter.report(@world.example_count) do |reporter|
begin
@configuration.run_hook(:before, :suite)
@world.example_groups.ordered.map {|g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code
@world.ordered_example_groups.map {|g| g.run(reporter) }.all? ? 0 : @configuration.failure_exit_code
ensure
@configuration.run_hook(:after, :suite)
end
Expand Down
Loading

0 comments on commit 2ecfec8

Please sign in to comment.