Keys to iOS testing: KIF and Kiwi
Most recently Blazing Cloud iOS developers use these open source libraries: Kiwi for unit testing and KIF for acceptance testing.
Kiwi is a BDD (Behavior Driven Development) testing library that supports mocking, stubbing and asynchronous invocations of Objective-C methods or units of code.
KIF (Keep It Functional) library allows to use Objective-C code to write scripts to simulate user taps, gestures and keyboard input and assert on expected updates on a device screen.
Here are the Github forks we use in Blazing Cloud production apps:
https://github.com/blazingcloud/Kiwi
https://github.com/blazingcloud/KIF
Many thanks to Square, Allen Ding and many open source contributors!
Usually we setup separate build targets on iOS Xcode project, which have no impact on the app target.
- Specs could be invoked within XCode by
⌘-U
keyboard shortcut. - Integration Tests could be run by
⌘-R
keyboard shortcut.
Both test targets could run on iOS Simulator as well as iOS device. Simulator is great in day-to-day rapid development and device to validate behavior in realistic environment.
To start with Kiwi, let’s write a simple spec that should pass when Kiwi is correctly installed. Adding tests to an existing iOS project could be a challenge, so start small.
According to Kiwi docs we create a new (Specs) target on our iOS project and add first spec as a new file to the this target:
1 2 3 4 5 6 7 |
describe(@"Kiwi", ^{
context(@"when newly installed", ^{
it(@"should work", ^{
[[theValue(true) should] beTrue];
});
});
}); |
For Integration Tests, let’s start by adding simple scenario that validates app was launched successfully. We can do this by asserting on presence of some UI element, like label or button. For example, below should pass when user sees Welcome screen.
After installing KIF and creating an Integration Tests target we add this scenario to our category of KIFTestScenario class:
1 2 3 4 5 6 7 8 |
+ (id)scenarioToLaunch
{
KIFTestScenario *scenario =
[KIFTestScenario scenarioWithDescription:@"Test that a user can start the app"];
[scenario addStep:
[KIFTestStep stepToWaitForViewWithAccessibilityLabel:@"Welcome"]];
return scenario;
} |
There are many other ways to test the apps, including manually. We usually do manual testing thinking the app will be small and quick to test by just using it. On our experience apps grow in complexity quite fast and manual testing leads to fear of change what’s working and embarrassing bugs.
Legacy frameworks like SenTest and OCMock are great when you already have tests. OCMock tests are hard to read, debug and refactor.
We have used GHUnit, which was a minor improvement over OCUnit in the past.
As Objective-C developers we want to author the integration tests instead of dedicating QA resources to do repetitious tasks. Integration tests give us an additional safety net, save time testing in different environments (iOS versions, iPhone and iPad versions). Seeing your apps running through multiple automated scenarios gives you confidence and allows to focus on more interesting and creative test cases.
Let us know in comments how do you test your iOS apps. What are your challenges in testing Objective-C?
2 Comments
Do you have a example how to use Kiwi to test a application that use core data, like test a CRUD example?
thx
CoreData tests are easier to start as App Specs, not Unit Specs. Because Core Data is accessing Documents folder which is not set for Unit Specs. App Specs will load application bundle and can access Core Data of the main target. You can set up some test helper class which will reset core data state before all tests begin.