-
Notifications
You must be signed in to change notification settings - Fork 88
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
Make matchers composable more easily #259
Comments
Hi! I did a lot of work on this a year or so ago. For ideas, see:
For code, see:
where I tried to reduce inheritance and replace with interfaces. It's probably not necessary to make matcher more composable, but it's how I'd do it. I abandoned the effort after 8 months, due to not being able to sell the idea to the rest of the team and due to a 5 month wait for a re-review on #211. |
@thomir can't the specific cases you mention be solved with MatchesAll (and possibly MatchesAny)? E.g.: from testtools.matchers import MatchesAll
def MyMatcher(matchee):
return MatchesAll(SomeOtherMatcher('foo'), YetAnotherMatcher(123)) while I agree that matchers composition needs a bit of love, I think that the testtools.matchers._higherorder package can already get you covered in several situations. |
IIRC, @rbtcollins was open to the idea of explicit interfaces as long as they were plain old Python classes (no abc or zope.interface, for reasons that elude me), and strongly against adapters. I'm not sure everyone was sold on the general idea of reducing code-sharing inheritance by exposing only interfaces and functions. |
Worth noting: I had lots of follow-up done for #211 that I've since (probably) lost, or at least have only in hard-to-access archives. Removed most Mismatch subclasses and IIRC most Matcher subclasses. I'm not going to do this work again, but someone might want to. |
Jonathan Lange <[email protected]> writes:
IIRC, @rbtcollins was open to the idea of explicit interfaces as long
as they were plain old Python classes (no abc or zope.interface, for
reasons that elude me), and strongly against adapters.
I'd be against adapters as public interface too for this specific case
(expecially if they'd use the global registry). We might want to use
adapters internally as implementation detail, but it feels really
overkill.
I wouldn't oppose to zope.interface, although it brings in a slightly
questionable dependency.
@rbcollins feedback is appreciated! :)
I'm not sure everyone was sold on the general idea of reducing
code-sharing inheritance by exposing only interfaces and functions.
FWIW I'm sold on that part.
|
Hi @freeekanayaka - thanks for your reply.
Based on the conversation here, I suspect there's appetite for doing something to make matchers more composable. |
@thomir yes, I agree that it does not feel particularly natural, and it has the limitations that you point. So MatchesAll is something you can use right now to alleviate the particular issues reported in this ticket, but let's leave this open for future reference in case somebody wants to tackle the problem appropriately. |
@jml - I'm open and pro explicit typing here - e.g. using the typing module and mypy would be great. zope.interfaces with the global registry of type adapters and so on I don't like: its not that it can't work (it obviously can), but its not something that is obvious or predictable to Python developers per se (unilke e.g. in rust where interface adaption is a commonly used idiom that is core to the language.; ABC brings runtime overheads but would be ok. I'm strongly pro composition as a preferred approach for building rich matchers; I had specific code review concerns with the POC that was put up previously, from memory. I'm disinterested in reducing the code we've got right now - I'll happily review patches to do it, but its not something I feel an urge to do myself. Making it easier for other folk to write matchers is something I think is important, and our existing code may be a good place to test out ideas for that. I'm unsatisfied with our structural matching support, but not sure how to make it better right now ;(. I don't recall how/why #211 stalled - it looks to me like it had been fully reviewed. HTH. |
We love testtools matchers. We typically build some pretty complex matchers, which make our tests much easier to read. However, we frequently run into issues with the fact that re-using one matcher to implement a second one is tricky. At best it involves writing something like this inside the
match
function:...this gets tiresome quickly.
Another thing that sometimes happens is engineers try and work around this with subclassing one matcher from another:
...however this leads to all the classic issues surrounding using inheritance to re-use behavior.
I propose instead that the base
Matcher
class should contain anassertThat
method, so the first example above could be more natually expressed as:I'm filing this bug in order to solicit ideas/feedback - I can probably find some time to implement this myself in the next few weeks.
The text was updated successfully, but these errors were encountered: