SlideShare a Scribd company logo
Unit Testing
Special Cases
How to Test
UIViewControllers

How to TestUnit Testing
What Is Testing For? 
UIViewControllers

Block-based code

!
How to TestUnit Testing
What Is Testing For? 
UIViewControllers

Block-based code

CoreData	

How to TestUnit Testing
What Is Testing For? 
UIViewController
IBOutlets & IBActions

viewDidLoad

dealloc

UINavigationController
UIViewController
IBOutlets & IBActions
Outlet is connected
- (void)setUp {
[super setUp];
sut = [ConverterViewController new];
}
!
- (void)tearDown {
sut = nil;
[super tearDown];
}
Is Outlet Connected?
- (void)setUp {
[super setUp];
sut = [ConverterViewController new];
}
!
- (void)tearDown {
sut = nil;
[super tearDown];
}
!
- (void)testThatTextFieldOutletIsConnected {
XCTAssertNotNil(sut.textField, @"outlet should be connected");
}
Is Outlet Connected?
- (void)setUp {
[super setUp];
sut = [ConverterViewController new];
}
!
- (void)tearDown {
sut = nil;
[super tearDown];
}
!
- (void)testThatTextFieldOutletIsConnected {
XCTAssertNotNil(sut.textField, @"outlet should be connected");
}
Is Outlet Connected?
- (void)setUp {
[super setUp];
sut = [ConverterViewController new];
}
!
- (void)tearDown {
sut = nil;
[super tearDown];
}
!
- (void)testThatTextFieldOutletIsConnected {
[sut view];
XCTAssertNotNil(sut.textField, @"outlet should be connected");
}
Is Outlet Connected?
IBOutlets & IBActions
Outlet has a right action.
- (void)testButtonActionBinding {
[sut view];
NSArray* acts =
[sut.button actionsForTarget:sut
forControlEvent:UIControlEventTouchUpInside];
XCTAssert([acts containsObject:@"onButton:"], @"should use
correct action");
}
Is Action Connected?
IBOutlets & IBActions
The action does the right things.
viewDidLoad
Unit testing of a view controller
nearly always means writing the
view controller methods differently
viewDidLoad
- should call helper methods
viewDidLoad
- should call helper methods

- each of the helper methods should
do just one thing (SOLID principles)
viewDidLoad
- should call helper methods

- each of the helper methods should
do just one thing (SOLID principles)

- write tests for each of the helper
methods
viewDidLoad
- should call helper methods

- each of the helper methods should
do just one thing (SOLID principles)

- write tests for each of the helper
methods

- test viewDidLoad calls helper
methods (partial mock)
dealloc
setUp tearDown zombie
dealloc
❓hook dealloc method of SUT when
setup
dealloc
❓hook dealloc method of SUT when
setup

❓record calling of the hook
dealloc
❓hook dealloc method of SUT when
setup

❓record calling of the hook

❓verify if hook is called after teardown
Aspects
/// Adds a block of code before/instead/after the current
`selector` for a specific instance.
- (id<AspectToken>)aspect_hookSelector:(SEL)selector
withOptions:(AspectOptions)options
usingBlock:(id)block
error:(NSError **)error;
!
/// Called after the original implementation (default)
AspectPositionAfter,
!
/// Will replace the original implementation.
AspectPositionInstead,
!
/// Called before the original implementation.
AspectPositionBefore,
Aspects
dealloc
✅ hook dealloc method of SUT when
setup 

❓ record calling of the hook

❓ verify if hook is called after teardown
Aspects
dealloc
✅ hook dealloc method of SUT when
setup 

✅ record calling of the hook

❓ verify if hook is called after teardown
Aspects
instance var
dealloc
✅ hook dealloc method of SUT when
setup 

✅ record calling of the hook

✅ verify if hook is called after teardown
Aspects
instance var
XCTAssert
@interface ConverterViewControllerTests : XCTestCase {
ConverterViewController* sut;
BOOL _sutDeallocated;
}
@end
!
- (void)setUp {
[super setUp];
sut = [ConverterViewController new];
_sutDeallocated = NO;
[sut aspect_hookSelector:NSSelectorFromString(@"dealloc")
withOptions:AspectPositionBefore
usingBlock:^(id<AspectInfo> aspectInfo){
_sutDeallocated = YES;
} error:nil];
}
!
- (void)tearDown {
sut = nil;
XCTAssertTrue(_sutDeallocated, @"SUT is not deallocated");
[super tearDown];
}
dealloc
@interface
}
@end
!
- (
[
!
!
!
!
!
}
!
- (
[
}
dealloc
!
!
!
!
!
!
!
!
!
!
[sut aspect_hookSelector:NSSelectorFromString(@"dealloc")
withOptions:AspectPositionBefore
usingBlock:^(id<AspectInfo> aspectInfo){
_sutDeallocated = YES;
} error:nil];
UINavigationController
- test push view controller

- test pop view controller
UINavigationController
UINavigationController
But
UINavigationController
But
@interface UIViewController (UINavigationControllerItem)
!
@property(nonatomic,readonly,retain) UINavigationController*
navigationController;
!
@end
-(void)testTappingDetailsShouldDisplayDetails {
UINavigationController *nav = [[UINavigationController alloc]
initWithRootViewController:sut];
id mockNav = [OCMockObject partialMockForObject:nav];
[[mockNav expect] pushViewController:[OCMArg any]
animated:YES];
[sut onShowDetailsButton:nil];
[mockNav verify];
}
UINavigationController
Choosing not to test view controllers
is the decision not to test most of
your code.
UIViewController
Testing simple things is simple, and
testing complex things is complex
UIViewController
Block-based code
Why does test fail?
Block-based code
!
typedef void(^CompletionHandler)(NSArray * result);
!
- (void)runAsyncCode:(CompletionHandler)completion {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil);
});
}
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
Block-based code
What can we do?
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
!
!
!
!
!
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:0.1];
while([timeout timeIntervalSinceNow] > 0 && hasCalledBack == NO) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:timeout];
}
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
- (void)testRunAsyncCode {
// arrange
__block BOOL hasCalledBack = NO;
!
// act
[sut runAsyncCode:^(NSArray *result) {
hasCalledBack = YES;
}];
// assert
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:0.1];
while([timeout timeIntervalSinceNow] > 0 && hasCalledBack == NO) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:timeout];
}
XCTAssert(hasCalledBack, @"Test timed out");
}
Block-based code
Block-based code
Also we can use:
- (void)verifyWithDelay:(NSTimeInterval)delay
{
NSTimeInterval step = 0.01;
while(delay > 0)
{
if([expectations count] == 0)
break;
NSDate* until = [NSDate dateWithTimeIntervalSinceNow:step];
[[NSRunLoop currentRunLoop] runUntilDate:until];
delay -= step;
step *= 2;
}
[self verify];
}
OCMock
CoreData
CoreData
As long as you don't put business
logic in your models, you don't have
to test them.
CoreData
creates setters & getters in run-time
CoreData
creates setters & getters in run-time
we can’t mock CoreData models
CoreData
What can we do?
CoreData
- create protocol that has all model’s
properties defined
CoreData
- create protocol that has all model’s
properties defined

