SlideShare a Scribd company logo
iOS Testing
Derrick Chao @ Loopd
Frameworks
• XCTest
• OCMock
• KIF
XCTest
• XCTest is the testing framework in Xcode
• A test method is an instance method of a
test class that begins with the prefix test

- (void)testExample {
// This is an example of a functional test case.
XCTAssert(YES, @"Pass");
XCTAssert(1+1==2);
XCTAssertTrue(1+1==2);
XCTAssertFalse(1+1==3);
}
• XCTAssert
XCTAssert(expression, …);
XCTAssertTrue(expression, …);
XCTAssertFalse(expression, ...);
Unit Test Example
- (void)testValidatePassword {
NSString *password1 = @"AbCd1234";
NSString *password2 = @"AbCd12";
NSString *password3 = @"ABCD";
NSString *password4 = @"AbCd1";
NSString *password5 = @"";
XCTAssertTrue([Helper validatePassword:password1]);
XCTAssertTrue([Helper validatePassword:password2]);
XCTAssertFalse([Helper validatePassword:password3]);
XCTAssertFalse([Helper validatePassword:password4]);
XCTAssertFalse([Helper validatePassword:password5]);
}
Test Async Function
Example
• send a message to another user
• async
• block callback
Test Async Function
Example
- (void)testSendMessageWithNilMessage {
XCTestExpectation *expectation =
[self expectationWithDescription:@"completion should be called"];
[Message sendMessage:nil recipientInfo:nil completion:^(id responseObject, NSError
*error) {
[expectation fulfill];
XCTAssertNotNil(error);
XCTAssert([error.userInfo[@"message"] isEqualToString:@"message can't be
nil"]);
}];
[self waitForExpectationsWithTimeout:2 handler:nil];
}
Singleton
// LoopdManager.h file
+ (instancetype)sharedManager;
// LoopdManager.m file
+ (instancetype)sharedManager {
static dispatch_once_t onceToken;
static LoopdManager *sharedInstance;
dispatch_once(&onceToken, ^{
sharedInstance = [[LoopdManager alloc] init];
});
return sharedInstance;
}
Test Singleton Example
- (void)testSharedManager {
LoopdManager *manager1 = [LoopdManager sharedManager];
LoopdManager *manager2 = [LoopdManager sharedManager];
LoopdManager *manager3 = [LoopdManager new];
XCTAssertNotNil(manager1);
XCTAssertNotNil(manager2);
XCTAssertEqual(manager1, manager2);
XCTAssertNotEqual(manager1, manager3);
}
OCMock
• mock objects are simulated objects that mimic the
behavior of real objects in controlled ways

- (void)testMock {
id mockUserInfo = OCMClassMock([UserInfo class]);
// fullname should be nil for now
XCTAssertNil([mockUserInfo fullname]);
// make a custom return value
OCMStub([mockUserInfo fullname]).andReturn(@"David");
// fullname should be David now
XCTAssert([[mockUserInfo fullname] isEqualToString:@"David"]);
}
OCMock Example (1)
ListViewController has a collection view
find all SomeModel from server when viewDidLoad
// in SomeModel.h file

@interface SomeModel : ModelObject
+ (void)findAllByCurrentUserId:(NSString *)currentUserId
completion:(ArrayResultBlock)completion;
@end
OCMock Example (2)
- (void)testCollectionViewCellNumber {
id mockSomeModel = OCMClassMock([SomeModel class]);
OCMStub([mockSomeModel findAllRelationshipsByCurrentUserId:[OCMArg any]
completion:[OCMArg
any]]).andDo(^(NSInvocation *invocation) {
ArrayResultBlock completion;
[invocation getArgument:&completion atIndex: 3];
NSArray *someModels = @[@“1”, @“2”, @“3”, @“4”, @“5”];
completion(someModels, nil);
});
ListViewController *listVC = [ListViewController new];
listVC.view;
NSInteger num = [listVC collectionView:nil numberOfItemsInSection:0];
XCTAssert(num == 5);
XCTAssert(num != 6);
}
KIF
• KIF iOS Integration Testing Framework


Testing (eng)
KIF Example
@interface UITests : KIFTestCase
@end
@implementation UITests
- (void)testLoginSteps {
[tester tapViewWithAccessibilityLabel:@"regular_button"];
[tester enterText:@"123@123.com" intoViewWithAccessibilityLabel:@"emailTextField"];
[tester enterText:@"abcdefg" intoViewWithAccessibilityLabel:@"passwordTextField"];
[tester tapViewWithAccessibilityLabel:@“checkmark_button"];
}
@end
MVC & MVP
MVC
• view can retrieve data
from model directly
• view hosts all the UI
controls
• high coupling
MVC & MVP
MVP
• MVP is a derivation of the
MVC architectural pattern
• view can’t retrieve data from
model directly
• low coupling
MVP's advantage
• easier to unit test, clean
separation of the View and Model
• maintainability of UI increases
due to almost no dependency on
business logic
• Usually view to presenter map
one to one. Complex views may
have multi presenters
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView
dequeueReusableCellWithReuseIdentifier:@"Cell"
forIndexPath:indexPath];
// config cell
Car *car = self.cars[indexPath.item];
cell.makeLabel.text = car.make;
cell.modelLabel.text = car.model;
cell.yearLabel.text = car.year;
cell.detailLabel.text = car.detail;
return cell;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView
dequeueReusableCellWithReuseIdentifier:@"Cell"
forIndexPath:indexPath];
// config cell
Car *car = self.cars[indexPath.item];
cell.car = car;
[cell showUI];
return cell;
}
Testing (eng)
Test Cell
- (void)testCollectionViewCellNumber {
id mockSomeModel = OCMClassMock([SomeModel class]);
OCMStub([mockSomeModel findAllRelationshipsByCurrentUserId:[OCMArg any]
completion:[OCMArg
any]]).andDo(^(NSInvocation *invocation) {
ArrayResultBlock completion;
[invocation getArgument:&completion atIndex: 3];
NSArray *someModels = @[mod1, mod2, mod3, mod4, mod5];
completion(someModels, nil);
});
ListViewController *listVC = [ListViewController new];
listVC.view;
NSInteger num = [listVC collectionView:nil numberOfItemsInSection:0];
XCTAssert(num == 5);
XCTAssert(num != 6);
UICollectionViewCell *cell = [contactListVC collectionView:nil
cellForItemAtIndexPath:0];
}
Testing (eng)
Testing (eng)
Spike Solution
Spike Solution
• not sure how to achieve some
requirement.
Spike Solution (2)
• A spike solution is dirty and quick.
Code just enough to get the answer
you need.
• Throw it away when you’re done with
it.
Spike Solution (3)
• open a new branch
• do some test in the branch
• Throw it away when you’re done with
it
TDD with Xcode
• requirement: a helper for add two
integers
TDD with Xcode (2)
• create files
TDD with Xcode (3)
TDD with Xcode (4)
• command+u
TDD with Xcode (5)
• verify the function
TDD with Xcode (6)
• finish the function then test again
how I feel for TDD at
beginning
benefits of Testing/TDD
• test => spec
• saves you development time
• saves you development time
• Good unit testing forces good
architecture.  In order to make your
code unit-testable, it must be properly
modularized, by writing the unit
testing first various architectural
problems tend to surface earlier
The End
references
• http://iosunittesting.com
• http://stackoverflow.com/questions/
1053406/why-does-apple-say-iphone-
apps-use-mvc
• http://blog.sanc.idv.tw/2011/09/uimvp-
passive-view.html

