Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TDD Concepts & Kiwi

TDD Concepts & Kiwi

A quick, brief, stupid overview of TDD in general, and then some Kiwi-specific stuff. Codebase referenced in the slidedeck is here: https://github.com/crebma/pants-lister

7c2a83b93fe0e5f2ed4c95c59367259c?s=128

Amber Conville

April 16, 2014
Tweet

More Decks by Amber Conville

Other Decks in Programming

Transcript

  1. what is a tdd & why do i care

  2. whywhywhy automate the things you are testing manually.

  3. whywhywhy automate the things you are testing manually. protect from

    careless refactors
  4. whywhywhy automate the things you are testing manually. protect from

    careless refactors build a design that is inherently testable, which means modular and easy to change
  5. whywhywhy automate the things you are testing manually. protect from

    careless refactors build a design that is inherently testable, which means modular and easy to change reveal code smells (srp, dawg!)
  6. whywhywhy automate the things you are testing manually. protect from

    careless refactors build a design that is inherently testable, which means modular and easy to change reveal code smells (srp, dawg!) breaks large nebulous things into small tasks so it can inform the next step (omg, just like a card wall!)
  7. whywhywhy automate the things you are testing manually. protect from

    careless refactors build a design that is inherently testable, which means modular and easy to change reveal code smells (srp, dawg!) breaks large nebulous things into small tasks so it can inform the next step (omg, just like a card wall!) allows the ability to change code with confidence
  8. whut a unit test is not *just* a test, is

    it a kind of test. a unit test does not:
  9. whut a unit test is not *just* a test, is

    it a kind of test. a unit test does not: touch the filesystem
  10. whut a unit test is not *just* a test, is

    it a kind of test. a unit test does not: touch the filesystem talk to a database
  11. whut a unit test is not *just* a test, is

    it a kind of test. a unit test does not: touch the filesystem talk to a database have any real ui
  12. whut a unit test is not *just* a test, is

    it a kind of test. a unit test does not: touch the filesystem talk to a database have any ui make any network calls
  13. whut a unit test is not *just* a test, is

    it a kind of test. a unit test does not: touch the filesystem talk to a database have any ui make any network calls why?
  14. whut because you want your unit tests to be the

    most-often run tests. you want the feedback cycle to be fast, so we cut out the parts that are slow and replace them with mocks.
  15. whut because you want your unit tests to be the

    most-often run tests. you want the feedback cycle to be fast, so we cut out the parts that are slow and replace them with mocks. you don't want to test third party libraries. if you’ve done library selection carefully, you’ve chosen a library that already has tests, so we can focus on testing our own output and not everyone else’s.
  16. –Jim Hood, possibly quoting another smart person “test until you

    are bored instead of worried or confused”
  17. good testing practices

  18. don’t expose your privates test your objects through their public

    api. when you expose your privates and test those, you are locking in the implementation of that object, rather than the output of that object. you want to test that your object does or produces X in a given scenario, not exactly how it will come to produce X. this makes it easier to refactor code to do the same thing, but better, without having to change your tests.
  19. replace your objects collaborators with puppets. since we are testing

    our object in isolation, we want to be able to completely control the scenario for each test, similar to pulling the strings on a puppet. more on this later. be a puppet master
  20. replace your objects collaborators with puppets. since we are testing

    our object in isolation, we want to be able to completely control the scenario for each test, similar to pulling the strings on a puppet. more on this later. …yes, i’m talking about mocks. what is wrong with me. be a puppet master
  21. replace your objects collaborators with puppets. since we are testing

    our object in isolation, we want to be able to completely control the scenario for each test, similar to pulling the strings on a puppet. more on this later. …yes, i’m talking about mocks. what is wrong with me. be a puppet master
  22. use the whitespace in your test to help other people

    understand what is happening. arrange your test goodly
  23. use the whitespace in your test to help other people

    understand what is happening. arrange your test goodly this costs more time for someone to figure out: that’s a test with parts in it, presumably ending with an assertion…?
  24. use the whitespace in your test to help other people

    understand what is happening. arrange your test goodly than this does: setup execute assert
  25. when you have more than one failure per test, a

    test failure becomes ambiguous. it could be any given assertion in a test. this is especially a pain if your multiple asserts are by way of a for loop. have fun debugging that. one assert per test
  26. when you have more than one failure per test, a

    test failure becomes ambiguous. it could be any given assertion in a test. this is especially a pain if your multiple asserts are by way of a for loop. have fun debugging that. one assert per test it also means you’re probably taking WAY too big of a step. take baby steps. all you have to do is take one little step at a time, and you can do anything!
  27. when you have more than one failure per test, a

    test failure becomes ambiguous. it could be any given assertion in a test. this is especially a pain if your multiple asserts are by way of a for loop. have fun debugging that. one assert per test it also means you’re probably taking WAY too big of a step. take baby steps. all you have to do is take one little step at a time, and you can do anything!
  28. how to do

  29. this is simple, and makes for awesome clean code *during*

    the process instead of some nebulous “refactor stuff” card later that never gets played because no one knows what it means. red green refactor
  30. this is simple, and makes for awesome clean code *during*

    the process instead of some nebulous “refactor stuff” card later that never gets played because no one knows what it means. red green refactor 1. you write a little test.
  31. this is simple, and makes for awesome clean code *during*

    the process instead of some nebulous “refactor stuff” card later that never gets played because no one knows what it means. red green refactor 1. you write a little test. 2. you make the test pass.
  32. this is simple, and makes for awesome clean code *during*

    the process instead of some nebulous “refactor stuff” card later that never gets played because no one knows what it means. red green refactor 1. you write a little test. 2. you make the test pass. 3. you look at your code and see if there is anything to clean up or any way to make it better. this also applies to your test code. this is refactoring!
  33. this is simple, and makes for awesome clean code *during*

    the process instead of some nebulous “refactor stuff” card later that never gets played because no one knows what it means. red green refactor 1. you write a little test. 2. you make the test pass. 3. you look at your code and see if there is anything to clean up or any way to make it better. this also applies to your test code. this is refactoring! 4. go back to 1 and start over. don’t skip 3.
  34. mocks are those puppet things i rambled about earlier. mocks

    are awesome. let’s draw on the board about that. that puppet thing…mocks
  35. mocks are those puppet things i rambled about earlier. mocks

    are awesome. let’s draw on the board about that. that puppet thing…mocks there are a couple kinds of mocks. a strict mock will blow up if anything on it is called that you did not stub. a nice mock will either do nothing or return null if necessary.
  36. mocks are those puppet things i rambled about earlier. mocks

    are awesome. let’s draw on the board about that. that puppet thing…mocks there are a couple kinds of mocks. a strict mock will blow up if anything on it is called that you did not stub. a nice mock will either do nothing or return null if necessary. what is “stub”?
  37. mocks are those puppet things i rambled about earlier. mocks

    are awesome. let’s draw on the board about that. that puppet thing…mocks there are a couple kinds of mocks. a strict mock will blow up if anything on it is called that you did not stub. a nice mock will either do nothing or return null if necessary. what is “stub”? a stub is the way you pull the puppet strings. you can stub a mock to return some predetermined value, or to execute some alternate functionality! strings!!!!
  38. where the magic of strings and puppets becomes obvious. i

    mean mocks and stubs. whatever. but this service talks to an external api
  39. where the magic of strings and puppets becomes obvious. i

    mean mocks and stubs. whatever. but this service talks to an external api we can mock the actual library that talks to the external api and stub it to return a predetermined bunch of data, and then test our service’s output. in java, that probably means an injected wrapper class. in iOS, you can just do it. examples later.
  40. yup, that is going to suck. but mock dem view

    objects. but this has a lot of view interactions
  41. yup, that is going to suck. but mock dem view

    objects. but this has a lot of view interactions where possible, you should extract the non- view logic to a collaborator, which will make it much easier to test. for example, in a view controller in iOS, anything that gets data should be in a collaborator object.
  42. yup, that is going to suck. but mock dem view

    objects. but this has a lot of view interactions where possible, you should extract the non- view logic to a collaborator, which will make it much easier to test. for example, in a view controller in iOS, anything that gets data should be in a collaborator object. tests around how things *look* instead of how things *behave* should live in a different quite of tests. we’ll talk a little about that later.
  43. code coverage

  44. basically that. it tells you what percentage of your production

    code is exercised by tests. it will examine logic branches, like ifs and loops, as well as your public methods. scavenger hunt is at about 72% coverage, which means they can change code with a relatively high degree of confidence that the tests will tell them if anything went wrong. a chart that shows what is tested!
  45. sometimes people say their goal is 100% code coverage. there

    is no magic number
  46. sometimes people say their goal is 100% code coverage. there

    is no magic number
  47. sometimes people say their goal is 100% code coverage. there

    is no magic number that leads to doing stuff like testing getters and setters, which is silly. a lot of folks aim for 85%, knowing that being below that is perfectly fine if it is explainable. that seems like a good goal.
  48. different kinds of tests

  49. unit tests are sometimes called isolation tests, for the reasons

    we talked about in the beginning. they can also be called logic tests. kinds of tests
  50. unit tests are sometimes called isolation tests, for the reasons

    we talked about in the beginning. they can also be called logic tests. kinds of tests integration tests are also a thing. they test the contract between 2-3 layers. these tests might talk to an actual database or an actual database and test the contract between your service object and the network or database.
  51. unit tests are sometimes called isolation tests, for the reasons

    we talked about in the beginning. they can also be called logic tests. kinds of tests integration tests are also a thing. they test the contract between 2-3 layers. these tests might talk to an actual database or an actual database and test the contract between your service object and the network or database. another kind of test is acceptance tests, also called behavior tests, end to end tests, or application tests. these tests do not mock at all if possible, and run through the real ui right down to the real service.
  52. xunit style testing public class YourFaceTest {
 @Test
 public void

    yourFaceIsAmazing() {
 Face yourFace = new Face();
 assertThat(yourFace, is(“Amazing”));
 }
 
 @Test
 public void yourFaceIsSmilingWhenYouAreHappy() {
 Face yourFace = new Face();
 yourFace.setMood(HAPPY);
 assertThat(yourFace.getExpression(), is(SMILING));
 }
 
 }
  53. spec style testing describe(@“Your Face”, ^{
 
 it(@“your face is

    amazing”, ^{
 Face *yourFace = [[Face alloc] init];
 [yourFace should] equal:@“amazing”];
 };
 
 context(@“You are happy”, ^{
 
 it(@“is smiling”, ^{
 Face *yourFace = [[Face alloc] init];
 [yourFace setMood:@“Happy”];
 [yourFace.expression should] equal:@“smiling”];
 });
 });
 };
  54. iOS

  55. why kiwi? describe(@“Your Face”, ^{
 
 it(@“your face is amazing”,

    ^{
 Face *yourFace = [[Face alloc] init];
 [yourFace should] equal:@“amazing”];
 };
 
 context(@“You are happy”, ^{
 
 it(@“is smiling”, ^{
 Face *yourFace = [[Face alloc] init];
 [yourFace setMood:@“Happy”];
 [yourFace.expression should] equal:@“smiling”];
 });
 });
 };
  56. helpful kiwi anatomy describe
 context
 it
 beforeEach
 nullMock
 should receive:


    theValue()
 stub:
 stub:andReturn:
 stub:withBlock:
 captureArgument:atIndex:
  57. to the codebase!