I just read the following post and tried to implement the approach described there:
Writing iOS Acceptance Tests Using Kiwi - Agile
Everything described here works great. But! there is one thing that breaks determinism when I do my acceptance tests.
Here is a repo on Github where the author of the post pushed his experiments (you can find it at the bottom of the page in the comments): https://github.com/moredip/2012-Olympics-iOS--iPad-and-iPhone--source-code / tree / kiwi-acceptance-mk1
Consider this code, which it uses to listen to the view:
- (void) tapViewViaSelector:(NSString *)viewSelector{ [UIAutomationBridge tapView:[self viewViaSelector:viewSelector]]; sleepFor(0.1);
... where sleepFor has the following definition behind it :
#define sleepFor(interval) (CFRunLoopRunInMode(kCFRunLoopDefaultMode, interval, false))
This is a naive attempt ("naive" not about the author, but about the fact that this is the first thing that comes to mind) to wait a tiny period of time until all animations are processed and all possible events that were (or can be) planned are soaked in the main run loop (see also this comment ).
The problem is that this naive code does not work in a deterministic way. There are a bunch of user interface interactions that make you click the fx next button button before the currently edited text field keyboard disappears and so on ...
If I just increase the time from 0.1 to fx 1, all problems disappear, but this leads to the fact that each individual interaction, such as "filling the text field with text ..." or "click button with a header ...", it becomes worth one second!
So, I do not mean simply increasing the waiting time here, but rather a way to make such artificial expectations a guarantee that I can continue my test case with the next step.
I hope this will be a more reliable way to wait until all the things caused by the current action (all transitions / animations or something like the main loop of the loop) are done.
To summarize everything, you need to ask a question:
Is there a way to release / merge / absorb all the materials planned in the main thread and its cycle loop to make sure the main thread is inactive and its start cycle is “empty”?
This was my initial decision:
// DON'T like it static inline void runLoopIfNeeded() { // https://developer.apple.com/library/mac/