Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undefined method stub report #15

Closed
myronmarston opened this issue Sep 1, 2010 · 7 comments
Closed

Undefined method stub report #15

myronmarston opened this issue Sep 1, 2010 · 7 comments

Comments

@myronmarston
Copy link
Member

As discussed on the mailing list, I've started the work on adding an undefined method stub report in a branch. I've got things to the point where I've recorded all the various bits of info, and now we just need to add the code to print the report. Since there wasn't much feedback from others, I figured it'd be easiest to nail down the details here, but we can take the conversation back to the mailing list if you'd prefer.

For reference, here's the current documentation output for the UndefinedMethodDouble specs:

RSpec::Mocks::UndefinedMethodDouble
  when recording is disabled
    a stub of a previously undefined method
      is not recorded
    a mock of a previously undefined method
      is not recorded
  when recording is enabled
    a stub of a previously defined method
      is not recorded
    a stub of a previously undefined method
      is not recorded when the method is defined before the invocation
      when the method double is defined and invoked once
        records the stubed object
        records the stubed method
        records the invocation
        records the definition
        for a pure mock object
          is not recorded
        for a pure stub object
          is not recorded
        for a pure double object
          is not recorded
      when the method double is defined once and invoked twice
        records only a single stubed object
        records only a single stubed method
        records only a single definition
        records each invocation
      when the method double is defined twice and invoked once
        records only a single stubed object
        records only a single stubed method
        records each definition
        records only a single invocation
    a mock of a previously defined method
      is not recorded
    a mock of a previously undefined method
      is not recorded when the method is defined before the invocation
      when the method double is defined and invoked once
        records the mocked object
        records the mocked method
        records the invocation
        records the definition
        for a pure mock object
          is not recorded
        for a pure stub object
          is not recorded
        for a pure double object
          is not recorded
      when the method double is defined once and invoked twice
        records only a single mocked object
        records only a single mocked method
        records only a single definition
        records each invocation
      when the method double is defined twice and invoked once
        records only a single mocked object
        records only a single mocked method
        records each definition
        records only a single invocation

David, at this point, I could use some input from you.

  • I'd like to record the running example at the time that each undefined method double is invoked, but I couldn't find a way to access that. Is there something I'm missing?
  • I'm not sure of the best way to hook this in to the formatters. Do we care to provide this report for non-text formatters? I guess maybe the html formatter could just wrap it in a big <pre> block.
  • At which point in the reportor should it go? I was thinking that it could go at the start of #dump_summary.
  • I'm not sure of the best way to implement this in a mock-framework-agnostic way. How does this sound? In addition to the current three methods we have on the mock adapters (setup_mocks_for_rspec, verify_mocks_for_rspec and teardown_mocks_for_rspec), we can add an (optional) fourth method: print_summary_for_rspec. For now, rspec-mocks would be the only one to actually do anything here, but in the future if any of the other mocking libraries provide similar functionality, they'd have a place to hook in.

BTW, I'm not 100% happy with my naming of things (particularly UndefinedMethodDouble), so please make suggestions for anything you think could be organized or named better!

@dchelimsky
Copy link
Contributor

Myron - that spec output is fantastic.

Let's not worry about other frameworks at all until this is up and running.

I had not considered the means of reporting this. I need to give that some thought. Even though rspec-mocks is part of rspec, it's still a separate library, and I don't want to have any explicit dependencies on it from rspec-core other than the adapter.

I think we need an API for external libraries to extend existing formatters. WDYT?

I started to work on an event-based pub/sub messaging approach to reporting (on branch events), but put that off for rspec-2.1. I think that would make a formatter extension API much more feasible. Agree?

In terms of naming, the names you have suggest that the stub is not defined rather than the method being stubbed. How about something like StubbedMethodUndefined? I'm not in love with that either, but I think it's the right direction.

@myronmarston
Copy link
Member Author

Even though rspec-mocks is part of rspec, it's still a separate library, and I don't want to have any explicit dependencies on it from rspec-core other than the adapter.

Exactly. This was the issue I was facing in trying to figure out the reporting, which is why I suggested adding an additional method to the mocking adapters for this--that would be the only point of contact. I think I like your API idea better, though :).

I started to work on an event-based pub/sub messaging approach to reporting (on branch events), but put that off for rspec-2.1. I think that would make a formatter extension API much more feasible. Agree?

I took a look at the branch. It looks like that would allow me to know what the current running example is, but I'm not sure how that would play into the formatter API. What did you have in mind?

I was originally thinking that we could just expose the current running example as a class method of RSpec::Core::Example. The event approach is definitely more flexible, but it's also more complex for the simple case of just wanting to know the current running example.

How about something like StubbedMethodUndefined?

I thought about that, but to me it sounds like it's for stubs only and not for mocks (especially given Fowler's "mocks aren't stubs" article). I figured MethodDouble was a decent generic name for both mocks and stubs. Would UndefinedMethodMethodDouble be more clear? I thought about that, but rejected it because of the double Method. Anyhow, I don't have a preference at this point between any of the names we've discussed (they all kinda work, but not that well!), so I'll leave it to you to decide and just tell me what you want.

What did you have in mind for the formatter extension API? One complexity is that people can define external formatters--would I have to extend those as well? Or could we find a way to extend in a generic way that works for all formatters?

@justinko
Copy link
Contributor

justinko commented Sep 1, 2010

@myronmarston - its "stubbed" not "stubed" :)

@myronmarston
Copy link
Member Author

@justinko: I was aware of that when I wrote the code. I'm dynamically generating those specs in a loop (one iteration for mocks, one iteration for stubs), and I just added "ed" in the doc string to the variable that has "mock" or "stub". I could put more logic in place so that it's spelled right, but I didn't think it was worth it.

@jamesmartin
Copy link

I tried to reply to the mailing list thread, but had some Google account problems.

Just to clarify my understanding I wrote up a little example gist using the canonical Account->Logger example.

My comment on the Gist describes a potential use case that I see for this kind of feature. Am I barking up the wrong tree?

Also, do you need any help getting this implemented? What can I do to help?

@myronmarston
Copy link
Member Author

@jamesmartin: Thanks for sharing your example. The feature I've proposed here probably wouldn't help in an case like yours, because you are using pure test doubles, as opposed to setting a mock or stub on a concrete object. If your specs set the logger variable to Logger.new (i.e. an instance of the class that would actually get used in production), then this suggested feature could help, because that would presumably have a log method, and if it didn't, it would tell you so.

The hold up on this feature is that we want the report to be printed at the end of the spec run, but there currently isn't support in rspec-core for this. There's an open issue about this that will need to be resolved first.

In the meantime, check out aidmock. It may do what you want.

Myron

@myronmarston
Copy link
Member Author

At this point, I've been using (and loving) rspec-fire for a while. I'm happy to let that remain in an extension gem and leave rspec-mocks how it is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants