Greetings,

I'm writing to report an issue I stumbled upon while trying to adjust to
the new (for me) world of implicit-subject expectation writing.

Consider this rather silly test case:

describe "something" do
  context "in context" do
    subject { "an object" }
    it { should == "an object" }
  end
end

When I run rspec with `--format documentation`, I see the nifty
documentation generated by the matcher itself:

something
  in context
    should == "an object"

However, this is what I see when I run with `--format json` (modulo pretty
printing):

{
    "summary_line": "1 example, 0 failures",
    "summary": {
        "example_count": 1,
        "duration": 0.000344,
        "failure_count": 0,
        "pending_count":0
    },
    "examples": [
        {
            "status": "passed",
            "description": "should == \"an object\"",
            "full_description": "something in context ",
            "line_number": 4,
            "file_path": "./spec/test_spec.rb"
        }
    ]
}

Note that the full_description is missing the matcher documentation. And
with ci_reporter 1.8.4, this comes out as a sorry hash indeed, because
_only_ the full descriptions are reported to CI. Here's the trimmed XML
output.

SPEC-something.xml:
<testsuite errors="0" tests="0" failures="0" name="something" skipped="0"
time="0.000228">
  ...
</testsuite>

SPEC-something-in-context.xml:
<testsuite errors="0" tests="1" failures="0" name="something in context"
skipped="0" time="0.00102">
  <testcase name="something in context " time="0.000651" />
  ...
</testsuite>

Now imagine you had 15-20 test cases whose names were all "something in
context". Ugh.

What I want to see, of course, is the generated matcher documentation being
added to the end of the full description of the example, and showing up in
my CI reports.

----

I couldn't find a report of this issue already, but please stop here and
wave me off if you've already got a handle on this. Otherwise, here's my
analysis and suggested fix.

----

At first I was digging through ci_reporter to see if there was something
wrong on that end, but you can see that the built-in JSON reporter is
running into the same problem: full_description is simply missing important
stuff.

The problem as I see it starts from the fact that the generated description
from the matcher gets stored into metadata[:description] after the example
is run, but metadata[:full_description] never gets updated. This results in
the following metadata hash for our example:

{
    :caller => ...,
    :description => "should == \"an object\"",
    :description_args = [],
    :example_group => ...,
    :example_group_block => #<Proc: ...>,
    :execution_result => ...,
}

No :full_description entry in sight.

This means that, when someone calls `example.description` after the test is
run, they get the generated matcher description, because the implementation
of Example#description sees that `metadata[:description]` is set. But when
someone calls `example.full_description` or
`example.metadata[:full_description]`, both fall through to this
implementation, from the ExampleMetadata module:

def full_description
  build_description_from(self[:example_group][:full_description],
*self[:description_args])
end

Hmm... I see the parent's full description, the empty list of
description_args... but where's the example's description itself? We're not
taking into account that in this case the description didn't come from the
args at all, it came from the generated matcher. That, I believe, is the
root cause.

I think the best behavior is to respect the description args above all, but
_only if they're given_. Failing that, we should use the generated
description if it's available, and then we do I dunno what (stick with the
above, or go back to "example at ..."). Going with this behavior would fix
my issue.

So, my suggested fix is to have #full_description take
metadata[:description] into account:

def full_description
+  if self[:description]
+    build_description_from(self[:example_group][:full_description],
self[:description])
+  else
    build_description_from(self[:example_group][:full_description],
*self[:description_args])
+  end
end

It's not the cleanest patch, because it appears on the surface to be
undermining the behavior I described above, prioritizing whatever it finds
in self[:description], generated or otherwise, above
self[:description_args]. However, I think it works, and I'm not sure how
better to express it. If metadata[:description] is set, I think it could
contain either the contents of metadata[:description_args] or the generated
matcher description (any other possibilities?). And it looks to me from
Example#assign_generated_description that if metadata[:description] is
already filled out (from the description args), the previous contents will
win. So really, I think what you're going to see is: if we fall through to
the else, self[:description_args] is going to be empty. But I have yet to
prove that.

Questions notwithstanding, I've tried a monkey patch with this and it does
indeed fix my issue. I can work it into a full test case and submission if
you want, but as I'm new to the group I'll need some guidance.

Thanks for reviewing, and for a fun little test framework!

-- Owen
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to