"Implies" matcher#295
Open
xtreme-james-cooper wants to merge 2 commits intocedarbdd:masterfrom
xtreme-james-cooper:implies
Open
"Implies" matcher#295xtreme-james-cooper wants to merge 2 commits intocedarbdd:masterfrom xtreme-james-cooper:implies
xtreme-james-cooper wants to merge 2 commits intocedarbdd:masterfrom
xtreme-james-cooper:implies
Conversation
Author
|
A different use case is checking "homemade algebraic data types": the common ObjC design pattern where a field is only valid if a flag is set. data MyData = NoFields | OneField [Int] | TwoFields Int String might be represented as typedef enum {
NO_FIELDS,
ONE_FIELD,
TWO_FIELDS
} MyData;
...
@property (nonatomic, assign) MyData myDataFlag;
@property (nonatomic, assign) NSArray* intArrayField;
@property (nonatomic, assign) int intField;
@property (nonatomic, assign) NSString* stringField;With an implies matcher, the invariant for this can be easily checked: invariant(@"MyData should behave like the ADT it's emulating", ^{
(subject.myDataFlag == NO_FIELDS) should imply (subject.intArrayField == nil);
(subject.myDataFlag == NO_FIELDS) should imply (subject.intField == 0);
(subject.myDataFlag == NO_FIELDS) should imply (subject.stringField == nil);
(subject.myDataFlag == ONE_FIELD) should imply (subject.intArrayField != nil);
(subject.myDataFlag == ONE_FIELD) should imply (subject.intField == 0);
(subject.myDataFlag == ONE_FIELD) should imply (subject.stringField == nil);
(subject.myDataFlag == TWO_FIELDS) should imply (subject.intArrayField == nil);
(subject.myDataFlag == TWO_FIELDS) should imply (subject.intField != 0);
(subject.myDataFlag == TWO_FIELDS) should imply (subject.stringField != nil);
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A simple implies matcher, for use in invariants [#294, #289]. Because in an invariant, unlike a regular hand-written unit test, the exact values of the variables at test-time may not be known, it may be necessary to add in conditionals to ensure the perpetual truth of the invariant:
Adding in the implies logical connective as a matcher makes this simpler and more declarative:
The implies matcher follows the standard logical connective semantics:
Currently it only supports boolean arguments (or object arguments interpreted as nil/not nil). One possible improvement would be to upgrade it to a full-blown matcher-combinator, taking matchers as one or either argument, enabling the user to leverage the full scope of matchers available; although most matchers can be implemented reasonably clearly and efficiently as a boolean test (
X should be_instance_of(Y)as[x isKindOfClass: Y], for instance) so this doesn't seem as critical, and it would open the door to nested matcher combinators etc, which is probably not the road to go down just yet.