unit testing in ios

18
Unit Testing with iOS

Upload: long-weekend-llc

Post on 12-Nov-2014

8.431 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Unit Testing in iOS

Unit Testing with iOS

Page 2: Unit Testing in iOS

Have you ever developed in...

• Ruby on Rails• PHP on Symfony• PHP on Zend• Python on Django• Java on J2EE

All of these languages / frameworks make it easy to write/run:

• Unit tests• Functional tests• Integration tests

Page 3: Unit Testing in iOS

Unfortunately...

• "Objective-C on Cocoa Touch" didn't make the list.

Page 4: Unit Testing in iOS

Why test in the first place?

• You can't write a test case until you know what "good output" and "bad output" look like: writing a test case forces you to define the problem.

• And, if you write test cases before you write production code, you are not emotionally attached to an implementation -- if you discover a mistake, you're likely to address it.

Page 5: Unit Testing in iOS

Unit testing in Objective-C

• Functional tests are a bit painful yet (I feel) in Objective-C / Cocoa Touch - you have to write Javascript commands

• Let's focus on unit testing only today (larger "units" can start to act as functional tests).

Page 6: Unit Testing in iOS

Unit testing frameworks provide...

• Setup/teardown helpers run before each test• Assertion macros like:

o STAssertTrue(NO,@"I am a complete failure");o STAssertEqual(foo,bar,@"foo should = bar");

• A test runner than runs all of, or a subset of, your unit test cases & reports the results.

Page 7: Unit Testing in iOS

Choosing a unit testing framework...• You have 2 choices:

o GHUnit (on GitHub)o OCUnit (built into Xcode)

• I spent a long time1 considering the pros and cons of each, but if you are:o Writing a new projecto Won't have hundreds of test caseso Are using Xcode 4

    ... then I argue you should probably choose OCUnit.

1 Approximately 10 hours on a transpacific flight

Page 8: Unit Testing in iOS

More details on OCUnit...

• When you tick "Use Unit Testing" on the New Project template wizard, the set up is already done

• ⌘U is all you need to press to run your tests• Does not have the -setUpClass and -tearDownClass helpers

• Does not allow you to run unit tests individually, must run entire test suite (some MAY argue that this is a "feature")

Page 9: Unit Testing in iOS

More details on GHUnit...

• Handier macros & test class helper methods than OCUnit

• Can run a single test (good for debugging if you have many tests)

• Much sexier log output than OCUnit• Not built into Xcode 4, you have to set it up as a

separate target and build & link its framework• More time-consuming to run tests• Runs in the Simulator or on the device as an actual

target, with its own UI

Page 10: Unit Testing in iOS

Whichever you choose...

• They will both get the job done, and they are both so much better than having no unit tests at all.

• OK, so all set up?  If you need help on GHUnit, see my blog post on the subject:

http://longweekendmobile.com/2011/02/23/tdd-best-practices-testing-in-ios4-with-ghunit-part-1/

Page 11: Unit Testing in iOS

Let's write some tests...

There are 2 times to write unit tests:• Before developing a new feature (wow, you TDD

stud)• When a section of code is:

o Buggy - doesn't work how you expecto Fragile - seems to break all the timeo Coupled - seems to break all the time when you

change things elsewhere, and in non-obvious ways*

* Usually this type of test writing is done after a bug by such code is found, but also can be done before a major refactor.  Or both.  Unit tests also allow you to refactor mercilessly, which is a good habit to be in.

Page 12: Unit Testing in iOS

What does a unit test look like?

// MyTest.m (I roll .h into this)

- (void) setUp {}

- (void) tearDown {}

- (void) testSomething {}

- (void) testAnotherThing {}

Page 13: Unit Testing in iOS

I use setUp and tearDown for this...@interface LWEFormViewTest {  LWEFormView _testObject;}

- (void) setUp {  _testObject = [[LWEFormView alloc]                          initWithFrame:CGRectZero];}

- (void) tearDown {  [_testObject release];  _testObject = nil;}

Page 14: Unit Testing in iOS

...which helps me focus on tests:

- (void) testTextFieldAdd{  UITextField *aField = [[UITextField alloc] init];  aField.tag = 1;  [_testObject addSubview:aField];

  int numForms = [[_testObject formOrder] count];

  // Assertions go here

  [aField release];}

Page 15: Unit Testing in iOS

Assertion macros finish off the test

- (void) testTextFieldAdd{  UITextField *aField = [[UITextField alloc] init];  aField.tag = 1;  [_testObject addSubview:aField];

  int numForms = [[_testObject formOrder] count];

  GHAssertTrue((numForms == 1),            @"We added an object, why wasn't it showing up?");

  id<NSObject> lastObj = [[_testObject formOrder] lastObject];  GHAssertEqualObjects(lastObj,aField,            @"Why did a different one come back?");

  [aField release];}

Page 16: Unit Testing in iOS

GHUnit & OCUnit macros

  GHUnit: • GHAssertTrue• GHAssertEqualObjects• ... many more

  OCUnit:• STAssertTrue• STAssertEquals• ... many more

Page 17: Unit Testing in iOS

Unit tests you should always write

• Incorrect object types• Out-of-bounds values• Boundary values• Expected values• Using loops to stress test... but maybe not unit

Page 18: Unit Testing in iOS

Q+A

• Interested to hear everyone's experiences with testing on iOS