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

今週のタイムライン

  • ゴルフの打ちっぱなしに行った(日曜日)
  • 新入社員とドリームマネジメントをやった(月曜日)
  • 新たなAPIを使用した開発のための調査(火曜日)
  • Streamlitを用いたデータ可視化(水曜日)
  • Amazon Personalizeを用いたバッチでの推薦(木曜日)
  • テストファーストでプログラミング(金曜日)

話したいこと

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

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

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

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

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

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

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

// PriceCalculator.java
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));
    }
}

これでやっと実装しはじめられますね。 こうやってテストファーストで書くのがいいなって思いました。

最後に

人生初の打ちっぱなしに行きました。Youtubeをみてイメージしていきましたが。全然思ったように当たらず。。。新しいことをするのはいつになっても楽しい!

f:id:makky_emmanuel:20210418071613j:plain