- conform NSManagedObject to the
protocol
CoreData
- create protocol that has all model’s
properties defined

- conform NSManagedObject to the
protocol

- create NSObject model just for
testing, conforms to the protocol
and @synthesize properties
CoreData
Protocol
Model<Protocol> TestModel<Protocol>
CoreData
Protocol
Model<Protocol> TestModel<Protocol>
CoreData
Have a better solution?
CoreData
Create own CoreData stack for each
test-case
- (void)setUp
{
[super setUp];
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"SimpleInvoice"
withExtension:@“momd"];
!
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc]
initWithContentsOfURL:modelURL];
!
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:mom];
!
XCTAssertNotNil([psc addPersistentStoreWithType:NSInMemoryStoreType
configuration:nil
URL:nil
options:nil
error:NULL], @"Should be able to
add in-memory store”);
!
_moc = [[NSManagedObjectContext alloc] init];
_moc.persistentStoreCoordinator = psc;
}
CoreData
- (void
{
[
!
initWithContentsOfURL
!
initWithManagedObjectModel
!
!
!
!
!
!
!
!
}
CoreData
- (void)setUp
{
!
!
!
!
!
!
!
!
!
!
XCTAssertNotNil([psc addPersistentStoreWithType:NSInMemoryStoreType
configuration:nil
URL:nil
options:nil
error:NULL], @"Should be able to
add in-memory store”);
!
!
!
}
CoreData
Advantages?
CoreData
Advantages?
- no additional classes
CoreData
Advantages?
- no additional classes

- no dependence on external state
CoreData
Advantages?
- no additional classes

- no dependence on external state

- close approximation to the
application environment
CoreData
Advantages?
- no additional classes

- no dependence on external state

- close approximation to the
application environment

- we are able to create base test
class with a stack and subclass it
where we need
CoreData
Advantages?
- no additional classes

- no dependence on external state

- close approximation to the
application environment

- we are able to create base test
class with a stack and subclass it
where we need
- (void)testFullNameReturnsСorrectString {
Person* ps;
ps = [NSEntityDescription insertNewObjectForEntityForName:@"Person"
inManagedObjectContext:_moc];
ps.firstName = @"Tom";
ps.lastName = @“Lol";
!
STAssertTrue([[ps fullName] isEqualToString:@"Lol Tom"],
@"should have matched full name");
}
CoreData
CoreData
- test model’s additional business-logic

- test ManagedObjectModel for an
entity

- create and use models as a mocks
✅ UIViewControllers

✅ Block-based code

✅ CoreData	

How to Test
Video is coming!
https://github.com/maksum
!
maksum.ko
contact me:
Sources
http://www.amazon.com/Test-Driven-iOS-Development-Developers-Library/dp/
0321774183
!
http://www.objc.io/issue-1/testing-view-controllers.html
http://www.silverbaytech.com/2013/02/25/ios-testing-part-3-testing-view-controller/
http://iosunittesting.com/unit-testing-view-controllers/
http://blog.carbonfive.com/2010/03/10/testing-view-controllers/
!
http://iosunittesting.com/how-to-unit-test-completion-blocks/
!
http://iosunittesting.com/unit-testing-core-data/
http://ashfurrow.com/blog/unit-testing-with-core-data-models
http://www.sicpers.info/2010/06/template-class-for-unit-testing-core-data-entities/
http://iamleeg.blogspot.com/2010/01/unit-testing-core-data-driven-apps-fit.html
Unit Testing: Special Cases

More Related Content

PDF
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
KEY
Unit testing en iOS @ MobileCon Galicia
PPTX
Understanding JavaScript Testing
RTF
Easy Button
PDF
GMock framework
PPT
2012 JDays Bad Tests Good Tests
PDF
Architecture for Massively Parallel HDL Simulations
PDF
Clean code via dependency injection + guice
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing en iOS @ MobileCon Galicia
Understanding JavaScript Testing
Easy Button
GMock framework
2012 JDays Bad Tests Good Tests
Architecture for Massively Parallel HDL Simulations
Clean code via dependency injection + guice

What's hot (20)

PDF
Rx java testing patterns
PDF
Testing the waters of iOS
PDF
Introduction to web programming for java and c# programmers by @drpicox
PDF
33rd Degree 2013, Bad Tests, Good Tests
PDF
Software Testing - Invited Lecture at UNSW Sydney
PDF
Stop Making Excuses and Start Testing Your JavaScript
PDF
10 Typical Problems in Enterprise Java Applications
PPT
Introduzione al TDD
PPTX
Qunit Java script Un
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
PDF
Java 7 LavaJUG
PDF
ReactJS for Programmers
PPTX
Code generation for alternative languages
PPTX
Unit testing patterns for concurrent code
PPTX
Building unit tests correctly
PDF
Tdd iPhone For Dummies
PDF
Agile Android
PDF
Agile Swift
PDF
Testing logging in asp dot net core
PPTX
Migrating to JUnit 5
Rx java testing patterns
Testing the waters of iOS
Introduction to web programming for java and c# programmers by @drpicox
33rd Degree 2013, Bad Tests, Good Tests
Software Testing - Invited Lecture at UNSW Sydney
Stop Making Excuses and Start Testing Your JavaScript
10 Typical Problems in Enterprise Java Applications
Introduzione al TDD
Qunit Java script Un
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 LavaJUG
ReactJS for Programmers
Code generation for alternative languages
Unit testing patterns for concurrent code
Building unit tests correctly
Tdd iPhone For Dummies
Agile Android
Agile Swift
Testing logging in asp dot net core
Migrating to JUnit 5
Ad

Similar to Unit Testing: Special Cases (20)

PDF
Swift testing ftw
PDF
TDD by Controlling Dependencies
PDF
Unit testing in xcode 8 with swift
PDF
Testing (eng)
PDF
The Cowardly Test-o-Phobe's Guide To Testing
PDF
iOS testing
PDF
Unit Tesing in iOS
PDF
iOS unit tests
PDF
2013-01-10 iOS testing
PDF
7 Stages of Unit Testing in iOS
PPT
Unit Testing in iOS
PDF
Cocoa heads testing and viewcontrollers
PPTX
Unit testing
PPTX
Unit test
PPTX
Secret unit testing tools no one ever told you about
PPTX
Type mock isolator
PPS
Unit testing_pps
PDF
[XCode] Automating UI Testing
KEY
Beginning iPhone Development
PPTX
An Introduction to Unit Testing
Swift testing ftw
TDD by Controlling Dependencies
Unit testing in xcode 8 with swift
Testing (eng)
The Cowardly Test-o-Phobe's Guide To Testing
iOS testing
Unit Tesing in iOS
iOS unit tests
2013-01-10 iOS testing
7 Stages of Unit Testing in iOS
Unit Testing in iOS
Cocoa heads testing and viewcontrollers
Unit testing
Unit test
Secret unit testing tools no one ever told you about
Type mock isolator
Unit testing_pps
[XCode] Automating UI Testing
Beginning iPhone Development
An Introduction to Unit Testing
Ad

More from Ciklum Ukraine (20)

PDF
"How keep normal blood pressure using TDD" By Roman Loparev
PDF
"Through the three circles of the it hell" by Roman Liashenko
PDF
Alex Pazhyn: Google_Material_Design
PPTX
Introduction to amazon web services for developers
PPTX
Your 1st Apple watch Application
PDF
Test Driven Development
PPTX
Back to the future: ux trends 2015
PPTX
Developing high load systems using C++
PPTX
Collection view layout
PPTX
Introduction to auto layout
PDF
Groovy on Android
PPTX
Material design
PPTX
Kanban development
PPTX
Mobile sketching
PDF
More UX in our life
PDF
Model-View-Controller: Tips&Tricks
PDF
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...
PDF
Михаил Попчук "Cкрытые резервы команд или 1+1=3"
PDF
"To be, rather than to seem” interview with Ciklum VP of HR Marina Vyshegorod...
PDF
Why to join Ciklum?
"How keep normal blood pressure using TDD" By Roman Loparev
"Through the three circles of the it hell" by Roman Liashenko
Alex Pazhyn: Google_Material_Design
Introduction to amazon web services for developers
Your 1st Apple watch Application
Test Driven Development
Back to the future: ux trends 2015
Developing high load systems using C++
Collection view layout
Introduction to auto layout
Groovy on Android
Material design
Kanban development
Mobile sketching
More UX in our life
Model-View-Controller: Tips&Tricks
Future of Outsourcing report published in The Times featuring Ciklum's CEO To...
Михаил Попчук "Cкрытые резервы команд или 1+1=3"
"To be, rather than to seem” interview with Ciklum VP of HR Marina Vyshegorod...
Why to join Ciklum?

Recently uploaded (20)

PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PPT
Teaching material agriculture food technology
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
Spectroscopy.pptx food analysis technology
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Machine learning based COVID-19 study performance prediction
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
Digital-Transformation-Roadmap-for-Companies.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
Teaching material agriculture food technology
Per capita expenditure prediction using model stacking based on satellite ima...
Understanding_Digital_Forensics_Presentation.pptx
Encapsulation_ Review paper, used for researhc scholars
Spectral efficient network and resource selection model in 5G networks
Reach Out and Touch Someone: Haptics and Empathic Computing
Programs and apps: productivity, graphics, security and other tools
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Spectroscopy.pptx food analysis technology
Unlocking AI with Model Context Protocol (MCP)
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Machine learning based COVID-19 study performance prediction
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Mobile App Security Testing_ A Comprehensive Guide.pdf
“AI and Expert System Decision Support & Business Intelligence Systems”
20250228 LYD VKU AI Blended-Learning.pptx

Unit Testing: Special Cases