Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Indicative docstrings #71

Closed
wants to merge 9 commits into from

8 participants

@rentalcustard

This makes generated docstrings come out in the indicative rather than reading e.g. 'should do X', so that we don't get specdoc that mixes and matches when using the indicative in explicit docstrings.

It introduces a new method, docstrings, on matchers which returns a hash for negative and positive docstrings, but it also tries to avoid putting too much burden on the authors of matchers by a) providing a default implementation for matchers defined via the dsl and b) falling back on 'should/should_not #{description}' when the docstrings method isn't present.

The tests and features pass, although I'm aware of some tests in rspec-core (e.g. http://relishapp.com/rspec/rspec-core/v/2-6-rc/dir/command-line/line-number-option) which will break (in easily fixable ways) as a result of applying these changes.

I'm aware that this is a pretty invasive change and I wouldn't be surprised to hear that it breaks something else as currently implemented, but I wanted to throw up a pull request/issue to solicit thoughts/discussion as much as anything else.

@dchelimsky
Owner

@mortice - nice! My instinct is the hash keys should be :should and :should_not instead of :positive and :negative (aligns with method names). WDYT?

@rentalcustard

@dchelimsky I'm not sure - it feels a bit jarring to me to have strings which explicitly avoid 'should/should not' as the values for keys with those names. I don't really have strong feelings about it though...

@dchelimsky
Owner

I'll buy that. I'm trying to get the 2.6.0 release out this week and this is a big enough change that I don't want to rush it into this release (especially since there's already been 3 release candidates). I'm definitely planning to add it to 2.7, though. Thanks!

@rentalcustard

Great! Feel free to @ me if/when it breaks stuff on application :)

@myronmarston

Great work! This is a really nice change.

The API of having a method return a hash w/ two entries seems a bit strange to me--I can't think of any other ruby API I've worked with that has used that. What would you think about changing it to something like this?

def docstring_for_should
  "is empty"
end

def docstring_for_should_not
  "is not empty"
end

This aligns nicely w/ the rest of the matcher API, I think. It does include should and should_not in the names, which you mentioned wanting to avoid, but to me it reads differently here--it doesn't imply it should have "should" in the strings, it just is explicitly defining the doc string for should or should_not.

I also wonder if some people still prefer the it "should do something" docstring style. I don't, but for those that do, they might not like this change. A config option could potentially help here, but I'm not sure I'm in favor of that, either. I'm not sure what the right answer is.

@dchelimsky
Owner

I'm definitely in favor of a config option, defaulting to the old format for now - then default to the new format in 3.0.

@rentalcustard

Thanks for the feedback Myron.

The hash return is definitely odd, come to think of it. My initial thought was to try and bring the description into the hash as well, trying to avoid adding lots of methods onto matchers. But on second thoughts, it makes little difference whether we add 1 or 2 new methods, and I like your suggested names in this context too.

I was wondering about a config option myself. I'll hack something together there - presumably that means an addition to RSpec core which would end up being upstream of this? Or is there a way of avoiding that dependency?

@rentalcustard

See above for part 1. I've tried to add the option via the add_setting method, doing this in a file which gets required on rspec-expectations load:

RSpec.configure do |config|
  config.add_setting :indicative_docstrings, :default => false
end

But when I try to override this setting for a cucumber scenario to demonstrate it, i.e. by including this at the top of a 'Given a file named 'X.rb' with:

RSpec.configure do |config|
  config.indicative_docstrings = true
end

I get "undefined method `indicative_docstrings=' for #<RSpec:Configuration" when I run cucumber.

I must be doing something wrong here - any chance of some pointers?

@rentalcustard

As a side note, I'm not sure about indicative_docstrings as the name for the config value... any suggestions?

@dchelimsky
Owner

How about

config.generated_docstring_format = :suggestive # default
config.generated_docstring_format = :indicative
@justinko

Great work! This is a really nice change.

What @myronmarston said.

@rentalcustard

Added config option with above. I went with modal vs indicative because 'suggestive' has... erm... other implications in my mind. :)

@rentalcustard

Sorry for the obnoxious force push there, my mistake.

@rentalcustard

I hate to be a pain, but I'd love to see this merged and there hasn't been much activity here. Anything I can do to help it on its way?

@dchelimsky
Owner

I'm planning to merge it, but it won't be released until 2.7, which is probably a month out. It's a big patch and I'll need time to review it, etc, and I'm at RailsConf this week. Feel free to ping again if you don't see any activity in a couple of weeks.