More Related Content

PDF
iOS Testing
PDF
Live Updating Swift Code
PDF
COScheduler In Depth
PPTX
How Data Flow analysis works in a static code analyzer
PDF
Head First Java Chapter 1
PDF
ActiveRecord Query Interface (1), Season 1
PDF
JDK Power Tools
PDF
PVS-Studio in 2021 - Error Examples
iOS Testing
Live Updating Swift Code
COScheduler In Depth
How Data Flow analysis works in a static code analyzer
Head First Java Chapter 1
ActiveRecord Query Interface (1), Season 1
JDK Power Tools
PVS-Studio in 2021 - Error Examples

What's hot (20)

PDF
Server1
PPTX
The zen of async: Best practices for best performance
DOCX
201913046 wahyu septiansyah network programing
PPTX
Introduction to Unit Testing (Part 2 of 2)
PDF
Обзор фреймворка Twisted
PDF
The Ring programming language version 1.6 book - Part 29 of 189
DOCX
Exception Handling in Scala
PDF
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
PPTX
Down to Stack Traces, up from Heap Dumps
PDF
Spock framework
PPTX
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"
PDF
Spockを使おう!
PPTX
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
PDF
ES3-2020-07 Testing techniques
PDF
Writing beautiful code with Java 8
PPTX
Javascript Execution Context Flow
PDF
Cascadia.js: Don't Cross the Streams
PPTX
Mastering Java Bytecode With ASM - 33rd degree, 2012
PDF
Everything you wanted to know about Stack Traces and Heap Dumps
Server1
The zen of async: Best practices for best performance
201913046 wahyu septiansyah network programing
Introduction to Unit Testing (Part 2 of 2)
Обзор фреймворка Twisted
The Ring programming language version 1.6 book - Part 29 of 189
Exception Handling in Scala
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
Down to Stack Traces, up from Heap Dumps
Spock framework
Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"
Spockを使おう!
#ITsubbotnik Spring 2017: Roman Iovlev "Java edge in test automation"
ES3-2020-07 Testing techniques
Writing beautiful code with Java 8
Javascript Execution Context Flow
Cascadia.js: Don't Cross the Streams
Mastering Java Bytecode With ASM - 33rd degree, 2012
Everything you wanted to know about Stack Traces and Heap Dumps
Ad

