Theory

Alternatively : you can watch the slides about the theory

TDD

TDD (Test Driven Development) is cool!

It makes sure we develop the right thing, step by step

Short version

flowchart TB
    start([Start])
    ==> red([Write only 1 failing test])
    ==> green([Make all tests pass])
    ==> refactor([Refactor])
    ==> finish([Finish])

    refactor -.->|Incomplete ?| red

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase

Long version

flowchart TB
    subgraph red[Red]
        direction LR

        fix_layout(( )) ==> write_a_test

        write_a_test[Write only 1 failing test]
        ==> run_tests{{Run tests}}

        run_tests
        -.->|Pass\nWrite another test| write_a_test
    end

    start([Start]) === fix_layout

    run_tests ==>|Fail| green([Green])

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase

    classDef fix_layout stroke:white,fill:transparent;
    class fix_layout fix_layout
flowchart TB
    subgraph green[Green]
        direction LR

        fix_layout(( )) ==> write_the_minimum_code

        write_the_minimum_code[Write the minimum code\nto make all tests pass]
        ==> run_tests{{Run tests}}

        run_tests
        -.->|Fail\nTry something else| write_the_minimum_code
    end

    red([Red]) === fix_layout

    run_tests ==>|Pass| refactor([Refactor])

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase

    classDef fix_layout stroke:white,fill:transparent;
    class fix_layout fix_layout
flowchart TB
    subgraph refactor[Refactor]
        direction LR

        rewrite_code[Rewrite code\nwithout changing the behavior]
        ==> run_tests{{Run tests}}
        -.->|Pass\nAnother things to refactor ?| rewrite_code

        run_tests
        -->|Fail\nChange something else| rewrite_code
    end

    green([Green]) ==> rewrite_code

    run_tests ==>|Pass| finish([Finish])
    run_tests -.->|Pass\nAnother feature to add ?| red([Red])

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase

    classDef fix_layout stroke:white,fill:transparent;
    class fix_layout fix_layout

TCR

TCR (test && commit || revert) is cool!

It encourages doing baby steps, reducing the waste when we are wrong

flowchart TB
    gamble{{Gambling on test results}}

    gamble ==>|Pass| commit(Commit)

    gamble -->|Fail| revert(Revert)
flowchart TB
    start([Start])
    ==> green([Change some code])
    ==> finish([Finish])

    green -.->|Incomplete ?| green

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

But it doesn't allow us to see the tests failing

So:

  • Maybe we test nothing (assert forgotten)

    def test_should_be_Buzz_given_5():
        input = 5
        actual = fizz_buzz(input)
        # Oops! Assert has been forgotten
    
  • Maybe we are testing something that is not the thing we should be testing

    it("should be Fizz given 3", () => {
      const input = 3;
      const actual = fizzBuzz(input);
      expect(input).toBe("Fizz");
      // Oops! Asserts on the input value instead of the actual value
    });
    

Detailed view

flowchart TB
    subgraph green[Green]
        direction TB

        start([Start])
        ==> change_code[Change some code]
        ==> run_tests{{"Run tests\n<code>test && commit || revert</code>"}}
        ==>|Pass| commit(Commit)
        ==> finish([Finish])

        commit
        -->|Another things to change ?| change_code

        run_tests
        -.->|Fail| revert(Revert)
        -.->|Try something else| change_code
    end

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

TCRDD

TCRDD = TCR + TDD

TCRDD blends the constraints of the two methods to benefit from their advantages

Therefore, TCRDD makes sure we develop the right thing, step by step, and we are encouraged to do so by baby steps, reducing the waste when we are wrong
flowchart TB
    red{{Write only 1 failing test}}
    green{{Make all tests pass}}
    refactor{{Refactor}}

    red ==>|Fail| red_commit(Commit) ==> green
    green ==>|Pass| green_commit(Commit) ==> refactor
    refactor ==>|Pass| refactor_commit(Commit)

    red -->|Pass| red_revert(Revert) --> red
    green -->|Fail| green_revert(Revert) --> green
    refactor -->|Fail| refactor_revert(Revert) --> refactor

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase
flowchart TB
    subgraph red[Red]
        direction LR

        fix_layout(( )) ==> write_a_test

        write_a_test[Write only 1 test]
        ==> gamble[/Gamble that the test fail\n<code>git gamble --red</code>/]
        ==> run_tests{{Actually run tests}}
        ==>|Fail| commit(Commit)

        run_tests
        -->|Pass| revert(Revert)
        -->|Write another test| write_a_test
    end

    start([Start]) ==> fix_layout

    commit ==> green([Green])

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase

    classDef fix_layout stroke:white,fill:transparent;
    class fix_layout fix_layout
flowchart TB
    subgraph green[Green]
        direction LR

        fix_layout(( )) ==> write_the_minimum_code

        write_the_minimum_code[Write the minimum code]
        ==> gamble[/Gamble that the tests pass\n<code>git gamble --green</code>/]
        ==> run_tests{{Actually run tests}}
        ==>|Pass| commit(Commit)

        run_tests
        -->|Fail| revert(Revert)
        -->|Try something else| write_the_minimum_code
    end

    red([Red]) ==> fix_layout

    commit ==> refactor([Refactor])

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase

    classDef fix_layout stroke:white,fill:transparent;
    class fix_layout fix_layout
flowchart TB
    subgraph refactor[Refactor]
        direction LR

        rewrite_code[Rewrite code\nwithout changing the behavior]
        ==> gamble[/Gamble that the tests pass\n<code>git gamble --refactor</code>/]
        ==> run_tests{{Actually run tests}}
        ==>|Pass| commit(Commit)
        -.->|Another things to refactor ?| rewrite_code

        run_tests
        -->|Fail| revert(Revert)
        -->|Change something else| rewrite_code
    end

    green([Green]) ==> rewrite_code

    commit ==> finish([Finish])
    commit -.->|Another feature to add ?| red([Red])

    classDef red_phase font-weight:bold,color:black,fill:coral;
    class red red_phase

    classDef green_phase font-weight:bold,color:black,fill:#1cba1c;
    class green green_phase

    classDef refactor_phase font-weight:bold,color:black,fill:#668cff;
    class refactor refactor_phase

    classDef fix_layout stroke:white,fill:transparent;
    class fix_layout fix_layout

git-gamble is a tool that helps to use the TCRDD method