@rentalcustard

Thanks David. I assumed that was the case but just wanted to make sure you didn't think anything major was missing. :)

@Mange

What's up with this one? I was surprised it wasn't part of 2.7.

@dchelimsky
Owner

Just lost track of it with other priorities. Getting ready to drop 2.8 in the next few days and my focus is on documentation, so this definitely won't be part of that, but I'll try to get it in after that.

@dchelimsky
Owner

Another problem I just realized is that github won't let me assign a milestone to this pull request as it does for issues :( Weak!

@dchelimsky
Owner

It's listed under the 2.9 milestone

@Mange

Great. Cheers!

@soulcutter
Collaborator

This is awesome! Thanks, @mortice

@dchelimsky
Owner

I'm going to go ahead and take care of merging, given that it sat around so long. Belated thanks for all the work, @mortice.

@rentalcustard

It was a pleasure, although I'd completely forgotten about it! Thanks for taking on the (presumably very hairy by this stage) merge, @dchelimsky.

@dchelimsky dchelimsky referenced this pull request from a commit
@rentalcustard rentalcustard indicative docstrings
This was a pull request (#71) from Tom Stuart that I didn't merge until several
months later, so I had to address some merge conflicts. In addition, the
original intent was to offer the end user a configuration option for the
"voice" of the message (e.g. "should be x" vs "is x"), but I made it check if
the matcher responds to new methods docstring_for_should or
docstring_for_should_not and use those. This way all the internal matchers do
the right thing, but external matchers will still work without rspec trying to
convert the mode of it's docstring.
2f0d105
@dchelimsky
Owner

@mortice very hairy, indeed! I ended up basically copying line by line from the diff here. I put you in as the author, although I made some changes. I pushed it to a separate branch because I'd like your approval to merge it to master since it has your name but there are some differences in approach.

@rentalcustard

I'm sorry I'm so behind in taking a look at this. I've had a look at 2f0d105 and am happy to have my name put to it as co-author or whatever makes most sense to you. Essentially, you could throw out all my code, rewrite and just credit me in the changelog with the original idea/implementation and I'd be happy; this is your project!

Let me know if there's anything I can do to help, though. I've just finished emigrating so I finally have some spare time to work on things.

@JonRowe
Owner

Did this eventually get merged elsewhere? Is it safe to close this issue or is it still awaiting work?

@myronmarston
Owner

@JonRowe, sadly, no this hasn't been merged. @dchelimsky rebased it and got it ready to merge in 2f0d105, but I had some concerns around introducing new parts of the matcher protocol that use the word should when we're moving away from that syntactically. (See my comment at 2f0d105#commitcomment-1856301)

As part of rspec 3, I plan to cleanup the matcher protocol w.r.t. should, and I think we should hold off on this until that shakes down.

@JonRowe
Owner

It occurs to me that it's shame there's no way to "snooze" or "pend" issues until a milestone (hint hint @github) but obviously this is best left to your discretion about the direction of the framework in general.

Off topic but personally I'm a fan of the should syntax and I'd be sad panda if it went away completely. Also what's the equivalent in the new expect syntax of its(:value) { should be_something } ?

@myronmarston
Owner

Off topic but personally I'm a fan of the should syntax and I'd be sad panda if it went away completely.

We have no plans to ever remove it completely. My plan is to disable it by default in a future release (likely RSpec 3.0, but that's open to discussion), but even then, it'll be one configuration line away from being available.

Also what's the equivalent in the new expect syntax of its(:value) { should be_something } ?

Rather than restate myself, I'll just point you to http://stackoverflow.com/questions/12260534/using-implicit-subject-with-expect-in-rspec-2-11/12266147#12266147 where I answered this :).

@samphippen
Collaborator

@mortice I'd be entirely up for remote pairing with you on this one if you want to carry it across the finish line for RSpec 3.0

@myronmarston
Owner

@samphippen -- IMO, this is gated on #270. @dchelimsky got this one rebased and ready to merge in 2f0d105 awhile ago but the sticking point was that we didn't want to add new methods to the API that use should in the name, given the direction RSpec has been going, and we couldn't come up with names we were happy with. While it's frustrating to let a PR linger, IMO it's best to hold off while we're unsure about naming new methods that are part of a protocol: once we add to it, it's very, very hard to change given the dependency that users now have on it.

All that said, since this PR was opened I've started to wonder/doubt it it's worth expanding the matcher protocol and adding additional infrastructure simply to change the grammatical "voice" of the generated doc strings. It seems very heavy weight for something that is, IMO, a minor feature of RSpec. I'm not sure if the tradeoff of the added infrastructure is worth adding for this feature. (Note: I'm not saying that I think it's not wroth adding this feature; I'm saying I'm on the fence.) Some RSpec users have rightly complained about how heavyweight RSpec is and this is the kind of stuff that contributes to that heavyweightness.

A couple alternate ideas:

  • We could just change the voice of the existing generated docstrings to the should-less form, w/o providing the config option infrastructure.
  • Users already configure the should vs expect syntax; could that be used to infer which doc string syntax they want to use?
@samphippen
Collaborator

After a quick chat on irc with @mortice I'm gonna close this:

[15:55:14] <mortice>     samphippen: i received the latest email about that PR while lying in bed in dubrovnik. Accordingly, I instantly forgot about it
[15:55:23] <samphippen>  I mean
[15:55:24] <samphippen>  wat
[15:56:17] <mortice>     i don't even care about it, no one bothers with -fdoc or doing anything useful with it anyway
[15:56:28] <mortice>     i just felt like hacking it together 2 years ago
[15:56:46] <samphippen>  ok
[15:56:52] <samphippen>  do you want to just close it out or  something?
[15:57:51] <mortice>     i don't care
[15:58:11] <mortice>     i like my PRs like I like my code: abandoned by me as soon as released
[15:58:15] <samphippen>  ok
[15:58:16] <mortice>     do what you like with it :)
[15:58:22] <samphippen>  I'll close it with a copy of this irc chat then
[15:58:56] <mortice>     seems legit
@samphippen samphippen closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 13, 2011
  1. @rentalcustard
  2. @rentalcustard
  3. @rentalcustard

    Add to documentation

    rentalcustard authored
  4. @rentalcustard
  5. @rentalcustard
  6. @rentalcustard
  7. @rentalcustard
  8. @rentalcustard
Commits on May 17, 2011
  1. @rentalcustard

    Refactoring docstring methods

    rentalcustard authored
      - extract modal docstring method
      - rename docstring -> indicative_docstring
      - remove unnecessary nil
This page is out of date. Refresh to see the latest.
View
25 features/custom_matchers/define_matcher.feature
@@ -8,6 +8,7 @@ Feature: define matcher
Given a file named "matcher_with_default_message_spec.rb" with:
"""
require 'rspec/expectations'
+ RSpec.configuration.generated_docstring_format = :indicative
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
@@ -37,8 +38,8 @@ Feature: define matcher
When I run `rspec ./matcher_with_default_message_spec.rb --format documentation`
Then the exit status should not be 0
- And the output should contain "should be a multiple of 3"
- And the output should contain "should not be a multiple of 4"
+ And the output should contain "is a multiple of 3"
+ And the output should contain "is not a multiple of 4"
And the output should contain "Failure/Error: it {should be_a_multiple_of(4)}"
And the output should contain "Failure/Error: it {should_not be_a_multiple_of(3)}"
@@ -94,17 +95,21 @@ Feature: define matcher
And the stdout should contain "1 example, 1 failure"
And the stdout should contain "expected that 9 would not be a multiple of 3"
- Scenario: overriding the description
+ Scenario: overriding the docstrings
Given a file named "matcher_overriding_description_spec.rb" with:
"""
require 'rspec/expectations'
+ RSpec.configuration.generated_docstring_format = :indicative
RSpec::Matchers.define :be_a_multiple_of do |expected|
match do |actual|
actual % expected == 0
end
- description do
- "be multiple of #{expected}"
+ docstring_for_should do
+ "is multiple of #{expected}"
+ end
+ docstring_for_should_not do
+ "is not multiple of #{expected}"
end
end
@@ -119,13 +124,14 @@ Feature: define matcher
When I run `rspec ./matcher_overriding_description_spec.rb --format documentation`
Then the exit status should be 0
And the stdout should contain "2 examples, 0 failures"
- And the stdout should contain "should be multiple of 3"
- And the stdout should contain "should not be multiple of 4"
+ And the stdout should contain "is multiple of 3"
+ And the stdout should contain "is not multiple of 4"
Scenario: with no args
Given a file named "matcher_with_no_args_spec.rb" with:
"""
require 'rspec/expectations'
+ RSpec.configuration.generated_docstring_format = :indicative
RSpec::Matchers.define :have_7_fingers do
match do |thing|
@@ -144,12 +150,13 @@ Feature: define matcher
When I run `rspec ./matcher_with_no_args_spec.rb --format documentation`
Then the exit status should be 0
And the stdout should contain "1 example, 0 failures"
- And the stdout should contain "should have 7 fingers"
+ And the stdout should contain "has 7 fingers"
Scenario: with multiple args
Given a file named "matcher_with_multiple_args_spec.rb" with:
"""
require 'rspec/expectations'
+ RSpec.configuration.generated_docstring_format = :indicative
RSpec::Matchers.define :be_the_sum_of do |a,b,c,d|
match do |sum|
@@ -164,7 +171,7 @@ Feature: define matcher
When I run `rspec ./matcher_with_multiple_args_spec.rb --format documentation`
Then the exit status should be 0
And the stdout should contain "1 example, 0 failures"
- And the stdout should contain "should be the sum of 1, 2, 3, and 4"
+ And the stdout should contain "is the sum of 1, 2, 3, and 4"
Scenario: with helper methods
Given a file named "matcher_with_internal_helper_spec.rb" with:
View
6 features/custom_matchers/define_matcher_with_fluent_interface.feature
@@ -5,6 +5,10 @@ Feature: define matcher with fluent interface
Scenario: chained method with argumetn
Given a file named "between_spec.rb" with:
"""
+ require 'rspec/expectations'
+
+ RSpec.configuration.generated_docstring_format = :indicative
+
RSpec::Matchers.define :be_bigger_than do |first|
match do |actual|
(actual > first) && (actual < @second)
@@ -21,4 +25,4 @@ Feature: define matcher with fluent interface
"""
When I run `rspec between_spec.rb --format documentation`
Then the output should contain "1 example, 0 failures"
- And the output should contain "should be bigger than 4"
+ And the output should contain "is bigger than 4"
View
29 features/implicit_docstrings.feature
@@ -50,3 +50,32 @@ Feature: implicit docstrings
And the output should contain "should be > 5"
And the output should contain "should include 4"
And the output should contain "should not respond to #size"
+
+ Scenario: run failing examples (indicative docstrings enabled)
+ Given a file named "failing_implicit_docstrings_spec.rb" with:
+ """
+ require 'rspec/expectations'
+ RSpec.configuration.generated_docstring_format = :indicative
+
+ describe "Failing examples with no descriptions" do
+
+ # description is auto-generated as "should equal(5)" based on the last #should
+ it do
+ 3.should equal(2)
+ 5.should equal(5)
+ end
+
+ it { 3.should be > 5 }
+
+ it { [1,2,3].should include(4) }
+
+ it { [1,2,3].should_not respond_to(:size) }
+
+ end
+ """
+
+ When I run `rspec ./failing_implicit_docstrings_spec.rb -fdoc`
+ Then the output should contain "equals 2"
+ And the output should contain "is > 5"
+ And the output should contain "includes 4"
+ And the output should contain "does not respond to #size"
View
2  lib/rspec/expectations.rb
@@ -1,3 +1,4 @@
+require 'rspec/core'
require 'rspec/expectations/extensions'
require 'rspec/matchers'
require 'rspec/expectations/fail_with'
@@ -35,5 +36,6 @@ module RSpec
# RSpec ships with a standard set of useful matchers, and writing your own
# matchers is quite simple. See RSpec::Matchers for details.
module Expectations
+ RSpec.configuration.add_setting :generated_docstring_format, :default => :modal
end
end
View
6 lib/rspec/matchers.rb
@@ -94,6 +94,12 @@ module RSpec
# description do
# # generate and return the appropriate string.
# end
+ # docstring_for_should do
+ # # generate and return the appropriate string.
+ # end
+ # docstring_for_should_not do
+ # # generate and return the appropriate string.
+ # end
# end
#
# Each of the message-generation methods has access to the block arguments
View
24 lib/rspec/matchers/be.rb
@@ -53,6 +53,14 @@ def description
"be"
end
+ def docstring_for_should
+ "is"
+ end
+
+ def docstring_for_should_not
+ "is not"
+ end
+
[:==, :<, :<=, :>=, :>, :===].each do |operator|
define_method operator do |operand|
BeComparedTo.new(operand, operator)
@@ -114,6 +122,14 @@ def description
"be #{@operator} #{expected_to_sentence}#{args_to_sentence}"
end
+ def docstring_for_should
+ "is #{@operator} #{expected_to_sentence}#{args_to_sentence}"
+ end
+
+ def docstring_for_should_not
+ "is not #{@operator} #{expected_to_sentence}#{args_to_sentence}"
+ end
+
end
class BePredicate < Be
@@ -151,6 +167,14 @@ def description
"#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
end
+ def docstring_for_should
+ "is #{expected_to_sentence}#{args_to_sentence}"
+ end
+
+ def docstring_for_should_not
+ "is not #{expected_to_sentence}#{args_to_sentence}"
+ end
+
private
def predicate
View
4 lib/rspec/matchers/eq.rb
@@ -43,6 +43,10 @@ def eq(expected)
description do
"== #{_expected_}"
end
+
+ docstring_for_should do
+ "== #{_expected_}"
+ end
end
end
end
View
8 lib/rspec/matchers/equal.rb
@@ -47,6 +47,14 @@ def inspect_object(o)
MESSAGE
end
+
+ docstring_for_should do
+ "equals #{_expected_.inspect}"
+ end
+
+ docstring_for_should_not do
+ "does not equal #{_expected_.inspect}"
+ end
end
end
end
View
26 lib/rspec/matchers/generated_descriptions.rb
@@ -11,13 +11,22 @@ def self.clear_generated_description
def self.generated_description
return nil if last_should.nil?
- "#{last_should.to_s.gsub('_',' ')} #{last_description}"
+ negative = last_should.to_s =~ /not/
+ last_description(negative)
end
private
-
- def self.last_description
- last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
+
+ def self.indicative_docstring(negative=false)
+ if negative && last_matcher.respond_to?(:docstring_for_should_not)
+ last_matcher.docstring_for_should_not
+ elsif last_matcher.respond_to?(:docstring_for_should)
+ last_matcher.docstring_for_should
+ end
+ end
+
+ def self.modal_docstring
+ last_matcher.respond_to?(:description) ? "#{last_should.to_s.sub("_", " ")} #{last_matcher.description}" : <<-MESSAGE
When you call a matcher in an example without a String, like this:
specify { object.should matcher }
@@ -31,6 +40,13 @@ def self.last_description
description method. Then you won't have to suffer this lengthy warning again.
MESSAGE
end
+
+ def self.last_description(negative=false)
+ if RSpec.configuration.generated_docstring_format == :indicative
+ self.indicative_docstring(negative)
+ else
+ self.modal_docstring
+ end
+ end
end
end
-
View
8 lib/rspec/matchers/has.rb
@@ -21,6 +21,14 @@ def description
[method_description(@expected), args_description(@args)].compact.join(' ')
end
+ def docstring_for_should
+ description.sub(/have/, "has")
+ end
+
+ def docstring_for_should_not
+ "not #{description}"
+ end
+
private
def predicate(sym)
"#{sym.to_s.sub("have_","has_")}?".to_sym
View
8 lib/rspec/matchers/have.rb
@@ -66,6 +66,14 @@ def failure_message_for_should_not
def description
"have #{relative_expectation} #{@collection_name}"
end
+
+ def docstring_for_should
+ "has #{relative_expectation} #{@collection_name}"
+ end
+
+ def docstring_for_should_not
+ "does not have #{relative_expectation} #{@collection_name}"
+ end
def respond_to?(sym)
@expected.respond_to?(sym) || super
View
4 lib/rspec/matchers/match_array.rb
@@ -31,6 +31,10 @@ def description
"contain exactly #{_pretty_print(@expected)}"
end
+ def docstring_for_should
+ "contains exactly #{_pretty_print(@expected)}"
+ end
+
private
def safe_sort(array)
View
21 lib/rspec/matchers/matcher.rb
@@ -15,6 +15,8 @@ def initialize(name, *expected, &declarations)
@match_for_should_not_block = nil
@messages = {
+ :docstring_for_should => lambda { "#{name_to_indicative_sentence}#{expected_to_sentence}" },
+ :docstring_for_should_not => lambda { "#{name_to_indicative_sentence(true)}#{expected_to_sentence}" },
:description => lambda {"#{name_to_sentence}#{expected_to_sentence}"},
:failure_message_for_should => lambda {|actual| "expected #{actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"},
:failure_message_for_should_not => lambda {|actual| "expected #{actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"}
@@ -91,6 +93,16 @@ def description(&block)
cache_or_call_cached(:description, &block)
end
+ # See RSpec::Matchers
+ def docstring_for_should(&block)
+ cache_or_call_cached(:docstring_for_should, &block)
+ end
+
+ # See RSpec::Matchers
+ def docstring_for_should_not(&block)
+ cache_or_call_cached(:docstring_for_should_not, &block)
+ end
+
#Used internally by objects returns by +should+ and +should_not+.
def diffable?
@diffable
@@ -151,6 +163,15 @@ def name_to_sentence
split_words(@name)
end
+ def name_to_indicative_sentence(negated=false)
+ if negated
+ indicative = to_indicative(name_to_sentence)
+ indicative =~ /is\s/ ? indicative.sub("is", "is not") : "does not #{name_to_sentence}"
+ else
+ to_indicative(name_to_sentence)
+ end
+ end
+
def expected_to_sentence
to_sentence(@expected)
end
View
8 lib/rspec/matchers/operator_matcher.rb
@@ -51,6 +51,14 @@ def fail_with_message(message)
def description
"#{@operator} #{@expected.inspect}"
end
+
+ def docstring_for_should
+ description
+ end
+
+ def docstring_for_should_not
+ "does not #{description}"
+ end
private
View
15 lib/rspec/matchers/pretty.rb
@@ -19,6 +19,19 @@ def to_sentence(words)
end
end
+ def to_indicative(infinitive)
+ changed = false
+ { /be/ => "is",
+ /have/ => "has",
+ /match/ => "matches"}.each_pair do |pattern, substitution|
+ if infinitive =~ pattern
+ infinitive.sub!(pattern, substitution)
+ changed = true
+ end
+ end
+ changed ? infinitive : infinitive.to_s + 's'
+ end
+
def _pretty_print(array)
result = ""
array.each_with_index do |item, index|
@@ -34,4 +47,4 @@ def _pretty_print(array)
end
end
end
-end
+end
View
8 lib/rspec/matchers/raise_error.rb
@@ -67,6 +67,14 @@ def failure_message_for_should_not
def description
"raise #{expected_error}"
end
+
+ def docstring_for_should
+ "raises #{expected_error}"
+ end
+
+ def docstring_for_should_not
+ "does not raise #{expected_error}"
+ end
private
def expected_error
View
8 lib/rspec/matchers/respond_to.rb
@@ -27,6 +27,14 @@ def description
"respond to #{pp_names}#{with_arity}"
end
+ def docstring_for_should
+ "responds to #{pp_names}#{with_arity}"
+ end
+
+ def docstring_for_should_not
+ "does not respond to #{pp_names}#{with_arity}"
+ end
+
def with(n)
@expected_arity = n
self
View
8 lib/rspec/matchers/throw_symbol.rb
@@ -63,6 +63,14 @@ def failure_message_for_should_not
def description
"throw #{expected}"
end
+
+ def docstring_for_should
+ "throws #{expected}"
+ end
+
+ def docstring_for_should_not
+ "does not throw #{expected}"
+ end
private
View
317 spec/rspec/matchers/description_generation_spec.rb
@@ -1,155 +1,178 @@
require 'spec_helper'
-describe "Matchers should be able to generate their own descriptions" do
+describe "Matchers generate their own descriptions" do
after(:each) do
RSpec::Matchers.clear_generated_description
end
-
- it "should == expected" do
- "this".should == "this"
- RSpec::Matchers.generated_description.should == "should == \"this\""
- end
-
- it "should not == expected" do
- "this".should_not == "that"
- RSpec::Matchers.generated_description.should == "should not == \"that\""
- end
-
- it "should be empty (arbitrary predicate)" do
- [].should be_empty
- RSpec::Matchers.generated_description.should == "should be empty"
- end
-
- it "should not be empty (arbitrary predicate)" do
- [1].should_not be_empty
- RSpec::Matchers.generated_description.should == "should not be empty"
- end
-
- it "should be true" do
- true.should be_true
- RSpec::Matchers.generated_description.should == "should be true"
- end
-
- it "should be false" do
- false.should be_false
- RSpec::Matchers.generated_description.should == "should be false"
- end
-
- it "should be nil" do
- nil.should be_nil
- RSpec::Matchers.generated_description.should == "should be nil"
- end
-
- it "should be > n" do
- 5.should be > 3
- RSpec::Matchers.generated_description.should == "should be > 3"
- end
-
- it "should be predicate arg1, arg2 and arg3" do
- 5.0.should be_between(0,10)
- RSpec::Matchers.generated_description.should == "should be between 0 and 10"
- end
-
- it "should equal" do
- expected = "expected"
- expected.should equal(expected)
- RSpec::Matchers.generated_description.should == "should equal \"expected\""
- end
-
- it "should_not equal" do
- 5.should_not equal(37)
- RSpec::Matchers.generated_description.should == "should not equal 37"
- end
-
- it "should eql" do
- "string".should eql("string")
- RSpec::Matchers.generated_description.should == "should eql \"string\""
- end
-
- it "should not eql" do
- "a".should_not eql(:a)
- RSpec::Matchers.generated_description.should == "should not eql :a"
- end
-
- it "should have_key" do
- {:a => "a"}.should have_key(:a)
- RSpec::Matchers.generated_description.should == "should have key :a"
- end
-
- it "should have_some_method" do
- object = Object.new
- def object.has_eyes_closed?; true; end
-
- object.should have_eyes_closed
- RSpec::Matchers.generated_description.should == 'should have eyes closed'
- end
-
- it "should have_some_method(args*)" do
- object = Object.new
- def object.has_taste_for?(*args); true; end
-
- object.should have_taste_for("wine", "cheese")
- RSpec::Matchers.generated_description.should == 'should have taste for "wine", "cheese"'
- end
-
- it "should have n items" do
- team.should have(3).players
- RSpec::Matchers.generated_description.should == "should have 3 players"
- end
-
- it "should have at least n items" do
- team.should have_at_least(2).players
- RSpec::Matchers.generated_description.should == "should have at least 2 players"
- end
-
- it "should have at most n items" do
- team.should have_at_most(4).players
- RSpec::Matchers.generated_description.should == "should have at most 4 players"
- end
-
- it "should include" do
- [1,2,3].should include(3)
- RSpec::Matchers.generated_description.should == "should include 3"
- end
-
- it "array.should =~ [1,2,3]" do
- [1,2,3].should =~ [1,2,3]
- RSpec::Matchers.generated_description.should == "should contain exactly 1, 2 and 3"
- end
-
- it "should match" do
- "this string".should match(/this string/)
- RSpec::Matchers.generated_description.should == "should match /this string/"
- end
-
- it "should raise_error" do
- lambda { raise }.should raise_error
- RSpec::Matchers.generated_description.should == "should raise Exception"
- end
-
- it "should raise_error with type" do
- lambda { raise }.should raise_error(RuntimeError)
- RSpec::Matchers.generated_description.should == "should raise RuntimeError"
- end
-
- it "should raise_error with type and message" do
- lambda { raise "there was an error" }.should raise_error(RuntimeError, "there was an error")
- RSpec::Matchers.generated_description.should == "should raise RuntimeError with \"there was an error\""
- end
-
- it "should respond_to" do
- [].should respond_to(:insert)
- RSpec::Matchers.generated_description.should == "should respond to #insert"
- end
-
- it "should throw symbol" do
- lambda { throw :what_a_mess }.should throw_symbol
- RSpec::Matchers.generated_description.should == "should throw a Symbol"
- end
-
- it "should throw symbol (with named symbol)" do
- lambda { throw :what_a_mess }.should throw_symbol(:what_a_mess)
- RSpec::Matchers.generated_description.should == "should throw :what_a_mess"
+
+ context "when the generated description format is indicative" do
+ before { RSpec::configuration.generated_docstring_format = :indicative }
+
+ it "should == expected" do
+ "this".should == "this"
+ RSpec::Matchers.generated_description.should == "== \"this\""
+ end
+
+ it "should not == expected" do
+ "this".should_not == "that"
+ RSpec::Matchers.generated_description.should == "does not == \"that\""
+ end
+
+ it "should be empty (arbitrary predicate)" do
+ [].should be_empty
+ RSpec::Matchers.generated_description.should == "is empty"
+ end
+
+ it "should not be empty (arbitrary predicate)" do
+ [1].should_not be_empty
+ RSpec::Matchers.generated_description.should == "is not empty"
+ end
+
+ it "should be true" do
+ true.should be_true
+ RSpec::Matchers.generated_description.should == "is true"
+ end
+
+ it "should be false" do
+ false.should be_false
+ RSpec::Matchers.generated_description.should == "is false"
+ end
+
+ it "should be nil" do
+ nil.should be_nil
+ RSpec::Matchers.generated_description.should == "is nil"
+ end
+
+ it "should be > n" do
+ 5.should be > 3
+ RSpec::Matchers.generated_description.should == "is > 3"
+ end
+
+ it "should be predicate arg1, arg2 and arg3" do
+ 5.0.should be_between(0,10)
+ RSpec::Matchers.generated_description.should == "is between 0 and 10"
+ end
+
+ it "should not be predicate arg1, arg2 and arg3" do
+ 5.0.should_not be_between(0, 1)
+ RSpec::Matchers.generated_description.should == "is not between 0 and 1"
+ end
+
+ it "should equal" do
+ expected = "expected"
+ expected.should equal(expected)
+ RSpec::Matchers.generated_description.should == "equals \"expected\""
+ end
+
+ it "should_not equal" do
+ 5.should_not equal(37)
+ RSpec::Matchers.generated_description.should == "does not equal 37"
+ end
+
+ it "should eql" do
+ "string".should eql("string")
+ RSpec::Matchers.generated_description.should == "eqls \"string\""
+ end
+
+ it "should not eql" do
+ "a".should_not eql(:a)
+ RSpec::Matchers.generated_description.should == "does not eql :a"
+ end
+
+ it "should have_key" do
+ {:a => "a"}.should have_key(:a)
+ RSpec::Matchers.generated_description.should == "has key :a"
+ end
+
+ it "should have_some_method" do
+ object = Object.new
+ def object.has_eyes_closed?; true; end
+
+ object.should have_eyes_closed
+ RSpec::Matchers.generated_description.should == 'has eyes closed'
+ end
+
+ it "should have_some_method(args*)" do
+ object = Object.new
+ def object.has_taste_for?(*args); true; end
+
+ object.should have_taste_for("wine", "cheese")
+ RSpec::Matchers.generated_description.should == 'has taste for "wine", "cheese"'
+ end
+
+ it "should have n items" do
+ team.should have(3).players
+ RSpec::Matchers.generated_description.should == "has 3 players"
+ end
+
+ it "should have at least n items" do
+ team.should have_at_least(2).players
+ RSpec::Matchers.generated_description.should == "has at least 2 players"
+ end
+
+ it "should have at most n items" do
+ team.should have_at_most(4).players
+ RSpec::Matchers.generated_description.should == "has at most 4 players"
+ end
+
+ it "should include" do
+ [1,2,3].should include(3)
+ RSpec::Matchers.generated_description.should == "includes 3"
+ end
+
+ it "array.should =~ [1,2,3]" do
+ [1,2,3].should =~ [1,2,3]
+ RSpec::Matchers.generated_description.should == "contains exactly 1, 2 and 3"
+ end
+
+ it "should match" do
+ "this string".should match(/this string/)
+ RSpec::Matchers.generated_description.should == "matches /this string/"
+ end
+
+ it "should raise_error" do
+ lambda { raise }.should raise_error
+ RSpec::Matchers.generated_description.should == "raises Exception"
+ end
+
+ it "should raise_error with type" do
+ lambda { raise }.should raise_error(RuntimeError)
+ RSpec::Matchers.generated_description.should == "raises RuntimeError"
+ end
+
+ it "should raise_error with type and message" do
+ lambda { raise "there was an error" }.should raise_error(RuntimeError, "there was an error")
+ RSpec::Matchers.generated_description.should == "raises RuntimeError with \"there was an error\""
+ end
+
+ it "should not raise_error with type and message" do
+ lambda { "Innocuous" }.should_not raise_error(RuntimeError, "there was an error")
+ RSpec::Matchers.generated_description.should == "does not raise RuntimeError with \"there was an error\""
+ end
+
+ it "should respond_to" do
+ [].should respond_to(:insert)
+ RSpec::Matchers.generated_description.should == "responds to #insert"
+ end
+
+ it "should throw symbol" do
+ lambda { throw :what_a_mess }.should throw_symbol
+ RSpec::Matchers.generated_description.should == "throws a Symbol"
+ end
+
+ it "should throw symbol (with named symbol)" do
+ lambda { throw :what_a_mess }.should throw_symbol(:what_a_mess)
+ RSpec::Matchers.generated_description.should == "throws :what_a_mess"
+ end
+ end
+
+ context "when the generated docstring format is modal" do
+ before { RSpec.configuration.generated_docstring_format = :modal }
+
+ it "should == expected" do
+ 3.should == 3
+ RSpec::Matchers.generated_description.should == "should == 3"
+ end
end
def team
Something went wrong with that request. Please try again.