Similar to Testing (eng) (20)

PDF
Unit Testing: Special Cases
KEY
Runtime
KEY
連邦の白いヤツ 「Objective-C」
PDF
iOS testing
KEY
Agile Iphone Development
PDF
Pavel kravchenko obj c runtime
PDF
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
KEY
Taking a Test Drive
PDF
Building stable testing by isolating network layer
PPTX
Unit testing patterns for concurrent code
PDF
Tdd iPhone For Dummies
PPTX
J unit스터디슬라이드
KEY
openFrameworks 007 - 3D
PDF
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
PPT
SQL Server 2005 CLR Integration
DOCX
C-Sharp Arithmatic Expression Calculator
PPTX
NSOperation objective-c
PDF
Writing native bindings to node.js in C++
PPTX
Objective-c Runtime
PDF
greenDAO
Unit Testing: Special Cases
Runtime
連邦の白いヤツ 「Objective-C」
iOS testing
Agile Iphone Development
Pavel kravchenko obj c runtime
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
Taking a Test Drive
Building stable testing by isolating network layer
Unit testing patterns for concurrent code
Tdd iPhone For Dummies
J unit스터디슬라이드
openFrameworks 007 - 3D
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
SQL Server 2005 CLR Integration
C-Sharp Arithmatic Expression Calculator
NSOperation objective-c
Writing native bindings to node.js in C++
Objective-c Runtime
greenDAO
Ad

Recently uploaded (20)

PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PDF
R24 SURVEYING LAB MANUAL for civil enggi
PDF
Model Code of Practice - Construction Work - 21102022 .pdf
PDF
PPT on Performance Review to get promotions
PDF
737-MAX_SRG.pdf student reference guides
PPT
Project quality management in manufacturing
PPTX
Geodesy 1.pptx...............................................
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
DOCX
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
PPTX
Fundamentals of safety and accident prevention -final (1).pptx
PPTX
additive manufacturing of ss316l using mig welding
PPTX
Construction Project Organization Group 2.pptx
PPTX
OOP with Java - Java Introduction (Basics)
PPTX
CYBER-CRIMES AND SECURITY A guide to understanding
PDF
Embodied AI: Ushering in the Next Era of Intelligent Systems
PDF
Operating System & Kernel Study Guide-1 - converted.pdf
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PDF
Well-logging-methods_new................
PDF
SM_6th-Sem__Cse_Internet-of-Things.pdf IOT
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
R24 SURVEYING LAB MANUAL for civil enggi
Model Code of Practice - Construction Work - 21102022 .pdf
PPT on Performance Review to get promotions
737-MAX_SRG.pdf student reference guides
Project quality management in manufacturing
Geodesy 1.pptx...............................................
Foundation to blockchain - A guide to Blockchain Tech
UNIT-1 - COAL BASED THERMAL POWER PLANTS
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
Fundamentals of safety and accident prevention -final (1).pptx
additive manufacturing of ss316l using mig welding
Construction Project Organization Group 2.pptx
OOP with Java - Java Introduction (Basics)
CYBER-CRIMES AND SECURITY A guide to understanding
Embodied AI: Ushering in the Next Era of Intelligent Systems
Operating System & Kernel Study Guide-1 - converted.pdf
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
Well-logging-methods_new................
SM_6th-Sem__Cse_Internet-of-Things.pdf IOT

