Note: I added kif to the title just for search indexing puposes, considering that most of the answer turned out to discuss it
I'm looking for something like selenium for iOS, basically a test-automation/unit test framework that can run a certain UI scenario many many times until it crashes, which would help me narrow down the cause of a UI bug that happens very rarely and randomly.
(and by the way, I've NSLogged every single line of code of datasource/table interaction and spent hours analyzing the potential cause.. but found nothing conclusive.. again this bug very rarely happens).
I looked at some of the unit testing frameworks in iOS, but they seem to be so many. I'm not sure which to pick. Also my reference to selenium is based on conjecture, as I've worked with QA folks who've used Selenium in large web projects in the past (and i'm assuming that there must be something similar for iOS).
Now that I'm a one man team working on an iOS project, I'm gonna have to put a QA hat on and figure this bug out.
I'm facing a classic bug that happens when there is a discrepancy between the actual number of rows inserted in a UITableView and the number of rows that the datasource delegate returns. This is the error message:
*** Assertion failure in -[UITableView
_endCellAnimationsWithContext:] Exception in insertRows: Invalid
update: invalid number of rows in section 0.
The number of rows contained in an existing section after the update (2) must be equal to
the number of rows contained in that section before the update (2),
plus or minus the number of rows inserted or deleted from that section
(1 inserted, 0 deleted) and plus or minus the number of rows moved
into or out of that section (0 moved in, 0 moved out).
I click on a UITableViewCell
that takes me into another UITableView
. Sometimes it works
and sometimes (very rarely) it doesn't (with the above error):
update:.. i've added example code about KIF 2.0 at the bottom after divider.. for those who are more interested in KIF than the specific problem i'm facing:
After some research and experimenting.. I've narrowed down my options to two test-automation libraries: Frank and KIF. I ultimately decided to use
KIF
while borrowing cucumber's Gherkin syntax to describe my unit tests.The reason I chose
KIF
(rather thanFrank
) was thatKIF
is 100% obj-c based, rather than using ruby as well as was the case withFrank
. So setting up is simpler, and it was more applicable to my narrow test case requirement. That being said, I admitFrank
would be more useful if my application was more complicated (ie using intput from multiple servers etc). You can see the last quarter of this excellent presentation to learn more about the pros and cons of KIF, Frank and other automation-testing frameworks including Apple's own UI Automation.After using KIF, I found the bug causing the error above, and I could reproduce it using KIF 100% of the time! The reason why it happened so rarely was because it happened only when I tapped through the screens really fast.. and since KIF automates the steps.. it does them at an incredibly fast speed.. which exposed the bug :).
So following will be a sample of the code I used for testing.. this is just to give you a quick feel of what KIF (and Gherkin) can do for you:
in one file I specify the scenarios I want to run:
each scenario maps to steps (to understand more about the gherkin syntax -and behavioral driven development, which is based on test driver development, I strongly recommend to read this excellent book about cucumber):
and steps are defined using KIF's UI automation methods (this is just one example):
KIF 2.0 sample code: KIF 2.0 uses Xcode 5's all new test navigator.. which is a huge improvement than what KIF 1.0 was doing.. now your tests feel a lot more organic and natural than the past.. (ie it goes in real time.. rather than creating scenarios that run in the future etc).. you even get to test each one with a play button etc.. you should try it out.
here are some examples (again using gherkin syntax):
here is the implementation of some of the test cases in the category files: