I’ve been following a Rails convention and defining multiple environments for my iPhone projects. This allows me to quickly switch application wide settings when running a test, development, or production version of the app.
Continue reading ‘Multiple Environments in an iPhone Project’
Archive for the 'iPhone' Category
Working in Xcode I almost forgot how much I like IntelliJ’s code formatting tools. Luckily for me Mike Smith recently pointed out that UniversalIndentGUI can be used to setup your own code formatting in Xcode.
Continue reading ‘Code Formatting in Xcode’
Most of my iPhone apps need to accept keyboard input somewhere and that means I need to reposition my UI elements such that the keyboard does not hide the field the user is typing in. The iPhone Application Programming Guide offers one example of Moving Content That Is Located Under The Keyboard but this is not necessarily the best solution.
Continue reading ‘Resizing views around the keyboard’
While working on iPhone applications I have found it useful to load as much of the UI layout and styling from nib files as possible. As a result I often want to load the cells for a table view from a nib file and created a factory class to handle this behavior every time I want to reuse it.
When I need to use a custom cell in a table view I add a cell factory as a property on the view’s controller and select a cell to use by setting that property when constructing the controller. This often allows me to reuse a single factory across multiple controllers so I don’t have to repeat myself by including duplicate references to the same cell nib in every controller.
I recently needed to support some basic gesture recognition in an iPhone app. As it turns out this is a little bit tricky to do when the touches occur within the same responder chain as a view which already responds to touches (like a UIScrollView or UIWebView which might need to scroll or zoom in addition to handling my custom gestures).
Continue reading ‘iPhone gesture recognition’
UILabels are often the most convenient way to display simple text in an iPhone app however I often want a label to display variable text which may need to wrap to multiple lines. Simply increasing the height of the UILabel doesn’t help because a single line of text will be centered vertically within the label’s bounds. Instead I need to computer the size of the text I want to render and update the label’s frame’s height accordingly.
In most cases I want to adjust the size of not only a label but the view containing that label as well so I wrote a category to resize labels and their parent views.
Previously we discussed building an iPhone Unit Testing Toolkit. I wanted to reuse that work without having to repeat those configuration steps every time I started a new Xcode project. Xcode provides a number of templates or starting iPhone applications so I made my own versions which include all of the unit testing tools we rely on.
Continue reading ‘Custom Xcode Templates for iPhone Development’
In my last post on unit testing iPhone development I introduced a couple helpful tools including OCMock, a mock objects implementation for Objective-C.
I recently came across a scenario where I needed to make an assertion on an argument passed to an expected method invocation but OCMock did not provide the constraint I needed. I was testing a FileDetailsViewController that pushes a new FileContentsViewController on to the view stack when a button is pressed. I mocked the UINavigationController so that I could add an assertion that pushViewController:animated: is called with the right arguments.
The meat of my test is:
@interface FileDetailsViewControllerTest : SenTestCase {} FileDetailsViewController *controller; id navigationController; @end @implementation FileDetailsViewControllerTest -(void) setUp { controller = [[FileDetailsViewController alloc] initWithNibName:@"FileDetailsView" bundle:nil]; navigationController = [OCMockObject mockForClass:[UINavigationController class]]; controller.navigationController = navigationController; } -(void) testShowContentLoadsView { [[navigationController expect] pushViewController:[OCMConstraint isKindOfClass:[FileContentsViewController class]] animated:YES]; [controller showContentsButtonWasPressed]; } -(void) tearDown { [navigationController verify]; } @end
Note that in this example, I some fanciness is required to assign controller.navigationController = navigationController since it is a readonly property in the UIViewController API. I’ll explain what I did in a later post.
The OCMock feature I was missing is the OCMock.isKindOfClass constraint. So I wrote my own.
Following is the header file that declares the isKindOfClass assertion as a static method in an Objective-C category for OCMock. Categories are kind of like Ruby mixins for Objective-C. You can add static or instance methods to an existing class definition. With this approach I can follow the OCMock pattern of providing static factory methods on the OCMock class for the range of constraints available.
//File: OCMockConstraint+Extensions.h #import <OCMock/OCMConstraint.h> @interface OCMConstraint (Extensions) + (id)isKindOfClass:(id)value; @end
Following is the implementation, both of my new constraint and the factory method to create it.
//File: OCMockConstraint+Extensions.m #import "OCMockConstraint+Extensions.h" @interface OCMKindOfClassConstraint : OCMConstraint { @public id testClass; } @end @implementation OCMKindOfClassConstraint - (BOOL)evaluate:(id)value { return [value isKindOfClass:testClass]; } @end // Static factory method @implementation OCMConstraint (Extensions) + (id)isKindOfClass:(id)value { OCMKindOfClassConstraint *constraint = [OCMKindOfClassConstraint constraint]; constraint->testClass = value; return constraint; } @end
This implementation shows both how to write a custom constraint for OCMock and a use of Objective-C categories to provide a nice API for using it.
In many cases, you’ll want to write a custom constraint that is specific to your test scenario and not appropriate to be shared globally in this manner. In this case you’ll probably follow a similar strategy but implemented in your test class instead of mixed in to OCMockConstraint.
As we get in to developing iPhone/Touch applications at Carbon Five, we obviously want to bring over all our best agile practices including test driven development (TDD).
I’ve been bootstrapping with the beta version of the Pragmatic iPhone SDK Development book but was disappointed to find no discussion of unit testing for the iPhone. So I’ve been piecing it together as I go.
GTM
Unit testing in Objective-C is provided by the SenTestingKit framework that installs with XCode in /Developer/Library/Frameworks/. However it is not compatible with the iPhone SDK. The Google Toolbox for Mac provides an implementation of SenTestCase for the iPhone that I am using instead. The instructions provided on that page worked for me with one exception that I included as a comment on that page:
I followed the instructions above but was unable to see any messages in the console. I did not see the behavior described above as:
Your target should now build cleanly, and if you check the build log you should see something like: “Executed 0 tests, with 0 failures (0 unexpected) in 0.001 (0.001) seconds” at the end.
It turned out that I needed to set the base SDK in the inspector for my target to an iPhone simulator even though the Overview showed I was building for simulator debugging.
I created a ‘Unit Tests’ target per the GTM directions to run my tests. Now I am happily running my tests with command-B. One point that could be a problem when getting into continuous integration is that my Unit Tests target reports ‘Build succeeded (1 error)’ when a unit test fails instead of having the build actually fail.
I have not gotten into the “Advanced Stuff” described on that page.
Hamcrest
The SenTestingKit assertion methods are pretty lame. They’re verbose and require that you provide a string message for your expectation (e.g. STAssertEqualStrings(a1, a2, description, …)). We’re using and like Hamcrest on many of our Java projects. I was psyched to see there is an Objective-C implementation.
There is no download available for Hamcrest Objective-C so I checked it out from SVN and built the framework product in Xcode for OS X 10.5/i386.
I struggled for a while to get the dependency on the hamcrest.framework build product into my project. I ended up with this solution:
- Create a ‘Frameworks’ folder in my project root
- Copy hamcrest.framework to Frameworks/
- In Xcode, right click on ‘Frameworks’ and ‘Add existing framework…”
- Browse to the hamcrest.framework folder and add it, making sure to add it to my Unit Tests target only
- Right click on the Unit Tests target to add a new Copy Files Build Phase that copies to the Products directory and put that build phase early in the target steps
- Add hamcrest.framework to that build phase by dragging from Frameworks
- Include Hamcrest in your test class and you’re good to go
#import "GTMSenTestCase.h" #define HC_SHORTHAND #import <hamcrest/hamcrest.h> @interface ExampleWithAssertThat : SenTestCase @end @implementation ExampleWithAssertThat - (void) testUsingAssertThat { assertThat(@"xx", is(@"xx")); assertThat(@"yy", isNot(@"xx")); assertThat(@"i like cheese", containsString(@"cheese")); } @end
OCMock
iPhone development requires a lot of mucking around with UI framework classes like UITableView, UIApplicationDelegate and so on. These classes have a lot of dependencies and are depended upon all over the place which can make it hard to get them under test.
Mock objects are a great solution to this problem and OCMock provides an implementation for Objective-C. In this case, the OCMock.framework provided in the OCMock binary release worked for me when installed in the same manner as described for Hamcrest above.
This example of testing [UIApplicationDelegate applicationDidFinishLaunching] illustrates its use pretty well. I have a simple test that creates a mock UITableView to asserts a cell is correctly created in [UITableViewController tableView:cellForRowAtIndexPath:]. It looks like:
#import "GTMSenTestCase.h" #define HC_SHORTHAND #import <hamcrest/hamcrest.h> #import <OCMock/OCMock.h> #import "SortedStateViewController.h" #import "Country.h" @interface SortedStateViewControllerTest : SenTestCase {} SortedStateViewController *controller; @end @implementation SortedStateViewControllerTest - (void) setUp { controller = [[SortedStateViewController alloc] init]; Country *country = [[Country alloc] init]; [country addState:@"New York" withPopulation:19306183 andArea:47213]; [country addState:@"California" withPopulation:36457549 andArea:155959]; controller.country = country; controller.key = @"population"; } - (void) testPopulatesCell { id tableView = [OCMockObject mockForClass:[UITableView class]]; [[tableView stub] dequeueReusableCellWithIdentifier:[OCMConstraint any]]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(NSUInteger)0 inSection:(NSUInteger)0]; UITableViewCell *cell = [controller tableView:tableView cellForRowAtIndexPath:indexPath]; assertThat(@"California", equalTo(cell.text)); } @end
Continuous Integration
So I’m pretty happy with where this is now. I’m working through the Pragmatic book TDD as I go. It’s also have an ObjectiveCTest that I add assertions to as I play with features of the language.
Missing from this toolkit is a good continuous integration solution.
There is now a recently released Xcode builder for CruiseControl. However, we use Bamboo for CI for our Java and Ruby projects and are considering moving to TeamCity. It looks like there is an Xcode plugin for TeamCity and some attempts with Bamboo.
More on that later.
For the seven years that we have been evolving our Extreme Programming practice, we have repeatedly readdressed the question of how to best integrate user experience design (visual design, information architecture,…) with an agile process. As a consulting company, it has always been a requirement that we flex our process to accommodate our clients and partners. Over the last year or two we have found our clients and partners increasingly interested in flexing their processes to work more agile and collaboratively with us.
The post is the first of a series on user experience (UX) design practices for agile software development teams. In an upcoming project with our partner Hot Studios we will be exploring new ways to integrate their user experience design process with our software development process. We’ll share some learnings from that, experiences from the past and new ideas for the future.
First we have a growing reading list of existing resources on the topic that I am posting here for you. If you have other resources for us, please share.
User Research as a Commodity
Added 2008-02-14
Alex at Pivotal Labs noted this post from a user experience manager at Kaiser Permanente who describes a strategy for including regular user testing in an agile development process. The strategy is attractive because it fits with a key characteristic of agile where simple practices performed regularly produce high level complex results.
Kent Beck v. Alan Cooper
This is a 2002 article with the following abstract “Kent Beck is known as the father of ‘extreme programming,’ a process created to help developers design and build software that effectively meets user expectations. Alan Cooper is the prime proponent of interaction design, a process with similar goals but different methodology. We brought these two visionaries together to compare philosophies, looking for points of consensus—and points of irreconcilable difference.” The difference in perspective between the two is very expressive of the conflicts we have seen between design and agile development processes. Many of the following resources reference this discussion.
Note: the original source for this great interview appears to have been taken over by another entity that is no longer making the article available. I am linking to it in the Internet Archive.
Waterfall Bad, Washing Machine Good
Leisa Reichelt’s IA Summit 07 presentation on the role of IA in the design process identifies the failures of a waterfall design process and argues that an agile, iterative design process is superior. Slide 14 is right on.
User Experience Activities on Agile Development Projects
Recent article by Scott Ambler addresses the gap between Beck and Cooper by identifying a middle ground that requires UX and agile practitioners to learn a bit more about each others’ practices and to adopt some of each.
Holistic Product Design & Development
A series of blog posts by Jeff Patton on agile software development and user centered design. Jeff moderates the agile-usability Yahoo group.
Agile Usability Yahoo! Group
The description for this group provides a good summary of the issues we are tackling here. You are invited to jump into the fray.
Experiences Integrating UED Practices
In this experience report Paul Hodgetts presents his “teams’ struggles to come to grips with the often programming-centric orientation of agile processes, and their ongoing efforts to integrate their UED (user experience design) best practices into the incremental, collaborative world of agile processes.” He provides an overview to the range of UX practices, identifies challenges and discusses practices that he found were particularly useful in integrating UX and and agile development.
Agile User-Centered Design
A post to ID-discuss that presents one designer’s struggle to reconcile agile and user-centered design.
Process Agility and Software Usability: Toward Lightweight Usage-Centered Design
2001 paper by Larry Constantine presents concrete practices for UX that map to agile practices. His approach is simple and pragmatic.
The Challenge of Agile Design
These are slides from a talk given by our friends at Pivotal Labs and Satisfaction.
User Centered Design Round Table
Podcast of a discussion on user-centered design and agile development with Lynn Miller, Jeff Patton and Rebecca Wirfs-Brock.
Originally posted 2007-09-06
Last updated 2008-02-14

