简体   繁体   中英

In rspec-rails, How can I create a custom ordering so that I can run the specs according to my own order?

I am new to RSpec and I want to create a custom order for running the specs, I want the most important specs to run first and then the less important one's and so on till least important specs. Rspec already has the default global ordering as :defined, but I want to override this and create my own custom ordering. I have read a documentation (" https://www.relishapp.com/rspec/rspec-core/docs/configuration/overriding-global-ordering ") on this but couldn't understand how to achieve it. It would be grateful if you guys can post some example code with explanation.

Here's my spec_helper.rb file:-

RSpec.configure do |config|
  #config.register_ordering :global do |examples|
  # model, other = examples.partition do |example|
  # example.metadata[:type] == :model
  # example.metadata[:type] == :controller
  # end
  #  model + other 
  # end
  config.register_ordering(:global) do |items|
    arr = [RSpec::ExampleGroups::User]
    items.sort_by &arr.method(:index)
  end

 =begin
  config.register_ordering(:global) do |items|
    items.sort_by do |group|
      case group.metadata[:type]
      when :feature then 3
      when :controller then 2
      when :model  then 1
      else 4
      end
    end
  end
 =end

config.expect_with :rspec do |expectations|
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end

config.mock_with :rspec do |mocks|
  mocks.verify_partial_doubles = true
end

And for example here's that spec file I want to execute first when the rspec is ran:- spec/models/user_spec_.rb

require 'rails_helper'
require  'spec_helper'

describe User do
  describe 'must fill in user name' do
    it { expect(User.new(:name => "")).not_to be_valid }
  end

  describe "must fill in email" do
    it { expect(User.new(:email => "")).not_to be_valid }
  end
  describe "when email address is already taken, do not allow duplication" do
    it "should not allow duplication" do
      @user = User.new(name: "Example User", email: "user12@example.com")
      # dup_user = @user.dup
      @user.save

      expect(@user.dup).not_to be_valid
    end
  end
end

The error I get when I try to use this type of configuration with an array is:-

        /spec/spec_helper.rb:29:in `sort_by': comparison of Fixnum with nil 
        failed (ArgumentError)
       from C:/RoR/rspec_demo/spec/spec_helper.rb:29:in `block (2 levels) in 
       <top (required)>'
       from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/lib/rspec/core/ordering.rb:151:in `block in register_ordering'
       from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/lib/rspec/core/ordering.rb:69:in `order'
       from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/lib/rspec/core/world.rb:34:in `ordered_example_groups'
       from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/lib/rspec/core/runner.rb:87:in `run'
       from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/lib/rspec/core/runner.rb:71:in `run'
       from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
       from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/exe/rspec:4:in `<top (required)>'
       from C:/Ruby23-x64/bin/rspec:22:in `load'
       from C:/Ruby23-x64/bin/rspec:22:in `<main>'

And If I use the following code for overriding:-

        config.register_ordering(:global) do |items|
        items = [RSpec::ExampleGroups::User]
        #items.sort_by &arr.method(:index)
        end

Then the spec file runs bet the test doesn't pass returning the following error:-

      1) User must fill in user name
      Failure/Error: super

       NoMethodError:
       undefined method `inspect_output' for 
       RSpec::ExampleGroups::User:Class
       # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
       3.5.4/lib/rspec/core/example_group.rb:732:in `method_missing'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/example_group.rb:625:in `block in run_examples'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/example_group.rb:623:in `map'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/example_group.rb:623:in `run_examples'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/example_group.rb:589:in `run'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:113:in `block (3 levels) in run_specs'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:113:in `map'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:113:in `block (2 levels) in run_specs'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/configuration.rb:1835:in `with_suite_hooks'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:112:in `block in run_specs'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/reporter.rb:77:in `report'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:111:in `run_specs'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:87:in `run'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:71:in `run'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
      # C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/rspec-core-
      3.5.4/exe/rspec:4:in `<top (required)>'
      # C:/Ruby23-x64/bin/rspec:22:in `load'
      # C:/Ruby23-x64/bin/rspec:22:in `<main>'
      #
      #   Showing full backtrace because every line was filtered out.
      #   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
      #   RSpec::Configuration#backtrace_inclusion_patterns for more 
          information.
       Failed examples:

        rspec ./spec/models/user_spec.rb:9 # User must fill in user name

I have also read this discussion(" https://github.com/rspec/rspec-core/issues/547 ") about custom ordering but couldn't understand how to implement it.

How can I achieve the following? Or even If I have to only execute a single example from this file first like "should not allow duplication" first when I run the RSpec. How can I make it possible?

To define a custom order, you just need to setup your own rules in configuration. As you want to specifically define important and non-important, you'll need to make your own list with the order you want and then sort the actual text list using it. Here is a crude working example that you put into spec/spec_helper.rb :

  config.register_ordering(:global) do |items|
    arr = [RSpec::ExampleGroups::ImportantText, RSpec::ExampleGroups::NotImportant]
    items.sort_by &arr.method(:index)
  end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM