ChatGPT解决这个技术问题 Extra ChatGPT

RSpec: describe, context, feature, scenario?

describe, context, feature, scenario: What is the difference(s) among the four and when do I use each one?


M
M.javid

The context is an alias for describe, so they are functionally equivalent. You can use them interchangeably, the only difference is how your spec file reads. There is no difference in test output for example. The RSpec book says:

"We tend to use describe() for things and context() for context".

Personally I like to use describe, but I can see why people prefer context.

feature and scenario are a part of Capybara, and not RSpec, and are meant to be used for acceptance tests. feature is equivalent to describe / context, and scenario equivalent to it / example.

If you're writing acceptance tests with Capybara, use the feature / scenario syntax, if not use describe / it syntax.


Sam is on point and here is a link with greater detail and excellent examples, specifically on the section for Capybara's built in DSL(Domain Specific Language): github.com/jnicklas/capybara#using-capybara-with-rspec
Seems rubocop will not accept it by default rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/…
C
Community

This morning, while writing some specs, I was having the same question. Usually, I mainly use describe and don't particularly think about this, but this morning I was dealing with lots of cases and different specs for one module, so it had to be easily understandable for the next developer that will read those specs. So I asked Google about this, and I found this: describe vs. context in rspec, whose answer I find quite interesting :

According to the rspec source code, “context” is just a alias method of “describe”, meaning that there is no functional difference between these two methods. However, there is a contextual difference that’ll help to make your tests more understandable by using both of them. The purpose of “describe” is to wrap a set of tests against one functionality while “context” is to wrap a set of tests against one functionality under the same state.

So, relying on this principle, you'd write a spec like this:

#
# The feature/behaviour I'm currently testing
#
describe "item ordering" do
  
  # 1st state of the feature/behaviour I'm testing
  context "without a order param" do
    ...
  end

  # 2nd state of the feature/behaviour I'm testing
  context "with a given order column" do
    ..
  end

  # Last state of the feature/behaviour I'm testing
  context "with a given order column + reverse" do
    ..
  end
end

Not sure if this is a generally accepted rule but I find this approach clear and quite easy to grasp.


This is a very good answer for describe/context. But you forgot the other half of the question about feature/scenario - however I think they can (and should) be used in exactly the same way you point out for describe/context.
Would be great if you expanded this with an explanation of feature/scenario!
G
GrayedFox

Expanding on Pierre's excellent answer, according to the docs:

The feature and scenario DSL correspond to describe and it, respectively. These methods are simply aliases that allow feature specs to read more as customer and acceptance tests.

So for those familiar with the Mocha terms describe and it (which are better suited to describing the behaviour of a test from a user's perspective, hence Mocha primarily functioning as a front end testing framework), you could:

choose to always and only use describe and it or another pairing

choose to use it inside of a context block that requires multiple assertions/tests to be made in a specific app state

Going with the second option, you can still follow the intention of "...wrap[ping] a set of tests against one functionality under the same state".

Thus your tests might look like this:

#
# The feature/behaviour I'm currently testing
#
describe "item ordering" do

  # 1st state of the feature/behaviour I'm testing
  context "without an order param" do
    # 1st and only test we want to run in this state
    it "asks the user for missing order param" do
     ...
    end
  end

  # 2nd state of the feature/behaviour I'm testing
  context "with an invalid order param" do
    # 1st test we want to run in this state
    it "validates and rejects order param" do
      ...
    end
    # 2nd test we want to run in this state
    it "returns an error to user" do
      ...
    end
  end

  # 3rd state of the feature/behaviour I'm testing with multiple tests
  context "with a valid order param" do
    it "validates and accepts order param" do
      ...
    end
    it "displays correct price for order" do
      ...
    end
    unless being_audited
      it "secretly charges higher price to user" do
        ...
      end
    end
  end
end

This way you skip the feature keyword entirely, which you might want to use for specific front end features or if you are doing FDD (feature driven development), which may feel uncomfortable for some. Ask your developer team for input here.

Caveat: don't always follow industry standards, imagine if we modelled all our tests after the Volkswagen philosophy?