# Usage with Cucumber

VCR can be used with cucumber in two basic ways:

* Use `VCR.use_cassette` in a step definition.
* Use a `VCR.cucumber_tags` block to tell VCR to use a cassette for a tagged scenario.

  In a cucumber support file (e.g. features/support/vcr.rb), put code like this:

  ```ruby
  VCR.cucumber_tags do |t|
  t.tag  '@tag1'
  t.tags '@tag2', '@tag3'

  t.tag  '@tag3', :cassette => :options
  t.tags '@tag4', '@tag5', :cassette => :options
  t.tag  '@vcr', :use_scenario_name => true
  end
  ```

  VCR will use a cassette named `cucumber_tags/<tag_name>` for scenarios with each of these tags (Unless the `:use_scenario_name` option is provided. See below). The configured `default_cassette_options` will be used, or you can override specific options by passing a hash as the last argument to `#tag` or `#tags`.

  You can also have VCR name your cassettes automatically according to the feature and scenario name by providing `:use_scenario_name => true` to `#tag` or `#tags`. In this case, the cassette will be named `<feature_name>/<scenario_name>`. For scenario outlines, VCR will record one cassette per row, and the cassettes will be named `<feature_name>/<scenario_name>/<row_name>`.

## Record HTTP interactions in a scenario by tagging it

*Given* a file named "lib/server.rb" with:

```
if ENV['WITH_SERVER'] == 'true'
  $server = start_sinatra_app do
    get('/:path') { "Hello #{params[:path]}" }
  end
end
```

*Given* a file named "features/support/vcr.rb" with:

```
require "lib/server"
require 'vcr'

VCR.configure do |c|
  c.hook_into :webmock
  c.cassette_library_dir     = 'features/cassettes'
  c.default_cassette_options = {
    :match_requests_on => [:method, :host, :path]
  }
end

VCR.cucumber_tags do |t|
  t.tag  '@localhost_request' # uses default record mode since no options are given
  t.tags '@disallowed_1', '@disallowed_2', :record => :none
  t.tag  '@vcr', :use_scenario_name => true
end
```

*And* a file named "features/step\_definitions/steps.rb" with:

```
require 'net/http'

When /^a request is made to "([^"]*)"$/ do |url|
  uri = URI.parse(url)
  uri.port = $server.port if $server
  @response = Net::HTTP.get_response(uri)
end

When /^(.*) within a cassette named "([^"]*)"$/ do |step_name, cassette_name|
  VCR.use_cassette(cassette_name) { step(step_name) }
end

Then /^the response should be "([^"]*)"$/ do |expected_response|
  expect(@response.body).to eq(expected_response)
end
```

*And* a file named "features/vcr\_example.feature" with:

```
Feature: VCR example

  Note: Cucumber treats the pre-amble as part of the feature name. When
  using the :use_scenario_name option, VCR will only use the first line
  of the feature name as the directory for the cassette.

  @localhost_request
  Scenario: tagged scenario
    When a request is made to "http://localhost:7777/localhost_request_1"
    Then the response should be "Hello localhost_request_1"
    When a request is made to "http://localhost:7777/nested_cassette" within a cassette named "nested_cassette"
    Then the response should be "Hello nested_cassette"
    When a request is made to "http://localhost:7777/localhost_request_2"
    Then the response should be "Hello localhost_request_2"

  @vcr
  Scenario: tagged scenario

  Note: Like the feature pre-amble, Cucumber treats the scenario pre-amble
  as part of the scenario name. When using the :use_scenario_name option,
  VCR will only use the first line of the feature name as the directory
  for the cassette.

    When a request is made to "http://localhost:7777/localhost_request_1"
    Then the response should be "Hello localhost_request_1"

  @vcr
  Scenario Outline: tagged scenario outline
    When a request is made to "http://localhost:7777/localhost_request_1"
    Then the response should be "Hello localhost_request_1"
    Examples:
      | key  | value |
      | foo  | bar   |

  @disallowed_1
  Scenario: tagged scenario
    When a request is made to "http://localhost:7777/allowed" within a cassette named "allowed"
    Then the response should be "Hello allowed"
    When a request is made to "http://localhost:7777/disallowed_1"

  @disallowed_2
  Scenario: tagged scenario
    When a request is made to "http://localhost:7777/disallowed_2"
```