Testing (eng)

  • 3. XCTest • XCTest is the testing framework in Xcode • A test method is an instance method of a test class that begins with the prefix test
 - (void)testExample { // This is an example of a functional test case. XCTAssert(YES, @"Pass"); XCTAssert(1+1==2); XCTAssertTrue(1+1==2); XCTAssertFalse(1+1==3); } • XCTAssert XCTAssert(expression, …); XCTAssertTrue(expression, …); XCTAssertFalse(expression, ...);
  • 4. Unit Test Example - (void)testValidatePassword { NSString *password1 = @"AbCd1234"; NSString *password2 = @"AbCd12"; NSString *password3 = @"ABCD"; NSString *password4 = @"AbCd1"; NSString *password5 = @""; XCTAssertTrue([Helper validatePassword:password1]); XCTAssertTrue([Helper validatePassword:password2]); XCTAssertFalse([Helper validatePassword:password3]); XCTAssertFalse([Helper validatePassword:password4]); XCTAssertFalse([Helper validatePassword:password5]); }
  • 5. Test Async Function Example • send a message to another user • async • block callback
  • 6. Test Async Function Example - (void)testSendMessageWithNilMessage { XCTestExpectation *expectation = [self expectationWithDescription:@"completion should be called"]; [Message sendMessage:nil recipientInfo:nil completion:^(id responseObject, NSError *error) { [expectation fulfill]; XCTAssertNotNil(error); XCTAssert([error.userInfo[@"message"] isEqualToString:@"message can't be nil"]); }]; [self waitForExpectationsWithTimeout:2 handler:nil]; }
  • 7. Singleton // LoopdManager.h file + (instancetype)sharedManager; // LoopdManager.m file + (instancetype)sharedManager { static dispatch_once_t onceToken; static LoopdManager *sharedInstance; dispatch_once(&onceToken, ^{ sharedInstance = [[LoopdManager alloc] init]; }); return sharedInstance; }
  • 8. Test Singleton Example - (void)testSharedManager { LoopdManager *manager1 = [LoopdManager sharedManager]; LoopdManager *manager2 = [LoopdManager sharedManager]; LoopdManager *manager3 = [LoopdManager new]; XCTAssertNotNil(manager1); XCTAssertNotNil(manager2); XCTAssertEqual(manager1, manager2); XCTAssertNotEqual(manager1, manager3); }
  • 9. OCMock • mock objects are simulated objects that mimic the behavior of real objects in controlled ways
 - (void)testMock { id mockUserInfo = OCMClassMock([UserInfo class]); // fullname should be nil for now XCTAssertNil([mockUserInfo fullname]); // make a custom return value OCMStub([mockUserInfo fullname]).andReturn(@"David"); // fullname should be David now XCTAssert([[mockUserInfo fullname] isEqualToString:@"David"]); }
  • 10. OCMock Example (1) ListViewController has a collection view find all SomeModel from server when viewDidLoad // in SomeModel.h file
 @interface SomeModel : ModelObject + (void)findAllByCurrentUserId:(NSString *)currentUserId completion:(ArrayResultBlock)completion; @end
  • 11. OCMock Example (2) - (void)testCollectionViewCellNumber { id mockSomeModel = OCMClassMock([SomeModel class]); OCMStub([mockSomeModel findAllRelationshipsByCurrentUserId:[OCMArg any] completion:[OCMArg any]]).andDo(^(NSInvocation *invocation) { ArrayResultBlock completion; [invocation getArgument:&completion atIndex: 3]; NSArray *someModels = @[@“1”, @“2”, @“3”, @“4”, @“5”]; completion(someModels, nil); }); ListViewController *listVC = [ListViewController new]; listVC.view; NSInteger num = [listVC collectionView:nil numberOfItemsInSection:0]; XCTAssert(num == 5); XCTAssert(num != 6); }
  • 12. KIF • KIF iOS Integration Testing Framework 

  • 14. KIF Example @interface UITests : KIFTestCase @end @implementation UITests - (void)testLoginSteps { [tester tapViewWithAccessibilityLabel:@"regular_button"]; [tester enterText:@"123@123.com" intoViewWithAccessibilityLabel:@"emailTextField"]; [tester enterText:@"abcdefg" intoViewWithAccessibilityLabel:@"passwordTextField"]; [tester tapViewWithAccessibilityLabel:@“checkmark_button"]; } @end
  • 16. MVC • view can retrieve data from model directly • view hosts all the UI controls • high coupling
  • 18. MVP • MVP is a derivation of the MVC architectural pattern • view can’t retrieve data from model directly • low coupling
  • 19. MVP's advantage • easier to unit test, clean separation of the View and Model • maintainability of UI increases due to almost no dependency on business logic • Usually view to presenter map one to one. Complex views may have multi presenters
  • 20. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath]; // config cell Car *car = self.cars[indexPath.item]; cell.makeLabel.text = car.make; cell.modelLabel.text = car.model; cell.yearLabel.text = car.year; cell.detailLabel.text = car.detail; return cell; }
  • 21. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath]; // config cell Car *car = self.cars[indexPath.item]; cell.car = car; [cell showUI]; return cell; }
  • 23. Test Cell - (void)testCollectionViewCellNumber { id mockSomeModel = OCMClassMock([SomeModel class]); OCMStub([mockSomeModel findAllRelationshipsByCurrentUserId:[OCMArg any] completion:[OCMArg any]]).andDo(^(NSInvocation *invocation) { ArrayResultBlock completion; [invocation getArgument:&completion atIndex: 3]; NSArray *someModels = @[mod1, mod2, mod3, mod4, mod5]; completion(someModels, nil); }); ListViewController *listVC = [ListViewController new]; listVC.view; NSInteger num = [listVC collectionView:nil numberOfItemsInSection:0]; XCTAssert(num == 5); XCTAssert(num != 6); UICollectionViewCell *cell = [contactListVC collectionView:nil cellForItemAtIndexPath:0]; }
  • 27. Spike Solution • not sure how to achieve some requirement.
  • 28. Spike Solution (2) • A spike solution is dirty and quick. Code just enough to get the answer you need. • Throw it away when you’re done with it.
  • 29. Spike Solution (3) • open a new branch • do some test in the branch • Throw it away when you’re done with it
  • 30. TDD with Xcode • requirement: a helper for add two integers
  • 31. TDD with Xcode (2) • create files
  • 33. TDD with Xcode (4) • command+u
  • 34. TDD with Xcode (5) • verify the function
  • 35. TDD with Xcode (6) • finish the function then test again
  • 36. how I feel for TDD at beginning
  • 37. benefits of Testing/TDD • test => spec • saves you development time • saves you development time • Good unit testing forces good architecture.  In order to make your code unit-testable, it must be properly modularized, by writing the unit testing first various architectural problems tend to surface earlier