Reputation: 7571
I want to setup a UI testing system with iOS that allows me to test just a single ViewController OR UIView such that
a) I can provide it with Mocked data b) I can render its view to the simulator c) I can take a Screenshot of it, save it to disk and aggregate the snapshots (like snapshot)
Why? 1) The QA team wants to quickly verify UI's still look the way they should 2) We want to be able to quickly iterate the appearance of deeply located, complex programmatic View's which Interface Builder cannot support in any meaningful way.
The Xcode 7 UI Testing does not suit this purpose since you cannot actually compile any of the original code.
The Logic XCTest framework seems like a better fit however, it understandably is reluctant to render anything to the screen. I don't care: I want something rendered to the screen.
Please spare me your dogmatic philosophic diatribes about the one true TDD and UI vs Logic testing. This is perfectly possible with Android Studio and I've used it to much success.
Thanks in advance for any help.
Example
Model * model = [[MockModel init] alloc]
model.value = @(10)
UIViewController * importantViewController= [[ImportantViewController alloc] initWithModel:model];
TestAppDelegate *appDelegate = (TestAppDelegate *)[UIApplication sharedApplication].delegate;
UINavigationController *navController = (UINavigationController*)appDelegate.window.rootViewController;
[navController pushViewController:importantViewController animated:NO];
TakeSnapshot("Important01")
Upvotes: 1
Views: 2200
Reputation: 21244
As stated in your question and comments, you want to:
You have three different sets of options:
An application test starts an application and injects the test bundle into it. This allows the greatest degree of control in the test. Most applications will perform some set up steps early in the application life cycle which will "dirty" the environment for testing. You can follow the guidance in this answer or create a minimal application target for testing.
In your test you can create "mock" model objects to your hearts content and pass those to views or view controllers. In an application test you have the freedom to change the view hierarchy within the test by adding or removing views from the root view controller, providing your own root view controller, or presenting a view controller modally. Taking a screenshot is straightforward as described by Technical QA 1817: View Snapshots on iOS 7.
The process with UI testing is similar to applicaiton tests. Most of your interaction with the view hierarchy is through UI testing proxy objects which can limit what is or is not feasible to test. UI testing allows you to record, play back, and edit interaction with the user interface - and this is it's primary benefit. According to your question this is probably not of significant use to you. Just like with application tests, for UI tests you will want the ability to create a "clean" environment for testing.
UI Automation is the predecessor to UI tests (UI tests are based on UI Automation). Just like with UI testing UI Automation allows for playback, recording, and editing of interaction with the application user interface. UI Automation, unlike UI tests, runs outside of Xcode in Instruments - this gives you far less freedom to mock objects, etc. though this is still possible through launch arguments and other methods of passing parameters to the application under test. UI Automation makes taking screenshots fairly easy.
The Xcode 7 UI Testing does not suit this purpose since you cannot actually compile any of the original code.
When UI tests or application tests are built they are dependent on an application target. When the tests are run they are injected into the application that was built as a dependency. So the original code for both the application under test and the tests themselves is actually compiled and run.
Upvotes: 1
Reputation: 1586
Facebook created a excellent library iOS-Snapshot-Test-Case to do snapshot tests of UIViews and CALayers. With it you create unit tests which generate .png files of your views and compare them to previously generated (known good) examples.
All rendering is done offscreen and it's very fast. But it doesn't have built-in support for testing UIViewControllers. So you might need to do a little massaging to get that working, it shouldn't be more complex than making sure the root view has been instantiated and layed out with a reasonable (device size) frame.
One thing to note. For whatever reason Facebook didn't deem it necessary to allow you to define the device resolution (1x, 2x, 3x) when writing tests. So you'll need to be careful about which devices you record and run your tests on.
Upvotes: 1