*And* the directory "features/cassettes" does not exist

*When* I run `cucumber WITH_SERVER=true features/vcr_example.feature`

*Then* it should fail with "5 scenarios (2 failed, 3 passed)"

*And* the file "features/cassettes/cucumber\_tags/localhost\_request.yml" should contain "Hello localhost\_request\_1"

*And* the file "features/cassettes/cucumber\_tags/localhost\_request.yml" should contain "Hello localhost\_request\_2"

*And* the file "features/cassettes/nested\_cassette.yml" should contain "Hello nested\_cassette"

*And* the file "features/cassettes/allowed.yml" should contain "Hello allowed"

*And* the file "features/cassettes/VCR\_example/tagged\_scenario.yml" should contain "Hello localhost\_request\_1"

*And* the file "features/cassettes/VCR*example/tagged\_scenario\_outline/\_foo\_bar*.yml" should contain "Hello localhost\_request\_1"

*When* I run `cucumber features/vcr_example.feature`

*Then* it should fail with "5 scenarios (2 failed, 3 passed)"

*And* the output should contain each of the following:

\| An HTTP request has been made that VCR does not know how to handle: | | GET <http://localhost:7777/disallowed_1> | | An HTTP request has been made that VCR does not know how to handle: | | GET <http://localhost:7777/disallowed_2> |

*And* the file "features/cassettes/cucumber\_tags/localhost\_request.yml" should contain "Hello localhost\_request\_1"

*And* the file "features/cassettes/cucumber\_tags/localhost\_request.yml" should contain "Hello localhost\_request\_2"

*And* the file "features/cassettes/nested\_cassette.yml" should contain "Hello nested\_cassette"

*And* the file "features/cassettes/allowed.yml" should contain "Hello allowed"

*And* the file "features/cassettes/VCR\_example/tagged\_scenario.yml" should contain "Hello localhost\_request\_1"

*And* the file "features/cassettes/VCR*example/tagged\_scenario\_outline/\_foo\_bar*.yml" should contain "Hello localhost\_request\_1".

## `:allow_unused_http_interactions => false` does not raise if the scenario already failed

*Given* a previously recorded cassette file "features/cassettes/cucumber\_tags/example.yml" with:

```
--- 
http_interactions: 
- request: 
    method: get
    uri: http://example.com/foo
    body: 
      encoding: UTF-8
      string: ""
    headers: {}
  response: 
    status: 
      code: 200
      message: OK
    headers: 
      Content-Length: 
      - "5"
    body: 
      encoding: UTF-8
      string: Hello
    http_version: "1.1"
  recorded_at: Tue, 01 Nov 2011 04:58:44 GMT
recorded_with: VCR 2.0.0
```

*And* a file named "features/support/vcr.rb" with:

```
require 'vcr'

VCR.configure do |c|
  c.hook_into :webmock
  c.cassette_library_dir = 'features/cassettes'
end

VCR.cucumber_tags do |t|
  t.tag '@example', :allow_unused_http_interactions => false
end
```

*And* a file named "features/step\_definitions/steps.rb" with:

```
When /^the scenario fails$/ do
  raise "boom"
end
```

*And* a file named "features/vcr\_example.feature" with:

```
Feature:

  @example
  Scenario: tagged scenario
    When the scenario fails
```

*When* I run `cucumber features/vcr_example.feature`

*Then* it should fail with "1 scenario (1 failed)"

*And* the output should contain "boom"

*And* the output should not contain "There are unused HTTP interactions".


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nicolasiensen.gitbook.io/vcr-documentation/usage-with-cucumber.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
