JUnitのテストメソッド名をどういう風につけたらいいかなー?

って話になって、チーム内で盛り上がった。例えばこんな感じのテストを書きたい時。

「ジュースを買う」メソッドに、お金とジュースの番号を入力したらそのジュースが返されて、在庫が一個減る。

メソッドはこんな感じかな?

Juice buyJuice(int inputAmount, int juiceId)

これでどう?

buyJuice_shouldReturnJuice_whenInputAmountIs130Yen

え?でもこれだと、なんかこう・・・在庫が減ってることとかは表せてなくない?

えー、じゃあこういう感じ?

buyJuice_shouldReturnSelectedJuiceAndOneLessInventory_whenInputAmountIs130YenAndSelectedIdIsValid

いや、長いね・・・。

ふむ。。。全部をメソッド名に書かない方が幸せなんじゃない?

メソッド名で全てを表そうとするのは諦めて、メソッドを呼び出すときの事前条件だけにしてみようか?

こうなるはず、って部分はテストメソッドの中身を見よう、ってことで。

buyJuiceWhenInputAmountIsEqualToOrMoreThan130YenAndSelectedIdIsValid

んー。ジュースが買える状態は正常だとして、省略してみようか。

buyJuice

で、異常な状態のテストは書いてみると

buyJuiceWithShortMoney

buyJuiceWithInvalidJuiceId

うん

悪くないんじゃないかなー。

  • buyJuice
  • buyJuiceWithShortMoney
  • buyJuiceWithInvalidJuiceId

という感じに落ち着いた。

つまり「事前条件をメソッド名にして、その条件のときに何が起こるかはテストメソッド内で表されるのを読むことにしてみよう」ってなった。

本みっけた

この話をした後に、うろうろしてたらいい感じの本見つけた。

www.safaribooksonline.com

ざっくり説明すると。

prefixスタイル

testってプレフィックスつけるネーミングルールの時代があったけど、今はアノテーションがあるのでtestプレフィックスは特に意味ないよね。

メソッド名で表現するのがいいよスタイル

addItem_hasListOfSortedItems_listContainsAdditionalItemAndIsSorted

Naming standards for unit tests - Blog - Osherove

should使うスタイル

shouldContainAdditionalItemAndIsSortedWhenAddItemOnListOfSortedItems

複数行スタイル

やっぱり、1行で表現しようとするのに無理があるんじゃね?てことでBDDスタイル。1行ずつがJUnitのテストケースにマッピングされる。

Given the timeline contains two sorted items

 When a new item gets added to the timeline

 Then the timeline contains all old items
  And the timeline contains the newly added one
  And the timeline is sorted correctly

GivenWhenThen

メントスタイル

BDDのをコメントで。

@Test
public void setFetchCountExceedsLowerBound() {
  // given
  int originalFetchCount = timeline.getFetchCount();

  // when
  timeline.setFetchCount( Timeline.FETCH_COUNT_LOWER_BOUND - 1 );

  // then
  assertEquals( originalFetchCount, timeline.getFetchCount() );
}

そもそもメソッド名って

テスト対象のメソッドの動きを変更した時にメソッド名の変更を追随させるの大変よね。

んで、そういう視点で言うと、事後条件って結構頻繁に変わるけど、事前条件ってそこまで変わらんし、それをメソッド名にしてみたらどうかね。

ってことで、

事前条件スタイル

[UnitOfWork_StateUnderTest]

TimelineTest:

addItem
addItemToEmptyList
addItemWithMissingDate
addItemIfThresholdHasBeenReached
addItemWithNull
...
setFetchCount
setFetchCountExceedsLowerBound
setFetchCountExceedsUpperBound
...

どうかね?

おー

同じところに落ち着いてるー

おまけ

1,2年前まで日本語でテストメソッド名書いてたので情報をいっぱい詰められたんだけどね。最近は海外出身の人と仕事をすることが増えてきたので英語で書くようになったー。