テストファーストでプログラミング

エンジニアのコト

学生の頃とプログラミングをする上で異なるところはテストを書くというところです。品質を担保(ちゃんと動いているかの証明)をするために働く上ではテストコードを書いています。

さらに最近ではテスト駆動開発(あまりわかっていないが)のようにやりたいことや修正したいことを先にテストに書いてしまってから実装を行うということをやっています。

例えば年齢に応じた映画館の料金を算出したいという要望があるとします。仕様は以下の通り。

  • 大人(23歳以上)は1,800円
  • 大学生・専門学生(18歳〜22歳)は1,500円
  • 中学・高校生(13歳〜17歳)は1,000円
  • それ以下は500円
    ※細かい料金体系は面倒なので年齢で区切りました

以下のようなクラスを考えるとします。

class PriceCalculator {
    static int calculate(int age) {
        return 0;
    }
}

まずやるのは、仕様をテストコードに反映させます。

class PriceCalculatorTest {
    private static final int ADULT_PRICE = 1800;
    private static final int COLLEGE_AND_PROFESSIONAL_STUDENT_PRICE = 1500;
    private static final int SCHOOL_STUDENT_PRICE = 1000;
    private static final int CHILD_PRICE = 500;

    @ParameterizedTest
    @MethodSource
    void shouldReturnValidPrice(int age, int price){
        assertThat(PriceCalculator.calculate(age), is(price));
    }

    static Stream<Arguments> shouldReturnValidPrice() {
        return Stream.of(
                arguments(23, ADULT_PRICE),
                arguments(22, COLLEGE_AND_PROFESSIONAL_STUDENT_PRICE),
                arguments(18, COLLEGE_AND_PROFESSIONAL_STUDENT_PRICE),
                arguments(17, SCHOOL_STUDENT_PRICE),
                arguments(13, SCHOOL_STUDENT_PRICE),
                arguments(12, CHILD_PRICE));
    }
}

このように書いてみると、年齢がマイナスの時や、年齢の上限はどこまで許せば良いんだろうという疑問が湧いてきます。

  • マイナスは例外だよね
  • 最高年齢は現状118歳だから200歳くらいまでを範囲としておいて、それ以上は例外にしちゃおう

などの考慮できていなかった仕様を考えることができます。そしてテストにも追加。

class PriceCalculatorTest {
...

    @ParameterizedTest
    @MethodSource
    void shouldThrow(int age) {
        assertThrows(IllegalArgumentException.class, () -> PriceCalculator.calculate(age));
    }

    static Stream<Arguments> shouldThrow() {
        return Stream.of(
                arguments(201),
                arguments(-1));
    }
}

これでやっと実装しはじめられますね。
こうやってテストファーストって素敵!

コメント

タイトルとURLをコピーしました