SlideShare una empresa de Scribd logo
1 de 36
Descargar para leer sin conexión
Testing in iOS
10.01.2013 by Tomasz Janeczko
About me
Tomasz Janeczko
• iOS developer in Kainos
• Enthusiast of business, electronics, Rails
  & Heroku
• Organizer of first App Camp in UK and
  PL
So let’s talk about testing.
Why we test?
So?
• Reliability

• Regression

• Confidence (e.g. refactoring)
Why not to test?
Why not to test?


• Heavy dependence on UI
• Non-testable code
• Bad framework
How to address issues


• Sample - downloading stuff from
  interwebz
First fault


Writing tests after
writing code
Separation of concerns
Separation of concerns


• Let’s separate out the UI code
• Same for services interaction
Demo of tests
Writing tests
Meet Kiwi and OCMock
Kiwi


• RSpec-like tests writing
• Matchers
• Cleaner and more self-descriptive code
Kiwi

  describe(@"Tested class", ^{

      context(@"When created", ^{

            it(@"should not fail", ^{
                [[theValue(0) should] equal:theValue(0)];
            });

      });

});
Kiwi

describe(@"Tested class", ^{

      context(@"When created", ^{

        it(@"should not fail", ^{
            id viewController = [ViewController new];
            [[viewController should]
conformToProtocol:@protocol(UITableViewDelegate)];
        });

      });

});
Matchers
  [subject	
  shouldNotBeNil]

• [subject	
  shouldBeNil]

• [[subject	
  should]	
  beIdenticalTo:(id)anObject] - compares id's

• [[subject	
  should]	
  equal:(id)anObject]

• [[subject	
  should]	
  equal:(double)aValue	
  withDelta:
  (double)aDelta]

• [[subject	
  should]	
  beWithin:(id)aDistance	
  of:(id)aValue]

• [[subject	
  should]	
  beLessThan:(id)aValue]

• etc.	
  etc.
Compare to SenTesting Kit


               [[subject	
  should]	
  equal:anObject]


                            compare	
  with


   STAssertEquals(subject,	
  anObject,	
  @”Should	
  be	
  equal”);
OCMock


