-
Notifications
You must be signed in to change notification settings - Fork 339
Implement expect_disjoint()
#2239
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
Conversation
@stibu81 my inclination would be to define the tests like this:
(i.e. just replacing "every" with "no", and adding "not" before subset). Does that make sense to you or have I confused myself? (As I do whenever I look at these functions) |
How about a single |
@hadley It is very confusing, yes. I think the confusion has to do with what I briefly mentioned at the end of my original post: there are two reasonable ways to think about these functions: in terms of single elements or in terms of sets. In the case of For
These two statements turn out to say exactly the same (
As an example, Your description of the tests mixes those two distinct ways of understanding the functions, so I think it is not correct. The name suggested by @lionel- is much clearer and cannot be misunderstood, so I prefer that one. From the name, it is less obvious that this is a kind of inverse to What is your preferred way forward? Should I replace the two functions by |
When I think of these, I do think the "elements" based approach mentioned above is what I'd expect them to do. I think pictures are useful here: What falls out from these pictures is that not-contains and not-in would use the same implementation when defined this way. I do think their error messages would probably be a little different:
And of course you'd provide the arguments in different orders, But I do really like what @lionel- suggested here. I think
I don't think the argument order actually matters all that much. Reporting something like this feels like it would be good enough for all use cases
|
@DavisVaughan I think, we agree then. This would replace the two functions that I implemented with a single one that does exactly the same, but has a clearer name and produces slightly different output. But it would not be the exact inverse of And I would not implement the set-variants of Is it ok for me to go ahead or should I wait on a comment by @hadley? |
I think you can go ahead! |
Plan sounds good to me! |
Second attempt, now with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hadley looks good to me and the implementation matches the spirit of expect_in()
- I'll let you be the final approver and merge-er
R/expect-setequal.R
Outdated
) | ||
msg_act <- c( | ||
sprintf("Actual: %s", values(act$val)), | ||
sprintf("Expected: none of %s", values(exp$val)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sprintf("Expected: none of %s", values(exp$val)), | |
sprintf("Expected: None of %s", values(exp$val)), |
I think I like having this capitalized more
|
||
expect_snapshot_failure(expect_disjoint(x1, x2)) | ||
expect_snapshot_failure(expect_disjoint(x1, x3)) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be useful to have a test for expect_disjoint(c("a", NA), NA)
to test that missing values are matched exactly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review. I made the requested changes. In doing so, I might have stumbled onto something else: expect_failure()
does not succeed for expect_disjoint()
and some other functions in this file, e.g.:
expect_failure(expect_in(3, 5))
## Error: Expected zero successes.
## Actually succeeded 1 times
I think that the reason is that the call of fail()
is not inside return()
for some functions, such that the later pass()
is also executed. expect_snapshot_failure()
seems to be ok with this but not expect_failure()
.
I could fix those missing return()
s, but I'm not sure that it is good to mix this into this PR that is about something else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stibu81 that's because the expectation style has changed since you started working on this PR 😬 I've updated your expectation to the new style and expect_failure(expect_in(3, 5))
now correctly passes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems I picked a bad moment for this... 😆 Thanks for fixing it.
expect_not_contains()
and expect_not_in()
expect_disjoint()
This introduces two negated expectations as suggested in #1851 with the following functionality:
expect_not_contains(x, y)
tests thatx
contains none of the elements ofy
(i.e.y
is disjoint fromx
).expect_not_in(x, y)
tests that no element ofx
is iny
(i.e.x
is disjoint fromy
).While the not negated expectations actually do something different, these two are equivalent. It might still make sense to have them both.
During implementation I realised that one might have different expectations from these names. For example, one might expect that
expect_not_in(x, y)
checks that:x
are iny
(which is what I implemented)x
is not a subset ofy
Both of them could also meaningfully be understood as inversions of the other two expectations. Would the second variant also be of interest?
Let me know if anything should be improved.