iOS Unit Testing

6,320 views

Published on

A talk about unit testing for iOS apps. Part rambling introduction to test driven development, part examples of certain types of tests for iOS, and a brief mention of writing your tests using Kiwi.

Published in: Technology, Education
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,320
On SlideShare
0
From Embeds
0
Number of Embeds
1,033
Actions
Shares
0
Downloads
117
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide
  • \n
  • - what is unit testing\n- introduction to ocunit in general\n
  • - what is unit testing\n- introduction to ocunit in general\n
  • - what is unit testing\n- introduction to ocunit in general\n
  • - what is unit testing\n- introduction to ocunit in general\n
  • - Frank talk at the first cocoaheads of the year in February\n- thanks to Oliver for editing and uploading video\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - balance your tests (Kevin doesn’t like this picture)\n- the unit tests are the work horse of your test suite\n- unit = translation unit in compiler speak\n- unit tests don’t talk to network, disk, database, Interface Builder\n(the unit testing tools can also be used to write tests for these things,\nbut let’s not call them unit tests)\n- xUnit v RSpec style tests\n
  • - this is partly true, but it’s hard to effectively test the whole app\n- need to look at the cost of testing\n-> time to write a test, time to fix a bug when it breaks\n-> want small, focused tests (understand 10 lines of code to fix the bug)\n- unit test boundary conditions / error cases (eg server rubbish)\n- can test things that are unlikely to come up in normal usage but are possible\n
  • - fallacy of unit testing is that it’s just about asserting behaviour or preventing bugs\n-> bigger benefit is about the design of your code\n- need to write your tests first to leverage this\n- want code with low coupling and high cohesion (that makes it easy to test)\n- doesn’t magically make you write good code, but bad code is hard to test\n- want reusable code (code fights being reused a second time)\n- keeps you from writing unnecessary code\n
  • - entire unit test suite should take seconds to run\n- if you can’t hold your breath while your test suite runs, don’t hold your breath that anyone will run it\n- specific errors, right after they occur\n- in context\n
  • - see them fail first: it is possible to have bugs in your tests\n- get them passing, only what’s needed\n- clean up after yourself while the tests are green (leverage tests)\n- a codebase not only well tested, but well maintained\n(easy to make changes - tests are there to help you)\n- refactor to make it easy to read\n- refactor your tests... but keep them easy to read (bit of duplication is ok)\n- he thought he was being pragmatic, you think he’s an idiot\n
  • \n
  • - true in the past, but not anymore\n- definitely not for unit testing frameworks\n- TDD/CI have been hard but getting better\n- how complicated is a testing framework anyway?\n\n
  • - true in the past, but not anymore\n- definitely not for unit testing frameworks\n- TDD/CI have been hard but getting better\n- how complicated is a testing framework anyway?\n\n
  • - true in the past, but not anymore\n- definitely not for unit testing frameworks\n- TDD/CI have been hard but getting better\n- how complicated is a testing framework anyway?\n\n
  • - that’s US dollars\n- I don’t have time to write tests\n- 90% of the life of a piece of code is later, more up front = less later\n- if your tests aren’t helping you write better software faster, change something\n- tests are easier to write than the main code, but they also make your real code easier\n- confidence to change things: once you’re comfortable with working in this way, I find it quicker than not writing tests\n
  • - that’s US dollars\n- I don’t have time to write tests\n- 90% of the life of a piece of code is later, more up front = less later\n- if your tests aren’t helping you write better software faster, change something\n- tests are easier to write than the main code, but they also make your real code easier\n- confidence to change things: once you’re comfortable with working in this way, I find it quicker than not writing tests\n
  • - that’s US dollars\n- I don’t have time to write tests\n- 90% of the life of a piece of code is later, more up front = less later\n- if your tests aren’t helping you write better software faster, change something\n- tests are easier to write than the main code, but they also make your real code easier\n- confidence to change things: once you’re comfortable with working in this way, I find it quicker than not writing tests\n
  • - testing is ultimately about pragmatism\n- plenty of good programmers don’t TDD, I’m not dogmatic about it\n- test the most important bits: separation of concerns is important\n- test parts with the most logic / more prone to change more (not less)\n* Models? Yes. Controllers? Probably. IB plumbing? Maybe. Views? Unlikely.\n- can even test position of views and memory, but what does that get you?\n- I want to show you the basics of some things you _can_ test, and how you can test them. It’s up to you\n
  • - testing is ultimately about pragmatism\n- plenty of good programmers don’t TDD, I’m not dogmatic about it\n- test the most important bits: separation of concerns is important\n- test parts with the most logic / more prone to change more (not less)\n* Models? Yes. Controllers? Probably. IB plumbing? Maybe. Views? Unlikely.\n- can even test position of views and memory, but what does that get you?\n- I want to show you the basics of some things you _can_ test, and how you can test them. It’s up to you\n
  • - testing is ultimately about pragmatism\n- plenty of good programmers don’t TDD, I’m not dogmatic about it\n- test the most important bits: separation of concerns is important\n- test parts with the most logic / more prone to change more (not less)\n* Models? Yes. Controllers? Probably. IB plumbing? Maybe. Views? Unlikely.\n- can even test position of views and memory, but what does that get you?\n- I want to show you the basics of some things you _can_ test, and how you can test them. It’s up to you\n
  • - I know what you’re thinking (boring, or reminds you of project estimation)\n- simple enough that none of us really have to think about how it works\n- algorithmically complex enough that we might screw it up\n(and it takes more than one test to drive a full implementation)\n
  • - I know what you’re thinking (boring, or reminds you of project estimation)\n- simple enough that none of us really have to think about how it works\n- algorithmically complex enough that we might screw it up\n(and it takes more than one test to drive a full implementation)\n
  • - I know what you’re thinking (boring, or reminds you of project estimation)\n- simple enough that none of us really have to think about how it works\n- algorithmically complex enough that we might screw it up\n(and it takes more than one test to drive a full implementation)\n
  • - not going to do a live coding demo\n(but hopefully appears on github and my blog soon)\n- create a new “Single View Application”, style up the NIB\n- design skills?\n(this is why I’ve been asking questions about Interface Builder)\n\n
  • - not going to do a live coding demo\n(but hopefully appears on github and my blog soon)\n- create a new “Single View Application”, style up the NIB\n- design skills?\n(this is why I’ve been asking questions about Interface Builder)\n\n
  • - not going to do a live coding demo\n(but hopefully appears on github and my blog soon)\n- create a new “Single View Application”, style up the NIB\n- design skills?\n(this is why I’ve been asking questions about Interface Builder)\n\n
  • - comes with unit tests by default\n- OCUnit is as easy as a check box, but other tools are easy too\n- used to be called SenTest or SenTestingKit, came bundled since Xcode 2\n- sets up applications tests / logic tests -> why?\n- application tests run in the context of your app (UI environment), can run on device)\n- Run with Cmd U -> shortcuts talk\n- but the example test fails\n
  • - comes with unit tests by default\n- OCUnit is as easy as a check box, but other tools are easy too\n- used to be called SenTest or SenTestingKit, came bundled since Xcode 2\n- sets up applications tests / logic tests -> why?\n- application tests run in the context of your app (UI environment), can run on device)\n- Run with Cmd U -> shortcuts talk\n- but the example test fails\n
  • - comes with unit tests by default\n- OCUnit is as easy as a check box, but other tools are easy too\n- used to be called SenTest or SenTestingKit, came bundled since Xcode 2\n- sets up applications tests / logic tests -> why?\n- application tests run in the context of your app (UI environment), can run on device)\n- Run with Cmd U -> shortcuts talk\n- but the example test fails\n
  • - comes with unit tests by default\n- OCUnit is as easy as a check box, but other tools are easy too\n- used to be called SenTest or SenTestingKit, came bundled since Xcode 2\n- sets up applications tests / logic tests -> why?\n- application tests run in the context of your app (UI environment), can run on device)\n- Run with Cmd U -> shortcuts talk\n- but the example test fails\n
  • - fail\n- imagine this is a build light\n- or one of those evil build bunnies\n\n
  • - let’s have a look at the example test file\n- SenTest is OCUnit, didn’t both to rename everything (like NSObject from NextStep)\n- subclass SenTestCase (like JUnit 3 days)\n- test methods return void and take no arguments, dynamically detected\n- extract code into common setUp/tearDown\n- remember to add these classes to the test bundle only\n
  • - let’s have a look at the example test file\n- SenTest is OCUnit, didn’t both to rename everything (like NSObject from NextStep)\n- subclass SenTestCase (like JUnit 3 days)\n- test methods return void and take no arguments, dynamically detected\n- extract code into common setUp/tearDown\n- remember to add these classes to the test bundle only\n
  • - let’s have a look at the example test file\n- SenTest is OCUnit, didn’t both to rename everything (like NSObject from NextStep)\n- subclass SenTestCase (like JUnit 3 days)\n- test methods return void and take no arguments, dynamically detected\n- extract code into common setUp/tearDown\n- remember to add these classes to the test bundle only\n
  • - let’s have a look at the example test file\n- SenTest is OCUnit, didn’t both to rename everything (like NSObject from NextStep)\n- subclass SenTestCase (like JUnit 3 days)\n- test methods return void and take no arguments, dynamically detected\n- extract code into common setUp/tearDown\n- remember to add these classes to the test bundle only\n
  • - let’s have a look at the example test file\n- SenTest is OCUnit, didn’t both to rename everything (like NSObject from NextStep)\n- subclass SenTestCase (like JUnit 3 days)\n- test methods return void and take no arguments, dynamically detected\n- extract code into common setUp/tearDown\n- remember to add these classes to the test bundle only\n
  • - let’s have a look at the example test file\n- SenTest is OCUnit, didn’t both to rename everything (like NSObject from NextStep)\n- subclass SenTestCase (like JUnit 3 days)\n- test methods return void and take no arguments, dynamically detected\n- extract code into common setUp/tearDown\n- remember to add these classes to the test bundle only\n
  • - let’s have a look at the example test file\n- SenTest is OCUnit, didn’t both to rename everything (like NSObject from NextStep)\n- subclass SenTestCase (like JUnit 3 days)\n- test methods return void and take no arguments, dynamically detected\n- extract code into common setUp/tearDown\n- remember to add these classes to the test bundle only\n
  • Controller Tests\n- 2 types: logic and IB plumbing\n- shouldn’t be much logic anyway, but start here and extract as needed\n(for simple apps, maybe it’s ok, but we’ve all seen almost entire apps implemented in a couple of UIViewControllers)\n- can test IB plumbing if you really want (much longer than dragging connections, but if people don’t look at their commits, can easily screw up and have pretty large effects)\n- large effect, should notice quickly, wont be a subtle bug\n
  • - let’s look at some example tests\n- long descriptive name, not camel case\n-- dual purpose (what’s being done, should happen)\n- set up without the NIB, independent of IB (our environment)\n(talk about tests that do use the NIB later)\n- feed in our own label for testing against (could use mock/fake, but can use real)\n- call method and assert outcome\n\n
  • - let’s look at some example tests\n- long descriptive name, not camel case\n-- dual purpose (what’s being done, should happen)\n- set up without the NIB, independent of IB (our environment)\n(talk about tests that do use the NIB later)\n- feed in our own label for testing against (could use mock/fake, but can use real)\n- call method and assert outcome\n\n
  • - let’s look at some example tests\n- long descriptive name, not camel case\n-- dual purpose (what’s being done, should happen)\n- set up without the NIB, independent of IB (our environment)\n(talk about tests that do use the NIB later)\n- feed in our own label for testing against (could use mock/fake, but can use real)\n- call method and assert outcome\n\n
  • - let’s look at some example tests\n- long descriptive name, not camel case\n-- dual purpose (what’s being done, should happen)\n- set up without the NIB, independent of IB (our environment)\n(talk about tests that do use the NIB later)\n- feed in our own label for testing against (could use mock/fake, but can use real)\n- call method and assert outcome\n\n
  • - let’s look at some example tests\n- long descriptive name, not camel case\n-- dual purpose (what’s being done, should happen)\n- set up without the NIB, independent of IB (our environment)\n(talk about tests that do use the NIB later)\n- feed in our own label for testing against (could use mock/fake, but can use real)\n- call method and assert outcome\n\n
  • - let’s look at some example tests\n- long descriptive name, not camel case\n-- dual purpose (what’s being done, should happen)\n- set up without the NIB, independent of IB (our environment)\n(talk about tests that do use the NIB later)\n- feed in our own label for testing against (could use mock/fake, but can use real)\n- call method and assert outcome\n\n
  • - have a look at the code as a whole\n-> everything fails, doesn’t even compile (a test doesn’t have to fail to run)\n-> sometimes quicker to write interface/empty implementation first\n(get autocompletion)\n-> add label property and reset action (IBOutlet/IBAction or do this later)\n- should be enough to build and run\n- press Cmd U again and run your tests\n
  • - that’s fine, we haven’t written the implementation yet\n- important to see your tests fail first, so you know they work\n
  • - that’s pretty simple\n- always a judgment call how simple is too simple\n- could introduce an ivar, convert to string\n(we know we’ll need to set that current variable back to zero at some stage)\n
  • - that’s pretty simple\n- always a judgment call how simple is too simple\n- could introduce an ivar, convert to string\n(we know we’ll need to set that current variable back to zero at some stage)\n
  • - that’s pretty simple\n- always a judgment call how simple is too simple\n- could introduce an ivar, convert to string\n(we know we’ll need to set that current variable back to zero at some stage)\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - don’t need more than that - if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n
  • - again, expect the test to fail\n- test failures are not always a bad thing\n
  • - brown madza\n- simplest thing for now, we’ll come back later\n
  • - don’t need more than that if you’re estimating\n- usually write one test at a time\n- if pair programming, ping pong between them\n-> tests are easy, move all the set up code to set up\njust call next 0, 1 or 2 times\n- next method won’t exist, go and create it, empty implementation\n- eventually, the algorithm will be complete no matter how far you count\n
  • - once your tests are passing, always look to improve your code\n- step 3: refactor\n- you’ll never do it later, do it now...\n(don’t take on technical debt)\n- probably not as awesome as an old english sports car\n
  • - once your tests are passing, always look to improve your code\n- step 3: refactor\n- you’ll never do it later, do it now...\n(don’t take on technical debt)\n- probably not as awesome as an old english sports car\n
  • - once your tests are passing, always look to improve your code\n- step 3: refactor\n- you’ll never do it later, do it now...\n(don’t take on technical debt)\n- probably not as awesome as an old english sports car\n
  • - once your tests are passing, always look to improve your code\n- step 3: refactor\n- you’ll never do it later, do it now...\n(don’t take on technical debt)\n- probably not as awesome as an old english sports car\n
  • controller has two main methods, but don’t really want all the algorithm code there\n- controllers get too busy, so separate out those details into a model\n- controller is left just plumbing things together, dealing with lifecycle\n- most iOS apps have almost the entire app written in UIViewController classes\n
  • controller has two main methods, but don’t really want all the algorithm code there\n- controllers get too busy, so separate out those details into a model\n- controller is left just plumbing things together, dealing with lifecycle\n- most iOS apps have almost the entire app written in UIViewController classes\n
  • controller has two main methods, but don’t really want all the algorithm code there\n- controllers get too busy, so separate out those details into a model\n- controller is left just plumbing things together, dealing with lifecycle\n- most iOS apps have almost the entire app written in UIViewController classes\n
  • controller has two main methods, but don’t really want all the algorithm code there\n- controllers get too busy, so separate out those details into a model\n- controller is left just plumbing things together, dealing with lifecycle\n- most iOS apps have almost the entire app written in UIViewController classes\n
  • controller has two main methods, but don’t really want all the algorithm code there\n- controllers get too busy, so separate out those details into a model\n- controller is left just plumbing things together, dealing with lifecycle\n- most iOS apps have almost the entire app written in UIViewController classes\n
  • controller has two main methods, but don’t really want all the algorithm code there\n- controllers get too busy, so separate out those details into a model\n- controller is left just plumbing things together, dealing with lifecycle\n- most iOS apps have almost the entire app written in UIViewController classes\n
  • controller has two main methods, but don’t really want all the algorithm code there\n- controllers get too busy, so separate out those details into a model\n- controller is left just plumbing things together, dealing with lifecycle\n- most iOS apps have almost the entire app written in UIViewController classes\n
  • - Interface Builder plumbing\n
  • - Interface Builder plumbing\n
  • - they’re written in Kiwi or OCUnit, but let’s not call them unit tests\n- it’s an interesting testing problem to try\n-> how good is it in practice?\n (everyone says no, but no one has tried it... the only team I know that tried it thinks they were the most valuable tests in the suite)\n- for an individual developer, or a team who actually reads git diffs before committing?\n
  • - let’s take a look at a few potential Interface Builder and NIB test\n- might want to check that you’ve set all your outlets correctly\n
  • - let’s take a look at a few potential Interface Builder and NIB test\n- might want to check that you’ve set all your outlets correctly\n
  • - might want to check your actions are correct\n
  • - might want to check your actions are correct\n
  • - check that your view gets cleaned up on low memory conditions\n- this one is potentially valuable\n- something we often forget, or get wrong but don’t often manually test\n-> could use screenshot based testing before and after as well\n
  • - check that your view gets cleaned up on low memory conditions\n- this one is potentially valuable\n- something we often forget, or get wrong but don’t often manually test\n-> could use screenshot based testing before and after as well\n
  • - didn’t get a really good chance to look at it yet\n- it’s a wrapper around OCUnit, so it runs within Xcode\n- heavily uses macros and blocks to make your tests nicer\n- only been out a few months, but actively worked on\n
  • - series of nested blocks to describe behaviour in certain context\n(in some ways it’s a bunch of different works for a similar function)\n- installation: static library, or cocoapods... vendor?\n
  • - series of nested blocks to describe behaviour in certain context\n- reads a lot more like plain English (but with ObjC syntax noise)\n\n
  • - series of nested blocks to describe behaviour in certain context\n- reads a lot more like plain English (but with ObjC syntax noise)\n\n
  • - series of nested blocks to describe behaviour in certain context\n- reads a lot more like plain English (but with ObjC syntax noise)\n\n
  • - in some ways it’s a bunch of different works for a similar function\n-> but these small changes actually change the way you think about your tests\n- Spec, not Test. “it should”, not “testThat”\n-> start describing the behaviour of your code, not testing the functionality\n- promotes test-first thinking\n
  • - Kiwi comes with its own mocking/stubbing capability\n(nicer syntax than OCMock, haven’t looked at LRMocky)\n
  • - look at our refactored code\n- controller is just passing messages between views and models\n
  • \n
  • - command line tooling is always an afterthought with Apple tools\n(surprising, given the Unix history)\n- need command line for running in CI without human intervention\n
  • xcodebuild -project FibCounter.xcodeproj -target FibCounterTests -configuration Debug -sdk iphonesimulator build\n
  • - xcode build specifies workspaces and schemes as well\n- workspaces and schemes seem worthwhile\n- the build step will run your unit \n
  • \n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • - training course is $70 or so, really worth while\n- Doug Sjoquist - idevblogaday, part 2 is out, more coming\n- Prag Prog had a few articles over the last year or two\n
  • \n
  • \n
  • \n
  • \n
  • iOS Unit Testing

    1. 1. An introduction to unit testing for iOS applicationsSTEWART GLEADOW @stewgleadow Thoughtwor
    2. 2. UnitTesting
    3. 3. Unit TestingOCUnit
    4. 4. Unit TestingOCUnit Kiwi
    5. 5. Unit TestingOCUnit Kiwi Comma nd Line
    6. 6. Have we been here before?http://sgleadow.github.com/ talks.html#frank
    7. 7. http://sgleadow.github.com/ talks.html#agileios
    8. 8. UI Integration Unithttp://sgleadow.github.com/ talks.html#agileios
    9. 9. UI Integration OCUnit GHUnit GTM Unithttp://sgleadow.github.com/ talks.html#agileios
    10. 10. UI Integration Kiwi Cedar OCUnit GHUnit GTM Unithttp://sgleadow.github.com/ talks.html#agileios
    11. 11. Why test in units?We only care if thewhole app works.
    12. 12. Write your tests first. Use tests to design your code
    13. 13. Write your tests first. Use tests to design your code “Classes typically resist the transition from one user to two, then the rest are easy” - Kent Beck, c2.wiki
    14. 14. Fast feedback
    15. 15. RedGreen Refact
    16. 16. but we’re making iOS apps
    17. 17. THE TOOLS AREN’T GOOD ENOUGH
    18. 18. THE TOOLS AREN’T GOOD ENOUGH there are too many frameworks to fit here
    19. 19. NO ONE PAYS YOU TO WRITE TESTS
    20. 20. NO ONE PAYS YOU TO WRITE TESTS they pay you to write software that works
    21. 21. SHOULD YOU ALWAYS TEST EVERYTHING ?
    22. 22. SHOULD YOU ALWAYS TEST EVERYTHING ? “it depends”, says the consultant
    23. 23. Fibonacci, really?
    24. 24. Apple designaward here we come
    25. 25. GettingStarted
    26. 26. Getting Started or, if you’ve already started...http://sgleadow.github.com/blog/2011/10/30/adding-unit-tests-to-an-existing-ios-project
    27. 27. OCUnit
    28. 28. OCUnitApplication Logic
    29. 29. #import <SenTestingKit/SenTestingKit.h>
    30. 30. @interface FibCounterTests : SenTestCase@end
    31. 31. - (void)testExample { STFail(@"epic fail");}
    32. 32. - (void)setUp {}- (void)tearDown {}
    33. 33. Controller Tests
    34. 34. - (void)test_the_fibonacci_number_is_zero_after_reset {}
    35. 35. - (void)test_the_fibonacci_number_is_zero_after_reset { ourCounter = [[UILabel alloc] init];}
    36. 36. - (void)test_the_fibonacci_number_is_zero_after_reset { ourCounter = [[UILabel alloc] init]; controller = [[SGViewController alloc] initWithNibName:nil bundle:nil];}
    37. 37. - (void)test_the_fibonacci_number_is_zero_after_reset { ourCounter = [[UILabel alloc] init]; controller = [[SGViewController alloc] initWithNibName:nil bundle:nil]; controller.counter = ourCounter;}
    38. 38. - (void)test_the_fibonacci_number_is_zero_after_reset { ourCounter = [[UILabel alloc] init]; controller = [[SGViewController alloc] initWithNibName:nil bundle:nil]; controller.counter = ourCounter; [controller resetCounter];}
    39. 39. - (void)test_the_fibonacci_number_is_zero_after_reset { ourCounter = [[UILabel alloc] init]; controller = [[SGViewController alloc] initWithNibName:nil bundle:nil]; controller.counter = ourCounter; [controller resetCounter]; STAssertEqualObjects(ourCounter.text, @"0", nil);}
    40. 40. - (void)test_the_fibonacci_number_is_zero_after_reset { ourCounter = [[UILabel alloc] init]; controller = [[SGViewController alloc] initWithNibName:nil bundle:nil]; controller.counter = ourCounter; [controller resetCounter]; STAssertEqualObjects(ourCounter.text, @"0", nil);}
    41. 41. (null) should be equal to 0
    42. 42. WRITE THESIMPLEST CODE TO MAKE THE TEST PASS
    43. 43. WRITE THE SIMPLEST CODE TO MAKE THE TEST PASS- (void)resetCounter { self.counter.text = @"0";}
    44. 44. WRITE THE SIMPLEST CODE TO MAKE THE TEST PASS- (void)resetCounter { self.counter.text = [NSStringstringWithFormat:@"%u", current];}
    45. 45. TEST DRIVE OUR FIBONACCI ALGORITHM
    46. 46. TEST DRIVE OUR FIBONACCI ALGORITHM 210, 1, 1, 2, 3, 5, 8, 13,
    47. 47. TEST DRIVE OUR FIBONACCI ALGORITHM 21 0, 1, 1, 2, 3, 5, 8, 13,test_the_first_fibonacci_number_is_zerotest_the_seond_fibonacci_number_is_onetest_the_third_fibonacci_number_is_one
    48. 48. TEST DRIVE OUR FIBONACCI ALGORITHM 21 0, 1, 1, 2, 3, 5, 8, 13,test_the_first_fibonacci_number_is_zero -test_the_seond_fibonacci_number_is_onetest_the_third_fibonacci_number_is_one
    49. 49. TEST DRIVE OUR FIBONACCI ALGORITHM 21 0, 1, 1, 2, 3, 5, 8, 13,test_the_first_fibonacci_number_is_zero -test_the_seond_fibonacci_nu [controllermber_is_one next];test_the_third_fibonacci_number_is_one
    50. 50. TEST DRIVE OUR FIBONACCI ALGORITHM 21 0, 1, 1, 2, 3, 5, 8, 13,test_the_first_fibonacci_number_is_zero -test_the_seond_fibonacci_nu [controllermber_is_one next]; [controllertest_the_third_fibonacci_nu next]; [controllermber_is_one next];
    51. 51. 0 should be equal to 1
    52. 52. DO THESIMPLESTTHING TO MAKE IT
    53. 53. KEEP BUILDING YOUR TESTS UNTIL YOU HAVE THE ENTIRE
    54. 54. MAKE IT AWESOME
    55. 55. MAKE IT AWESOME (aka - there is a step 3)
    56. 56. MAKE IT AWESOME (aka - there is a step 3)
    57. 57. (defun fib (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))) MAKE IT AWESOME (aka - there is a step 3)
    58. 58. SGViewController- (void)next;- (void)resetCounter;
    59. 59. SGViewController- (void)next;- (void)resetCounter; Fibber - (NSUInteger)current; - (NSUInteger)next; - (NSUInteger)reset;
    60. 60. UIButton SGViewController- (void)next; UILabel- (void)resetCounter; Fibber - (NSUInteger)current; - (NSUInteger)next; - (NSUInteger)reset;
    61. 61. MoreController Tests
    62. 62. It is possible to test yourUIViewControllerlifecycle and XIBfrom your “unit” tests
    63. 63. controller. view* check for non-nil outlets *
    64. 64. [button actionsForTarget:controllforControlEvent:UIControlEventTochUpInside] for correct action * check selectors *
    65. 65. [controllerdidReceiveMemoryWarning] * check for nil outlets *
    66. 66. WHAT ABOUT KIWI?
    67. 67. RSpec Style vs xUnit Style
    68. 68. SPEC_BEGIN(SGViewControllerSpec)SPEC_END
    69. 69. SPEC_BEGIN(SGViewControllerSpec) describe(@"fibonacci number", ^{ context(@"when reset", ^{ }); });SPEC_END
    70. 70. SPEC_BEGIN(SGViewControllerSpec) describe(@"fibonacci number", ^{ context(@"when reset", ^{ beforeEach(^{ // set up code }); it(@"should be zero", ^{ [controller resetCounter]; [[[ourCounter text] should] equal:@"0"]; }); }); });SPEC_END
    71. 71. Is it just a change of wording?
    72. 72. Kiwi comes with mocksand stubs built in
    73. 73. UIButton SGViewController- (void)next; UILabel- (void)resetCounter; Fibber - (NSUInteger)current; - (NSUInteger)next; - (NSUInteger)reset;
    74. 74. TESTS AREEFFECTIVELYTESTING THE PLUMBING
    75. 75. TESTS ARE EFFECTIVELY TESTING THE PLUMBINGit(@"should update label using fibber", ^{ id ourFibber = [Fibber mock]; [[ourFibber should] receive:@selector(next)andReturn:theValue(3)]; controller.fibber = ourFibber; [controller next]; [[[ourCounter text] should] equal:@"3"];});
    76. 76. WHAT ABOUTRUNNING TESTS FROM THECOMMAND LINE
    77. 77. xcodebuild is your friend...
    78. 78. xcodebuild is your friend... until it unfriends you
    79. 79. xcodebuild -projectFibCounter.xcodeproj -targetFibCounterTests -configurationDebug -sdkiphonesimulator
    80. 80. and hack this file: "${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests"
    81. 81. and hack this file: "${SYSTEM_DEVELOPER_DIR}/Tools/ RunUnitTests"http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/
    82. 82. Resources
    83. 83. ResourcesiDeveloper TV Unit TestingCourse (Graham Lee) http://ideveloper.tv/video/ unittestingcourse.html
    84. 84. ResourcesiDeveloper TV Unit TestingCourse (Graham Lee) http://ideveloper.tv/video/ unittestingcourse.htmlTDD for iOS Tutorials (DougSjoquist) http://www.sunetos.com/items/ 2011/10/24/tdd-ios-part-1
    85. 85. ResourcesiDeveloper TV Unit TestingCourse (Graham Lee) http://ideveloper.tv/video/ unittestingcourse.htmlTDD for iOS Tutorials (DougSjoquist) http://www.sunetos.com/items/ 2011/10/24/tdd-ios-part-1Prag Prog Magazine http://pragprog.com/magazines/2010-07/ tdd-on-iphone-diy
    86. 86. ResourcesiDeveloper TV Unit TestingCourse (Graham Lee) http://ideveloper.tv/video/ unittestingcourse.htmlTDD for iOS Tutorials (DougSjoquist) http://www.sunetos.com/items/ 2011/10/24/tdd-ios-part-1Prag Prog Magazine http://pragprog.com/magazines/2010-07/ tdd-on-iphone-diyShameless Shameless Plug http://sgleadow.github.com
    87. 87. THANKS
    88. 88. STEWART GLEADOW Thoughtworks sgleadow.github.c Talks: om/talksTwitter: @stewgleadow Email: sgleadow@though

    ×