• Mocking and stubbing library for iOS
• Quite versatile
• Makes use of NSProxy magic
Sample workflows
Classic calculator sample
                describe(@"Calculator",	
  ^{	
  	
  	
  	
  
 	
  	
  	
  	
  context(@"with	
  the	
  numbers	
  60	
  and	
  5	
  entered",	
  ^{
 	
  	
  	
  	
  	
  	
  	
  	
  RPNCalculator	
  *calculator	
  =	
  [[RPNCalculator	
  alloc]	
  init];	
  	
  	
  	
  	
  	
  	
  	
  
 	
  	
  	
  	
  	
  	
  	
  	
  beforeEach(^{
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [calculator	
  enter:60];
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [calculator	
  enter:5];
 	
  	
  	
  	
  	
  	
  	
  	
  });

 	
  	
  	
  	
  	
  	
  	
  	
  afterEach(^{	
  

 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [calculator	
  clear];
 	
  	
  	
  	
  	
  	
  	
  	
  });
 	
  	
  	
  	
  	
  	
  	
  
 	
  	
  	
  	
  	
  	
  	
  	
  it(@"returns	
  65	
  as	
  the	
  sum",	
  ^{
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [[theValue([calculator	
  add])	
  should]	
  equal:65	
  withDelta:.01];
 	
  	
  	
  	
  	
  	
  	
  	
  });
Test if calls dep methods

 1. Create a mock dependency
 2. Inject it
 3. Call the method
 4. Verify
Test dependency

// Create the tested object and mock to exchange part of the functionality
viewController = [ViewController new];
mockController = [OCMockObject partialMockForObject:viewController];

// Create the mock and change implementation to return our class
id serviceMock = [OCMockObject mockForClass:[InterwebzService class]];
[[[mockController stub] andReturn:serviceMock] service];

// Define expectations
[[serviceMock expect] downloadTweetsJSONWithSuccessBlock:[OCMArg any]];

// Run the tested method
[viewController tweetsButtonTapped:nil];

// Verify - throws exception on failure
[mockController verify];
Testing one layer

• Isolate dependencies
• Objective-C is highly dynamic - we can
  change implementations of private
  methods or static methods
• We can avoid IoC containers for testing
Accessing private methods
Accessing private methods

 @interface ViewController()

 - (void)startDownloadingTweets;

 @end



 ...
 [[mockController expect] startDownloadingTweets];
Static method testing

• Through separation to a method
@interface ViewController()

- (NSUserDefaults *)userDefaults;

@end

...

id mockDefaults = [OCMockObject mockForClass:[NSUserDefaults class]];

[[[mockDefaults expect] andReturn:@"Setting"] valueForKey:[OCMArg any]];

[[[mockController stub] andReturn:mockDefaults] userDefaults];
Static method testing

• Through method swizzling
void	
  SwizzleClassMethod(Class	
  c,	
  SEL	
  orig,	
  SEL	
  new)	
  {

	
  	
  	
  	
  Method	
  origMethod	
  =	
  class_getClassMethod(c,	
  orig);
	
  	
  	
  	
  Method	
  newMethod	
  =	
  class_getClassMethod(c,	
  new);

	
  	
  	
  	
  c	
  =	
  object_getClass((id)c);

	
  	
  	
  	
  if(class_addMethod(c,	
  orig,	
  method_getImplementation(newMethod),	
  method_getTypeEncoding(newMethod)))
	
  	
  	
  	
  	
  	
  	
  	
  class_replaceMethod(c,	
  new,	
  method_getImplementation(origMethod),	
  
method_getTypeEncoding(origMethod));
	
  	
  	
  	
  else
	
  	
  	
  	
  	
  	
  	
  	
  method_exchangeImplementations(origMethod,	
  newMethod);
}
Normal conditions apply
   despite it’s iOS & Objective--C
Problems of „mobile devs”


 • Pushing code with failing tests
 • Lot’s of hacking together
 • Weak knowledge of VCS tools - merge
   nightmares
Ending thoughts
• Think first (twice), then code :)
• Tests should come first
• Write the failing test, pass the test,
  refactor
• Adequate tools can enhance your
  testing experience
Ending thoughts



• Practice!
Thanks!
Questions

Más contenido relacionado

La actualidad más candente

Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, Ciklum
Alina Vilk
 

La actualidad más candente (19)

React&redux
React&reduxReact&redux
React&redux
 
Jquery- One slide completing all JQuery
Jquery- One slide completing all JQueryJquery- One slide completing all JQuery
Jquery- One slide completing all JQuery
 
Barcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentationBarcamp Auckland Rails3 presentation
Barcamp Auckland Rails3 presentation
 
Angular js 2.0, ng poznań 20.11
Angular js 2.0, ng poznań 20.11Angular js 2.0, ng poznań 20.11
Angular js 2.0, ng poznań 20.11
 
React with Redux
React with ReduxReact with Redux
React with Redux
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
 
Deep Dive into React Hooks
Deep Dive into React HooksDeep Dive into React Hooks
Deep Dive into React Hooks
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with Redux
 
20131004 - Sq lite sample by Jax
20131004 - Sq lite sample by Jax20131004 - Sq lite sample by Jax
20131004 - Sq lite sample by Jax
 
Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, Ciklum
 
ECS19 - Edin Kapic - WHO IS THAT? DEVELOPING AI-ASSISTED EMPLOYEE IMAGE TAGGING
ECS19 - Edin Kapic - WHO IS THAT? DEVELOPING AI-ASSISTED EMPLOYEE IMAGE TAGGINGECS19 - Edin Kapic - WHO IS THAT? DEVELOPING AI-ASSISTED EMPLOYEE IMAGE TAGGING
ECS19 - Edin Kapic - WHO IS THAT? DEVELOPING AI-ASSISTED EMPLOYEE IMAGE TAGGING
 
Javascript talk
Javascript talkJavascript talk
Javascript talk
 
Tdd iPhone For Dummies
Tdd iPhone For DummiesTdd iPhone For Dummies
Tdd iPhone For Dummies
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
Extending C# with Roslyn and Code Aware Libraries
Extending C# with Roslyn and Code Aware LibrariesExtending C# with Roslyn and Code Aware Libraries
Extending C# with Roslyn and Code Aware Libraries
 
C#
C#C#
C#
 
Redux training
Redux trainingRedux training
Redux training
 
Getting Comfortable with JS Promises
Getting Comfortable with JS PromisesGetting Comfortable with JS Promises
Getting Comfortable with JS Promises
 

Similar a iOS testing

谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability
drewz lin
 
Testing for Pragmatic People
Testing for Pragmatic PeopleTesting for Pragmatic People
Testing for Pragmatic People
davismr
 
SQL Server 2005 CLR Integration
SQL Server 2005 CLR IntegrationSQL Server 2005 CLR Integration
SQL Server 2005 CLR Integration
webhostingguy
 

Similar a iOS testing (20)

2013-01-10 iOS testing
2013-01-10 iOS testing2013-01-10 iOS testing
2013-01-10 iOS testing
 
iOS 101 - Xcode, Objective-C, iOS APIs
iOS 101 - Xcode, Objective-C, iOS APIsiOS 101 - Xcode, Objective-C, iOS APIs
iOS 101 - Xcode, Objective-C, iOS APIs
 
10 tips for a reusable architecture
10 tips for a reusable architecture10 tips for a reusable architecture
10 tips for a reusable architecture
 
Building stable testing by isolating network layer
Building stable testing by isolating network layerBuilding stable testing by isolating network layer
Building stable testing by isolating network layer
 
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
 
Model View Presenter presentation
Model View Presenter presentationModel View Presenter presentation
Model View Presenter presentation
 
Describe's Full of It's
Describe's Full of It'sDescribe's Full of It's
Describe's Full of It's
 
Legacy Code Kata v3.0
Legacy Code Kata v3.0Legacy Code Kata v3.0
Legacy Code Kata v3.0
 
谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability
 
Dsug 05 02-15 - ScalDI - lightweight DI in Scala
Dsug 05 02-15 - ScalDI - lightweight DI in ScalaDsug 05 02-15 - ScalDI - lightweight DI in Scala
Dsug 05 02-15 - ScalDI - lightweight DI in Scala
 
From mvc to viper
From mvc to viperFrom mvc to viper
From mvc to viper
 
Frontend training
Frontend trainingFrontend training
Frontend training
 
Web technologies-course 12.pptx
Web technologies-course 12.pptxWeb technologies-course 12.pptx
Web technologies-course 12.pptx
 
Testing for Pragmatic People
Testing for Pragmatic PeopleTesting for Pragmatic People
Testing for Pragmatic People
 
Intro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJSIntro to Unit Testing in AngularJS
Intro to Unit Testing in AngularJS
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgets
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using Ruby
 
SQL Server 2005 CLR Integration
SQL Server 2005 CLR IntegrationSQL Server 2005 CLR Integration
SQL Server 2005 CLR Integration
 

Último

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Último (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 

iOS testing

  • 1. Testing in iOS 10.01.2013 by Tomasz Janeczko
  • 2. About me Tomasz Janeczko • iOS developer in Kainos • Enthusiast of business, electronics, Rails & Heroku • Organizer of first App Camp in UK and PL
  • 3. So let’s talk about testing.
  • 5.
  • 6. So?
  • 7. • Reliability • Regression • Confidence (e.g. refactoring)
  • 8. Why not to test?
  • 9. Why not to test? • Heavy dependence on UI • Non-testable code • Bad framework
  • 10. How to address issues • Sample - downloading stuff from interwebz
  • 11. First fault Writing tests after writing code
  • 13. Separation of concerns • Let’s separate out the UI code • Same for services interaction
  • 16. Kiwi • RSpec-like tests writing • Matchers • Cleaner and more self-descriptive code
  • 17. Kiwi describe(@"Tested class", ^{ context(@"When created", ^{ it(@"should not fail", ^{ [[theValue(0) should] equal:theValue(0)]; }); }); });
  • 18. Kiwi describe(@"Tested class", ^{ context(@"When created", ^{ it(@"should not fail", ^{ id viewController = [ViewController new]; [[viewController should] conformToProtocol:@protocol(UITableViewDelegate)]; }); }); });
  • 19. Matchers [subject  shouldNotBeNil] • [subject  shouldBeNil] • [[subject  should]  beIdenticalTo:(id)anObject] - compares id's • [[subject  should]  equal:(id)anObject] • [[subject  should]  equal:(double)aValue  withDelta: (double)aDelta] • [[subject  should]  beWithin:(id)aDistance  of:(id)aValue] • [[subject  should]  beLessThan:(id)aValue] • etc.  etc.
  • 20. Compare to SenTesting Kit [[subject  should]  equal:anObject] compare  with STAssertEquals(subject,  anObject,  @”Should  be  equal”);
  • 21. OCMock • Mocking and stubbing library for iOS • Quite versatile • Makes use of NSProxy magic
  • 23. Classic calculator sample describe(@"Calculator",  ^{                context(@"with  the  numbers  60  and  5  entered",  ^{                RPNCalculator  *calculator  =  [[RPNCalculator  alloc]  init];                                beforeEach(^{                        [calculator  enter:60];                        [calculator  enter:5];                });                afterEach(^{                          [calculator  clear];                });                              it(@"returns  65  as  the  sum",  ^{                        [[theValue([calculator  add])  should]  equal:65  withDelta:.01];                });
  • 24. Test if calls dep methods 1. Create a mock dependency 2. Inject it 3. Call the method 4. Verify
  • 25. Test dependency // Create the tested object and mock to exchange part of the functionality viewController = [ViewController new]; mockController = [OCMockObject partialMockForObject:viewController]; // Create the mock and change implementation to return our class id serviceMock = [OCMockObject mockForClass:[InterwebzService class]]; [[[mockController stub] andReturn:serviceMock] service]; // Define expectations [[serviceMock expect] downloadTweetsJSONWithSuccessBlock:[OCMArg any]]; // Run the tested method [viewController tweetsButtonTapped:nil]; // Verify - throws exception on failure [mockController verify];
  • 26. Testing one layer • Isolate dependencies • Objective-C is highly dynamic - we can change implementations of private methods or static methods • We can avoid IoC containers for testing
  • 28. Accessing private methods @interface ViewController() - (void)startDownloadingTweets; @end ... [[mockController expect] startDownloadingTweets];
  • 29. Static method testing • Through separation to a method @interface ViewController() - (NSUserDefaults *)userDefaults; @end ... id mockDefaults = [OCMockObject mockForClass:[NSUserDefaults class]]; [[[mockDefaults expect] andReturn:@"Setting"] valueForKey:[OCMArg any]]; [[[mockController stub] andReturn:mockDefaults] userDefaults];
  • 30. Static method testing • Through method swizzling void  SwizzleClassMethod(Class  c,  SEL  orig,  SEL  new)  {        Method  origMethod  =  class_getClassMethod(c,  orig);        Method  newMethod  =  class_getClassMethod(c,  new);        c  =  object_getClass((id)c);        if(class_addMethod(c,  orig,  method_getImplementation(newMethod),  method_getTypeEncoding(newMethod)))                class_replaceMethod(c,  new,  method_getImplementation(origMethod),   method_getTypeEncoding(origMethod));        else                method_exchangeImplementations(origMethod,  newMethod); }
  • 31. Normal conditions apply despite it’s iOS & Objective--C
  • 32. Problems of „mobile devs” • Pushing code with failing tests • Lot’s of hacking together • Weak knowledge of VCS tools - merge nightmares
  • 33. Ending thoughts • Think first (twice), then code :) • Tests should come first • Write the failing test, pass the test, refactor • Adequate tools can enhance your testing experience