TDD step by step

5273 ワード

TDDとは何か、字面がよく理解できて、かつての私は先にテストを書いて、それから実現を書いて、それからテストを走って、合格して、仕事を終えたと思っていました.今日厚かましく高級敏捷コンサルタントの力岩さんと一緒にPairを捕まえて、本当のTDDとは何かを教えてくれました.彼は小さなCaseの練習で私をTDDのドアに連れて行ってくれました.次に、彼がどのようにstep by step TDDをしたのかをまとめます.
需要:チェス、1つの車(Rook)、1つの王(King)があって、王と車が1本の横線あるいは1本の縦線にある時、将軍(checkmate)と呼ばれて、今TDDによってこのStoryを実現します.
1、テスト用例を作成し、
    @Test
    // 1: , 
    public void should_rook_checkmates_king_when_rook_and_king_in_the_same_line() throws Exception {
        // 2: , , rook king, , ?
        ChessBoard chessboard = new ChessBoard();
        King king = new King();
        Rook rook = new Rook();
        
        chessboard.addKing(king,3,4);
        chessboard.addRook(rook,4,4);
        
        assertThat(rook.isCheckmate(),is(true));
    }
もちろんこの时のコードはきっとコンパイルの间违いがあって、この时、私达はIDEのfix机能を通じてコンパイルを通すことができて、覚えていて、ただコンパイルを通すだけで、新しく加えたクラスを考えないでください、方法のテスト、设计など.主航路から逸脱しないでください.覚えておいてください.
2、テスト用例を実行する.Step 1を通過すると、いくつかのオブジェクトといくつかのdummyの方法が得られます.dummyなので、明らかにいろいろな間違いを報告します.Null Pointerとか.
3、最も簡単な方法でテストを通過させ、具体的な実現論理の実現を考慮しないで、コードの美観という問題に集中して、1つの点に集中して、テストを通過させて、私たちのこのテストを例にして、私たちは直接rookのisCheckmate方法をtrueに戻せばいいです.
4、テスト用例を補充して、明らかに、私たちの前の方法は簡単にテストの保護を迂回して、私たちのテスト用例のカバーが足りないことを説明します.次に、将軍がいない場合をカバーするテスト例を追加します.
    @Test
    public void should_not_rook_checkmates_king_when_rook_and_king_is_not_in_the_same_line() {
        ChessBoard chessboard = new ChessBoard();
        King king = new King();
        Rook rook = new Rook();

        chessboard.addKing(king,3,3);
        chessboard.addRook(rook,4,4);

        assertThat(rook.isCheckmate(),is(false));
    }

5、すべての試験用例を再走し、新しく補充したこの試験用例は合格できない.
6、失敗したテスト用例を修復し、失敗した用例を修復することに専念し、どのように簡単にどのようにするか、このStoryの下でrookのisCheckmate()方法を修正する必要があります.Step 1と同様に、最も簡単な方法でコンパイルを通過させる場合のRookクラスコードは以下の通りです.
public class Rook {
    private King king;
    private int x;
    private int y;

    public boolean isCheckmate() {
        // 1: , King 
        int king_x = getKing().getX();
        int king_y = getKing().getY();
        // 2: , 
        if(x == king_x || y==king_y){
            return true;
        }
        return false;
    }

    public King getKing() {
        return king;
    }
}
同時に、Kingクラスにも2つのdummyメソッドgetX()、getY()が追加する.
7、すべてのテストをやり直して、テストは依然として合格しないで、fixテストを続けて、一連の修正を入ってテストを合格させて、Rookのコードのプログラミングはこのようにしました
public class Rook {
    private King king;
    private int x;
    private int y;
    private ChessBoard chessboard;

    public boolean isCheckmate() {
        // 1: , King 
        int king_x = getKing().getX();
        int king_y = getKing().getY();
        // 2: , 
        if (x == king_x || y == king_y) {
            return true;
        }
        return false;
    }

    public King getKing() {
        // 3: king 
        return chessboard.getKing();
    }

    // 4:chessboard , setter , ? rook 
    public void setChessboard(ChessBoard chessboard) {
        this.chessboard = chessboard;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }
}
他にも多くの修正がリストされていません.
8、すべてのコードのロジックは完成して、テストは合格して、次はBad Smellの整理で、Rook類を例にして、明らかにBad Smellはいくつかの点があります
public class Rook {
    //smell 1: 
    private King king;
    //smell 2: x,y , 
    private int x;
    private int y;
    private ChessBoard chessboard;

    public boolean isCheckmate() {
        int king_x = getKing().getX();
        int king_y = getKing().getY();
        //smell 3:if , 
        //smell 4:  if inline 
        if (x == king_x || y == king_y) {
            return true;
        }
        return false;
    }.....
Bad Smellを整理するたびにテストを実行し、breakdownテストを避けるために、小さなステップで速く走ることを覚えておいてください.
9、最後に完成したRook類を展示する
public class Rook {
    private ChessBoard chessboard;
    private ChessBoardPoint position;

    public boolean isCheckmate() {
        return isRookCheckmate();
    }

    private boolean isRookCheckmate() {
        return position.getX() == getKing().getPosition().getX() || position.getY() == getKing().getPosition().getY();
    }

    public King getKing() {
        return chessboard.getKing();
    }

    public void setChessboard(ChessBoard chessboard) {
        this.chessboard = chessboard;
    }

    public void setChessboardPosition(ChessBoardPoint chessBoardPoint) {
        this.position = chessBoardPoint;
    }
}
もちろんこれは終点ではありませんが、起点だけで、bad smellがたくさんあるかもしれません.このTDD全体の過程で、コードが一歩一歩美しくなるのを見ているのはとても楽しい過程です.
まとめ:今日のPairは、最も深く感じているのは、集中して、思想は永遠に1本の線の上で、現在関与していないものをあまり考えないことです.