-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Moving the StreamTest to integration tests #391
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
87932ca
to
958f866
Compare
_expectation = nil; | ||
} | ||
|
||
- (void)fulfillOnCallback:(XCTestExpectation *)expectation { |
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.
This name is off: the trailing part of the label should be "expectation" to match the argument on the other side of the type.
Meanwhile every usage of this
- declares the expectation
- calls _delegate fulfillOnCallback
- does some async thing
- calls await expectations
Why not write a routine that takes a block and wraps it with the first two steps then calls the block then finally awaits expectations.
Something like:
- (void)awaitCallbackInBlock:(blocktype)block {
XCTestExpectation *openExpectation = [_testCase expectationWithDescription:@"awaiting"];
[_delegate fulfillOnCallback:openExpectation];
block();
[_testCase awaitExpectations];
}
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.
Sounds good, done.
return [datastore createWatchStreamWithDelegate:_delegate]; | ||
} | ||
|
||
- (void)verifyDelegate:(NSArray<NSString *> *)expectedStates { |
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.
Naming: label should end in states. Perhaps verifyDelegateObservedStates
?
When you're doing objective-C naming right each argument should be repeated two or three times: the label, type, and argument should align.
Sometimes the type differs because the label/argument are more specific than the type (as would be in this case).
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.
Done, thanks for the explanation.
} | ||
|
||
- (void)tearDown { | ||
[super tearDown]; |
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.
You can omit this method if it's not doing anything.
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.
Done.
dispatch_sync(_testQueue, ^{ | ||
}); | ||
|
||
XCTAssertEqualObjects(_delegate.states, expectedStates); |
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.
Shouldn't this also remove the states accumulated in the delegate so that subsequent assertions only need to assert about the new states?
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.
Hm, we can do this here, but it's not technically needed since delegate
is scoped to the test.
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.
delegate
is scoped to the test but not clearing this means that you can't reasonably make more than one assertion. I'm also fine just leaving this alone until we need to do that, but just wanted the intent of my comment to be clear.
974162d
to
096e77c
Compare
Feedback addressed. |
@@ -38,17 +38,25 @@ - (void)writesFinishedWithError:(NSError *_Nullable)error; | |||
*/ | |||
@interface FSTStreamStatusDelegate : NSObject <FSTWatchStreamDelegate, FSTWriteStreamDelegate> | |||
|
|||
- (instancetype)initFrom:(XCTestCase *)testCase |
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.
Naming: first part of the label should end with "test case".
Also avoid connecting words in the labels for subsequent arguments unless they're critical to the meaning. It's appropriate in e.g. copyToFile:fromFile
but not here, where you're just specifying the queue argument.
This should be: initWithTestCase:(XCTestCase *)testCase queue:(FSTDispatchQueue *)queue
.
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.
This was inspired by the name in FEventTester. I updated it to use the naming you suggested and removed the 'using' part.
@property(nonatomic, readonly) NSMutableArray<NSString *> *states; | ||
@property(atomic, readwrite) BOOL invokeCallbacks; | ||
@property(nonatomic, weak) XCTestExpectation *expectation; | ||
@property(nonatomic, weak, readonly) FSTStream *stream; | ||
@property(nonatomic, weak, readonly) XCTestCase *testCase; | ||
@property(nonatomic, weak, readonly) FSTDispatchQueue *dispatchQueue; |
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.
There are a lot of weak references in here which is a serious design smell. Are these actually necessary?
In general avoid weak references unless you specifically need them to break a reference cycle because they make your code very difficult to reason about.
In this case, you need the testCase
to be weak because you're making this a member of that test case (which creates a cycle). The other things in here can be regular strong references.
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.
It's enough for 'testCase' to be weak. Everything else is only retained by the test case itself as well as 'FSTStreamStatusDelegate'.
- (instancetype)initFrom:(XCTestCase *)testCase | ||
usingQueue:(FSTDispatchQueue *)dispatchQueue NS_DESIGNATED_INITIALIZER; | ||
- (instancetype)init NS_UNAVAILABLE; | ||
|
||
@property(nonatomic, readonly) NSMutableArray<NSString *> *states; |
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.
Consider splitting out implementation properties into a separate interface with an empty category (as is our convention elsewhere). As it stands it's not clear which of these are implementation state and which are meant to be used from within tests that use this delegate.
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.
The only public-facing property was 'invokeCallbacks', but I am actually not using it in this PR (and have removed it from the other one as well).
I tried moving the other properties into their own category, but it looks like I then need to create my getters and setters by hand (even @synthesize
doesn't work). There's some discussion about this here: https://stackoverflow.com/questions/14399991/how-can-i-declare-a-private-property-within-a-named-category
@property(nonatomic, readonly) NSMutableArray<NSString *> *states; | ||
@property(atomic, readwrite) BOOL invokeCallbacks; | ||
@property(nonatomic, weak) XCTestExpectation *expectation; | ||
@property(nonatomic, weak, readonly) FSTStream *stream; | ||
@property(nonatomic, weak, readonly) XCTestCase *testCase; |
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.
nit: consider making your declaration order match your assignment order in the constructor, so it's easy to verify everything is assigned.
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.
Done
dispatch_sync(_testQueue, ^{ | ||
}); | ||
|
||
XCTAssertEqualObjects(_delegate.states, expectedStates); |
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.
delegate
is scoped to the test but not clearing this means that you can't reasonably make more than one assertion. I'm also fine just leaving this alone until we need to do that, but just wanted the intent of my comment to be clear.
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.
This turned out really nicely. Thanks for pushing through all these changes.
Please verify the travis failure isn't real before submitting.
This is meant to make #388 smaller.