Unit Testing is Wonderful, But
Asked Answered
A

4

10

I took the time to set up some Unit Tests and set up the targets in XCode, etc., and they're pretty useful for a few classes. However:

I want to test small UI pieces for which I don't want to launch the entire application. There is no concept of pass/fail: I need to "see" the pieces, and I can make dummy instances of all the relevant classes to do this. My question is: how can I set this up in XCode?

I realize I could use another XCode project for each class (or groups of classes), but that seems a bit cumbersome. Another target for each?

Ammon answered 30/9, 2010 at 20:46 Comment(0)
S
5

Well, you cannot call showing a piece of some GUI a testing even if that GUI is a part of a large application. What you can do here is create a separate executable target and write a small tool that reuses GUI components from your application and shows them to you basing on input parameters. This will eliminate the need for many many different targets.

If you still insist on using unit tests, you can show your GUI for some period of time, for example, 10 seconds. So the test case will run until GUI is closed or timeout elapses and each test will take up to N seconds to execute.

Smallage answered 30/9, 2010 at 20:56 Comment(2)
Thanks, point taken about it not being "testing." So these are new targets in the same XCode project, or in a different one?Ammon
@Yar: It is more like a matter of personal preference. Keeping it in the same project is more convenient for me.Smallage
D
12

I know that you're looking for an approach to testing UI components that doesn't require a fully functional application, but I've been impressed with what the new UI Automation instrument introduced in iOS 4.0 lets you do.

This instrument lets you use Javascript scripts to interactively test your application's interface, and it does so in a way that does not require checking exact pixel values or positions on a screen. It uses the built-in accessibility hooks present in the system for VoiceOver to identify and interact with components.

Using this instrument, I have been able to script tests that fully exercise my application as a user would interact with it, as well as ones that hammer on particular areas and look for subtle memory buildups.

The documentation on this part of Instruments is a little sparse, but I recently taught a class covering the subject for which the video is available on iTunes U for free (look for the Testing class in the Fall semester). My course notes (in VoodooPad format) cover this as well. I also highly recommend watching the WWDC 2010 video session 306 - "Automating User Interface Testing with Instruments".

Dayna answered 1/10, 2010 at 1:20 Comment(1)
Sometimes I wonder why I ask so many questions on SO, but once in a while I get a response like this one that opens up a door that I didn't even know about. Thanks for this.Ammon
S
5

Well, you cannot call showing a piece of some GUI a testing even if that GUI is a part of a large application. What you can do here is create a separate executable target and write a small tool that reuses GUI components from your application and shows them to you basing on input parameters. This will eliminate the need for many many different targets.

If you still insist on using unit tests, you can show your GUI for some period of time, for example, 10 seconds. So the test case will run until GUI is closed or timeout elapses and each test will take up to N seconds to execute.

Smallage answered 30/9, 2010 at 20:56 Comment(2)
Thanks, point taken about it not being "testing." So these are new targets in the same XCode project, or in a different one?Ammon
@Yar: It is more like a matter of personal preference. Keeping it in the same project is more convenient for me.Smallage
B
2

This is a good question. I think you actually do not want to use unit tests for those 'visual confirmations'. Personally I usually write little test apps to do this kind of testing or development. I don't like separate targets in the same project so I usually just create a test project next to the original one and then reference those classes and resources using relative paths. Less clutter. And it is really nice to be able to test more complex user interface elements in their own little test environment.

Brinkman answered 30/9, 2010 at 20:55 Comment(1)
Interesting... I was thinking about separate XCode projects, just wanted to make sure I'm sane :)Ammon
S
2

I would take a two-level approach to UI "unit testing":

  1. lthough Cocoa/CocoaTouch are still closer to the Model-View-Controller than the Model-View-ViewModel paradigm, you can gain much of the testability advantage by breaking your "View" into a "view model" and a "presenter" view (note that this is somewhat along the lines of the NSView/NSCell pair; Cocoa engineers had this one a long time ago). If the view is a simple presentation layer, than you can test behavior of the view by unit testing the "view model".

  2. To test the drawing/rendering of your views, you will have to either do human testing or do rendering/pixel-based tests. Google's Toolbox for Mac has several tools for doing pixel-by-pixel comparison of rendered NSViews, CALayers, UIViews, etc. I've written a tool for the Core Plot project to make dealing with the test failures and merging the reference files back into your unit test bundle a little easier.

Spermato answered 30/9, 2010 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.