title: RSpec custom matchers keep state between specs
body: <p>I've come across some counter intuitive behavior in RSpec (2.8.0) custom matchers functionality and I wonder whether it is a bug or feature or me being confused. Let's look at the code:</p>
  
  <pre class="lang-rb prettyprint-override"><code># matcher code
  RSpec::Matchers.define :exist do
    chain :with_start_time do |time|
      @start_time = time
    end
  
    chain :with_end_time do |time|
      @end_time = time
    end
  
    match do |subject|
      result = true
      result &amp;&amp;= subject.start_time == @start_time if @start_time
      result &amp;&amp;= subject.end_time == @end_time if @end_time
      result
    end
  
    failure_message_for_should do |subject|
      "Failure!\n".tap do |msg|
        if @start_time != subject.start_time
          msg &lt;&lt; "Expected start_time to be #@start_time but was #{subject.start_time}\n"
        end
        if @end_time != subject.end_time
          msg &lt;&lt; "Expected end_time to be #@end_time but was #{subject.end_time}\n"
        end
      end
    end
  end
  
  #spec code
  require 'ostruct'
  
  describe 'RSpec custom matcher keeping state between tests' do
    let(:time) { Time.now }
  
    it 'passes the first spec' do
      o = OpenStruct.new(start_time: time)
      o.should exist.with_start_time(time)
    end
  
    it 'fails the second because matcher kept @start_time from the first test' do
      o = OpenStruct.new(end_time: time)
      o.should exist.with_end_time(time)
    end
  end
  </code></pre>
  
  <p>This fails (demonstrating the issue):</p>
  
  <pre><code>avetia01:~/projects/custom_matcher_bug% rspec test_spec.rb             
  .F
  
  Failures:
  
    1) RSpec custom matcher keeping state between tests fails the second because matcher kept @start_time from the first test
       Failure/Error: o.should exist.with_end_time(time)
         Failure!
         Expected start_time to be 2012-02-27 12:20:25 +0000 but was 
       # ./test_spec.rb:41:in `block (2 levels) in &lt;top (required)&gt;'
  
  Finished in 0.00116 seconds
  
  2 examples, 1 failure
  </code></pre>
  
  <p><br>
  So the unexpected bit is that the same matcher instance seems to be used across multiple specs. Which, in this particular case leads, to <code>@start_time</code> being initialized with the value from the first spec, causing incorrect failure of the second spec.</p>