Loading ...
Sorry, an error occurred while loading the content.

What is the incremental TDD approach to reach a while loop with a terminating clause ?

Expand Messages
  • Gishu Pillai
    I was taking a crack at StringCalc Kata#2 The objective is to have a console app that calculates the result for the given
    Message 1 of 17 , Sep 8, 2011
    View Source
    • 0 Attachment
      I was taking a crack at StringCalc Kata#2 <http://osherove.com/tdd-kata-2/>

      The objective is to have a console app that calculates the result for the
      given input. It then prompts for more input and keeps printing out results
      until the user enters a blank input (at which point the console app exits).

      So now the convention is to test 0, 1 and then n iterations. The while loop
      is introduced as a refactoring step up from duplicated ifs. This is all
      good.

      However, there is a requirement that the console app does not exit until the
      user enters a blank input.
      But I do not have an explicit test for that ? Is it required ? If yes, it
      looks like a test whose success definition would be : the test times out if
      I keep entering a non-blank value as input. Where should that test come in?

      RFC

      Gishu


      [Non-text portions of this message have been removed]
    • Donaldson, John (GEO)
      Gishu, I started answering in my simple way until I realized you were asking: do I need a test for user does *not* enter exit signal . I think, in this case
      Message 2 of 17 , Sep 9, 2011
      View Source
      • 0 Attachment
        Gishu,

        I started answering in my simple way until I realized you were asking: do I need a test for "user does *not* enter exit signal".

        I think, in this case you don't need it.
        It's the exact opposite of "user *does* enter exit signal".

        Also you will have some kind of test that it does not exit when you keep supplying input - in the sense of "prompt for more input". (Keeps calculating is the same as does not exit).

        John D.

        -----Original Message-----
        From: testdrivendevelopment@yahoogroups.com [mailto:testdrivendevelopment@yahoogroups.com] On Behalf Of Gishu Pillai
        Sent: 09 September 2011 07:50
        To: testdrivendevelopment@yahoogroups.com
        Subject: [TDD] What is the incremental TDD approach to reach a while loop with a terminating clause ?

        I was taking a crack at StringCalc Kata#2 <http://osherove.com/tdd-kata-2/>

        The objective is to have a console app that calculates the result for the
        given input. It then prompts for more input and keeps printing out results
        until the user enters a blank input (at which point the console app exits).

        So now the convention is to test 0, 1 and then n iterations. The while loop
        is introduced as a refactoring step up from duplicated ifs. This is all
        good.

        However, there is a requirement that the console app does not exit until the
        user enters a blank input.
        But I do not have an explicit test for that ? Is it required ? If yes, it
        looks like a test whose success definition would be : the test times out if
        I keep entering a non-blank value as input. Where should that test come in?

        RFC

        Gishu


        [Non-text portions of this message have been removed]



        ------------------------------------

        Yahoo! Groups Links
      • Gishu Pillai
        ... forever? I have one test that tests the multiple iterations case. However it is still finite - n iterations This is how I went about it -
        Message 3 of 17 , Sep 15, 2011
        View Source
        • 0 Attachment
          > Also you will have some kind of test that it does not exit when you keep
          > supplying input - in the sense of "prompt for more input". (Keeps
          > calculating is the same as does not exit).
          >
          > That just inverts the problem... how do I test for keeps calculating
          forever?
          I have one test that tests the "multiple iterations" case. However it is
          still finite - n iterations

          This is how I went about it - http://vimeo.com/gishu/stringcalckata2b
          I had tests for 0, 1 and n (2) secondary inputs.


          [Non-text portions of this message have been removed]
        • Donaldson, John (GEO)
          Gishu, Why do you think this is a problem in this case? If you have a calculator and it works for 3+1, then you will not be worried about 3+2. In the same way,
          Message 4 of 17 , Sep 15, 2011
          View Source
          • 0 Attachment
            Gishu,

            Why do you think this is a problem in this case?
            If you have a calculator and it works for 3+1, then you will not be worried about 3+2.
            In the same way, if the reprompting works for 3 reprompts, then why worry about 4?
            We only find edge cases by code inspection - and this case - reprompt a lot - is not an edge case.

            John D.

            -----Original Message-----
            From: testdrivendevelopment@yahoogroups.com [mailto:testdrivendevelopment@yahoogroups.com] On Behalf Of Gishu Pillai
            Sent: 15 September 2011 13:47
            To: testdrivendevelopment@yahoogroups.com
            Subject: Re: [TDD] What is the incremental TDD approach to reach a while loop with a terminating clause ?

            > Also you will have some kind of test that it does not exit when you keep
            > supplying input - in the sense of "prompt for more input". (Keeps
            > calculating is the same as does not exit).
            >
            > That just inverts the problem... how do I test for keeps calculating
            forever?
            I have one test that tests the "multiple iterations" case. However it is
            still finite - n iterations

            This is how I went about it - http://vimeo.com/gishu/stringcalckata2b
            I had tests for 0, 1 and n (2) secondary inputs.


            [Non-text portions of this message have been removed]



            ------------------------------------

            Yahoo! Groups Links
          • Gishu Pillai
            On Thu, Sep 15, 2011 at 9:26 PM, Donaldson, John (GEO)
            Message 5 of 17 , Sep 16, 2011
            View Source
            • 0 Attachment
              On Thu, Sep 15, 2011 at 9:26 PM, Donaldson, John (GEO) <
              john.m.donaldson@...> wrote:

              > **
              > Why do you think this is a problem in this case?
              >
              > If you have a calculator and it works for 3+1, then you will not be worried
              > about 3+2.
              > In the same way, if the reprompting works for 3 reprompts, then why worry
              > about 4?
              >
              > Well do not want to be pedantic here... W.r.t. my video, I am okay with my
              tests -- 90%+ confident. But I'm used to belief that my unit tests should
              catch any broken scenario.

              The while loop is only introduced at the end as a refactoring to remove 3
              unrolled loops. e.g. if I undo the while loop introducing refactoring step,
              the unit tests that test for 0,1,2 secondary inputs would still pass.
              However that is key - without the while loop, the story is broken but the
              unit tests all pass.
              Should this be the responsibility of an acceptance test which tests with
              different max-iterations e.g. [4, 9, 15] ? (That'd be my answer if pushed
              into a hypothetical corner)


              [Non-text portions of this message have been removed]
            • Donaldson, John (GEO)
              Gishu, Yes, I agree it s a problem we would like to avoid. If it had been me, I would probably have side-stepped it because I normally do something like: 0, 1,
              Message 6 of 17 , Sep 16, 2011
              View Source
              • 0 Attachment
                Gishu,

                Yes, I agree it's a problem we would like to avoid.
                If it had been me, I would probably have side-stepped it because I normally do something like: 0, 1, many.
                (Where "many" usually turns out to be three).

                It feels like we are being too analytical - but you might make a test which used a random number of inputs for the "many" case?

                But maybe it's not an issue at all? There are probably an infinitely large number of code solutions you can refactor to - not all elegant. And you are just refactoring back to a perfectly valid solution for 0,1,2. Why indeed *should* it fail? It seems that you want the test to police a sort of code elegance!

                John D.

                -----Original Message-----
                From: testdrivendevelopment@yahoogroups.com [mailto:testdrivendevelopment@yahoogroups.com] On Behalf Of Gishu Pillai
                Sent: 16 September 2011 14:51
                To: testdrivendevelopment@yahoogroups.com
                Subject: Re: [TDD] What is the incremental TDD approach to reach a while loop with a terminating clause ?

                On Thu, Sep 15, 2011 at 9:26 PM, Donaldson, John (GEO) <
                john.m.donaldson@...> wrote:

                > **
                > Why do you think this is a problem in this case?
                >
                > If you have a calculator and it works for 3+1, then you will not be worried
                > about 3+2.
                > In the same way, if the reprompting works for 3 reprompts, then why worry
                > about 4?
                >
                > Well do not want to be pedantic here... W.r.t. my video, I am okay with my
                tests -- 90%+ confident. But I'm used to belief that my unit tests should
                catch any broken scenario.

                The while loop is only introduced at the end as a refactoring to remove 3
                unrolled loops. e.g. if I undo the while loop introducing refactoring step,
                the unit tests that test for 0,1,2 secondary inputs would still pass.
                However that is key - without the while loop, the story is broken but the
                unit tests all pass.
                Should this be the responsibility of an acceptance test which tests with
                different max-iterations e.g. [4, 9, 15] ? (That'd be my answer if pushed
                into a hypothetical corner)


                [Non-text portions of this message have been removed]



                ------------------------------------

                Yahoo! Groups Links
              • Gishu Pillai
                On Fri, Sep 16, 2011 at 6:38 PM, Donaldson, John (GEO)
                Message 7 of 17 , Sep 16, 2011
                View Source
                • 0 Attachment
                  On Fri, Sep 16, 2011 at 6:38 PM, Donaldson, John (GEO) <
                  john.m.donaldson@...> wrote:

                  > **
                  >
                  > It feels like we are being too analytical - but you might make a test which
                  > used a random number of inputs for the "many" case?
                  >
                  I usually write simple tests.. I think the test might lose on the
                  readability ... only one way to find out. I'll try that next time I try the
                  kata. Nice idea!

                  >
                  > But maybe it's not an issue at all? There are probably an infinitely large
                  > number of code solutions you can refactor to - not all elegant. And you are
                  > just refactoring back to a perfectly valid solution for 0,1,2. Why indeed
                  > *should* it fail? It seems that you want the test to police a sort of code
                  > elegance!
                  >
                  Maybe I have too much time on my hands :) Yes, It'd take a deliberate act to
                  break the software... not something to lose sleep over.
                  Just reflecting on my method, trying to figure out better ways to do the
                  same thing.

                  Thanks for the dialogue,
                  Gishu


                  [Non-text portions of this message have been removed]
                • JeffGrigg
                  ... Answer: You don t. I like the evil coder pattern: - You write the next test. - Then The Evil Coder writes code that passes the test... but is wrong.
                  Message 8 of 17 , Sep 16, 2011
                  View Source
                  • 0 Attachment
                    --- Gishu Pillai <gishu.pillai@...> wrote:
                    > how do I test for keeps calculating forever?

                    Answer: You don't.

                    I like the "evil coder" pattern:
                    - You write the next test.
                    - Then 'The Evil Coder' writes code that passes the test...
                    but is "wrong."

                    The trouble is, there is a limit to how much "evil" you can tolerate. If you allow "unlimited evil," you'll "be there all night" -- you'll never get anything done.

                    So...
                    The "evil" solution
                    - cannot be more complex than the "correct" solution.
                    - must comply (after reasonable refactoring) with all the rules of good style. For example -- no code duplication.

                    So...
                    if (x == 3) f();
                    if (x > 1) f();
                    if (x != 0) f();
                    is "too evil" when...
                    while (x-- > 0) f();
                    would suffice.
                  • Esko Luontola
                    A good principle is that to make the next test pass, the code must be made more general. See http://www.cs.helsinki.fi/u/luontola/tdd-2009/kalvot/A.1-TDD.pdf
                    Message 9 of 17 , Sep 17, 2011
                    View Source
                    • 0 Attachment
                      A good principle is that to make the next test pass, the code must be
                      made more general. See
                      http://www.cs.helsinki.fi/u/luontola/tdd-2009/kalvot/A.1-TDD.pdf page 4.


                      JeffGrigg wrote on 17.9.2011 5:53:
                      > The "evil" solution
                      > - cannot be more complex than the "correct" solution.
                      > - must comply (after reasonable refactoring) with all the rules of good
                      > style. For example -- no code duplication.
                      >
                      > So...
                      > if (x == 3) f();
                      > if (x > 1) f();
                      > if (x != 0) f();
                      > is "too evil" when...
                      > while (x-- > 0) f();
                      > would suffice.

                      --
                      Esko Luontola
                      www.orfjackal.net
                    • Amir Kolsky
                      Actually, going from the former to the latter is a refactoring to removing redundancy. The former is not evil ... So... if (x == 3) f(); if (x 1) f(); if
                      Message 10 of 17 , Sep 26, 2011
                      View Source
                      • 0 Attachment
                        Actually, going from the former to the latter is a refactoring to removing
                        redundancy.

                        The former is not "evil"



                        --- Gishu Pillai <gishu.pillai@...> wrote
                        So...
                        if (x == 3) f();
                        if (x > 1) f();
                        if (x != 0) f();
                        is "too evil" when...
                        while (x-- > 0) f();
                        would suffice.





                        [Non-text portions of this message have been removed]
                      • Neil
                        It would be a refactoring if the code did the same thing; it behaves differently when x is -1. It s hard to see how TDD could produce the initial code without
                        Message 11 of 17 , Sep 27, 2011
                        View Source
                        • 0 Attachment
                          It would be a refactoring if the code did the same thing; it behaves differently when x is -1. It's hard to see how TDD could produce the initial code without the "Evil Programmer" assumption/technique.

                          We need another test.

                          --- In testdrivendevelopment@yahoogroups.com, "Amir Kolsky" <kolsky@...> wrote:
                          >
                          > Actually, going from the former to the latter is a refactoring to removing
                          > redundancy.
                          >
                          > The former is not "evil"
                          >
                          >
                          >
                          > --- Gishu Pillai <gishu.pillai@> wrote
                          > So...
                          > if (x == 3) f();
                          > if (x > 1) f();
                          > if (x != 0) f();
                          > is "too evil" when...
                          > while (x-- > 0) f();
                          > would suffice.
                          >
                          >
                          >
                          >
                          >
                          > [Non-text portions of this message have been removed]
                          >
                        • Amir Kolsky
                          Oh.. so you re suggesting that the code was written just to satisfy the tests, in that case that is correct. It is the evil programmer . From:
                          Message 12 of 17 , Sep 27, 2011
                          View Source
                          • 0 Attachment
                            Oh.. so you're suggesting that the code was written just to satisfy the
                            tests, in that case that is correct. It is the "evil programmer".



                            From: testdrivendevelopment@yahoogroups.com
                            [mailto:testdrivendevelopment@yahoogroups.com] On Behalf Of Neil
                            Sent: Tuesday, September 27, 2011 8:44 AM
                            To: testdrivendevelopment@yahoogroups.com
                            Subject: Re: [TDD] What is the incremental TDD approach to reach a while
                            loop with a terminating clause ?





                            It would be a refactoring if the code did the same thing; it behaves
                            differently when x is -1. It's hard to see how TDD could produce the initial
                            code without the "Evil Programmer" assumption/technique.

                            We need another test.

                            --- In testdrivendevelopment@yahoogroups.com
                            <mailto:testdrivendevelopment%40yahoogroups.com> , "Amir Kolsky"
                            <kolsky@...> wrote:
                            >
                            > Actually, going from the former to the latter is a refactoring to removing
                            > redundancy.
                            >
                            > The former is not "evil"
                            >
                            >
                            >
                            > --- Gishu Pillai <gishu.pillai@> wrote
                            > So...
                            > if (x == 3) f();
                            > if (x > 1) f();
                            > if (x != 0) f();
                            > is "too evil" when...
                            > while (x-- > 0) f();
                            > would suffice.
                            >
                            >
                            >
                            >
                            >
                            > [Non-text portions of this message have been removed]
                            >





                            [Non-text portions of this message have been removed]
                          • Neil
                            Right, the code could have been produced by a programmer deliberately writing obfuscated code (for tests of x = 0, 1, 2, 3) and following Red, Green, but not
                            Message 13 of 17 , Sep 28, 2011
                            View Source
                            • 0 Attachment
                              Right, the code could have been produced by a programmer deliberately writing obfuscated code (for tests of x = 0, 1, 2, 3) and following "Red, Green, but not Refactor". As good a definition of Evil as any.

                              An additional test of x = -1 clarifies the specification. If the original code passes the "refactoring" won't.

                              --- In testdrivendevelopment@yahoogroups.com, "Amir Kolsky" <kolsky@...> wrote:
                              >
                              > Oh.. so you're suggesting that the code was written just to satisfy the
                              > tests, in that case that is correct. It is the "evil programmer".
                              >
                              >
                              >
                              > From: testdrivendevelopment@yahoogroups.com
                              > [mailto:testdrivendevelopment@yahoogroups.com] On Behalf Of Neil
                              > Sent: Tuesday, September 27, 2011 8:44 AM
                              > To: testdrivendevelopment@yahoogroups.com
                              > Subject: Re: [TDD] What is the incremental TDD approach to reach a while
                              > loop with a terminating clause ?
                              >
                              >
                              >
                              >
                              >
                              > It would be a refactoring if the code did the same thing; it behaves
                              > differently when x is -1. It's hard to see how TDD could produce the initial
                              > code without the "Evil Programmer" assumption/technique.
                              >
                              > We need another test.
                              >
                              > --- In testdrivendevelopment@yahoogroups.com
                              > <mailto:testdrivendevelopment%40yahoogroups.com> , "Amir Kolsky"
                              > <kolsky@> wrote:
                              > >
                              > > Actually, going from the former to the latter is a refactoring to removing
                              > > redundancy.
                              > >
                              > > The former is not "evil"
                              > >
                              > >
                              > >
                              > > --- Gishu Pillai <gishu.pillai@> wrote
                              > > So...
                              > > if (x == 3) f();
                              > > if (x > 1) f();
                              > > if (x != 0) f();
                              > > is "too evil" when...
                              > > while (x-- > 0) f();
                              > > would suffice.
                              > >
                              > >
                              > >
                              > >
                              > >
                              > > [Non-text portions of this message have been removed]
                              > >
                              >
                              >
                              >
                              >
                              >
                              > [Non-text portions of this message have been removed]
                              >
                            • JeffGrigg
                              Let s consider some code as it progresses... public void test() { assertEquals(1, Functions.addOne(0)); } public static int addOne(int value) { return 1; } OK.
                              Message 14 of 17 , Sep 29, 2011
                              View Source
                              • 0 Attachment
                                Let's consider some code as it progresses...

                                public void test() {
                                assertEquals(1, Functions.addOne(0));
                                }

                                public static int addOne(int value) {
                                return 1;
                                }

                                OK. It's the simplest code that passes the test.

                                public void test() {
                                assertEquals(1, Functions.addOne(0));
                                assertEquals(2, Functions.addOne(1));
                                }

                                public static int addOne(int value) {
                                if (value == 0)
                                return 1;
                                return 2;
                                }

                                A bit much, but still pretty conventional.

                                public void test() {
                                assertEquals(1, Functions.addOne(0));
                                assertEquals(2, Functions.addOne(1));
                                assertEquals(9, Functions.addOne(8));
                                }

                                public static int addOne(int value) {
                                if (value == 1)
                                return 2;
                                return value | 1;
                                }

                                Now that's just odd. You know, 'return value + 1;' would work too. How do you justify the added complexity?

                                Now we could keep playing this game >>> for some *possibly very large* number of iterations <<<. If I were really clever (and very "evil"), for each finite set of inputs (and required outputs) I could probably come up with some crazy algebraic expression that would return the correct result for the tested values, but "incorrect" results for most or all of the untested values. But there are over *four million* possible "int" values! (4,294,967,296 exactly) How many do I have to test to force the simple 'return value + 1;' implementation?

                                This leads me to limit the amount of evil allowed. TDD tests should protect us from unintentional regression: They should protect us from breaking changes that a later coder might *accidentally* make. They can't really protect us from all the most carefully crafted outright malicious bad coding practices that are possible.

                                How much testing would be needed to prevent this implementation:

                                public static int addOne(int value) {
                                if (value == -247397479)
                                return 6;
                                return value + 1;
                                }

                                ...*without* knowing that '-247397479' is the value that will be used by the coder!

                                I say that there is a role for "correct by inspection" in TDD. It really boils down to how much confidence you need to have that the code will produce the expected/correct results in all possible future cases.
                              • Alan Baljeu
                                The drive for a loop comes not from a list of test examples. It comes from a specification which talks generally and not with iterated details. In the bowling
                                Message 15 of 17 , Sep 29, 2011
                                View Source
                                • 0 Attachment
                                  The drive for a loop comes not from a list of test examples. It comes from a specification which talks generally and not with iterated details.

                                  In the bowling game, by the time you test the third frame test, you refactor to a loop because the spec is iterative. Seeing 3 tests without background, you have no idea if the pattern is supposed to continue or not. The stories tell you which way to go.

                                  Alan Baljeu

                                  On 2011-09-27, at 12:11 PM, "Amir Kolsky" <kolsky@...> wrote:

                                  > Oh.. so you're suggesting that the code was written just to satisfy the
                                  > tests, in that case that is correct. It is the "evil programmer".
                                  >
                                  > From: testdrivendevelopment@yahoogroups.com
                                  > [mailto:testdrivendevelopment@yahoogroups.com] On Behalf Of Neil
                                  > Sent: Tuesday, September 27, 2011 8:44 AM
                                  > To: testdrivendevelopment@yahoogroups.com
                                  > Subject: Re: [TDD] What is the incremental TDD approach to reach a while
                                  > loop with a terminating clause ?
                                  >
                                  > It would be a refactoring if the code did the same thing; it behaves
                                  > differently when x is -1. It's hard to see how TDD could produce the initial
                                  > code without the "Evil Programmer" assumption/technique.
                                  >
                                  > We need another test.
                                  >
                                  > --- In testdrivendevelopment@yahoogroups.com
                                  > <mailto:testdrivendevelopment%40yahoogroups.com> , "Amir Kolsky"
                                  > <kolsky@...> wrote:
                                  > >
                                  > > Actually, going from the former to the latter is a refactoring to removing
                                  > > redundancy.
                                  > >
                                  > > The former is not "evil"
                                  > >
                                  > >
                                  > >
                                  > > --- Gishu Pillai <gishu.pillai@> wrote
                                  > > So...
                                  > > if (x == 3) f();
                                  > > if (x > 1) f();
                                  > > if (x != 0) f();
                                  > > is "too evil" when...
                                  > > while (x-- > 0) f();
                                  > > would suffice.
                                  > >
                                  > >
                                  > >
                                  > >
                                  > >
                                  > > [Non-text portions of this message have been removed]
                                  > >
                                  >
                                  > [Non-text portions of this message have been removed]
                                  >
                                  >


                                  [Non-text portions of this message have been removed]
                                • Amir Kolsky
                                  I like this discussion. I think it leads to the essence of what TDD is about. TDD tests are not about preventing people from doing evil or stupid things.
                                  Message 16 of 17 , Sep 29, 2011
                                  View Source
                                  • 0 Attachment
                                    I like this discussion. I think it leads to the essence of what TDD is
                                    about. TDD 'tests' are not about preventing people from doing evil or stupid
                                    things. They are about specifying and clarifying what it is that needs to be
                                    done.



                                    From: testdrivendevelopment@yahoogroups.com
                                    [mailto:testdrivendevelopment@yahoogroups.com] On Behalf Of JeffGrigg
                                    Sent: Thursday, September 29, 2011 5:30 AM
                                    To: testdrivendevelopment@yahoogroups.com
                                    Subject: [TDD] Re: What is the incremental TDD approach to reach a while
                                    loop with a terminating clause ?





                                    Let's consider some code as it progresses...

                                    public void test() {
                                    assertEquals(1, Functions.addOne(0));
                                    }

                                    public static int addOne(int value) {
                                    return 1;
                                    }

                                    OK. It's the simplest code that passes the test.

                                    public void test() {
                                    assertEquals(1, Functions.addOne(0));
                                    assertEquals(2, Functions.addOne(1));
                                    }

                                    public static int addOne(int value) {
                                    if (value == 0)
                                    return 1;
                                    return 2;
                                    }

                                    A bit much, but still pretty conventional.

                                    public void test() {
                                    assertEquals(1, Functions.addOne(0));
                                    assertEquals(2, Functions.addOne(1));
                                    assertEquals(9, Functions.addOne(8));
                                    }

                                    public static int addOne(int value) {
                                    if (value == 1)
                                    return 2;
                                    return value | 1;
                                    }

                                    Now that's just odd. You know, 'return value + 1;' would work too. How do
                                    you justify the added complexity?

                                    Now we could keep playing this game >>> for some *possibly very large*
                                    number of iterations <<<. If I were really clever (and very "evil"), for
                                    each finite set of inputs (and required outputs) I could probably come up
                                    with some crazy algebraic expression that would return the correct result
                                    for the tested values, but "incorrect" results for most or all of the
                                    untested values. But there are over *four million* possible "int" values!
                                    (4,294,967,296 exactly) How many do I have to test to force the simple
                                    'return value + 1;' implementation?

                                    This leads me to limit the amount of evil allowed. TDD tests should protect
                                    us from unintentional regression: They should protect us from breaking
                                    changes that a later coder might *accidentally* make. They can't really
                                    protect us from all the most carefully crafted outright malicious bad coding
                                    practices that are possible.

                                    How much testing would be needed to prevent this implementation:

                                    public static int addOne(int value) {
                                    if (value == -247397479)
                                    return 6;
                                    return value + 1;
                                    }

                                    ...*without* knowing that '-247397479' is the value that will be used by the
                                    coder!

                                    I say that there is a role for "correct by inspection" in TDD. It really
                                    boils down to how much confidence you need to have that the code will
                                    produce the expected/correct results in all possible future cases.





                                    [Non-text portions of this message have been removed]
                                  • JeffGrigg
                                    Yes. Quite true. I find the evil coder game useful as a guide and motivation for good TDD. But can easily be taken to far and get dysfunctional, if taken
                                    Message 17 of 17 , Sep 30, 2011
                                    View Source
                                    • 0 Attachment
                                      Yes. Quite true.

                                      I find the "evil coder" game useful as a guide and motivation for good TDD. But can easily be taken to far and get dysfunctional, if taken too literally -- taken to extremes.


                                      --- "Amir Kolsky" <kolsky@...> wrote:
                                      > I like this discussion. I think it leads to the essence of
                                      > what TDD is about. TDD 'tests' are not about preventing
                                      > people from doing evil or stupid things. They are about
                                      > specifying and clarifying what it is that needs to be
                                      > done.


                                      For a more concrete, common and controversial example...

                                      How many tests should I have for the following Java beans property?

                                      public class Bean {
                                      private int property;
                                      public void setProperty(int value) {
                                      this.property = value;
                                      }
                                      public int getProperty() {
                                      return this.property;
                                      }
                                      }

                                      (Let's put aside the objection that properties are evil and a sign of bad object-oriented design. ;-)

                                      Depending on the project, and how critical it was to be sure that this code was correct, I've been happy with each one of the following answers:

                                      1. ZERO: The getter/setter pair is correct by inspection.

                                      2. One: Use any arbitrary integer value. (But not zero.)

                                      3. Two: This ensures that the value is not hard-coded in field initialization, the constructor, or in the getter.

                                      4. Several: A handful of values, representing boundary cases and common mainstream cases expected for this application.

                                      5. One massive reflection-based test that finds and loads each and every bean in the application, testing all properties it can find, with a couple sample values for each type, to catch all the getters that our CASE tool reverted to "return 0;" / "return null;", and all the setters where the CASE tool deleted the method bodies.

                                      I have seen each one of the options above defended by widely recognized and respected leaders of XP. All could be circumvented (without touching the tests) by any sufficiently evil coder.


                                      (And really, any actual lazy/stupid/evil coders will disable tests. I've seen it happen.)
                                    Your message has been successfully submitted and would be delivered to recipients shortly.