アジャイル開発現場におけるTips:仕様書としてのテスト
はじめに
#中佐藤です。今回は私が考えたものではなく、現場でとある開発者が使っていたテクニックです。他の方にも参考になると思い、共有します。
それは「テストを仕様書代わりにすること」です。どういうことか、解説していきます。
どんな場面で使えるか
#開発真っ最中のあるチームに初心者が配属されました。「新人研修でJavaは勉強しました」「でも実開発は未経験です」というレベルの新人です。この初心者の育成の意味が多分にあり、現場に配属されてきました。
こういう場合って、教育する側は結構「加減」が難しいのです。チームに最初からいるなら全員で一緒に育っていけるのですが、途中参加というのが特に悩ましい。どこまで手取り足取り教えるべきか。放っておくと行き詰って先に進まないし、あまりに逐一教えると本人のためにならない。指導側の工数もかなりかかります。この状況で指導側のテックリードが使ったのが、「仕様書の代わりとしてテストコードを使う」ことでした。
どのように使うか
#例を見ていただいたほうがわかりやすいですね。以下のようなテストコードをテックリードが初心者に示し、このテストが通るように実装コードを書くことを指示したと考えてください。
- Javaを使っていますが他の言語にも置き換えて考えられます
- 開発環境はセットアップ済と考えてください
- 以下コード内import文は省略しています
class DivideTest {
private MathUtil mathUtil;
@BeforeEach
void setUp() {
mathUtil = new MathUtil();
}
@Test
@DisplayName("通常の割り算")
void test6Divide2Equal3() throws CalculationException {
int expected = 3;
int actual = mathUtil.divide(6, 2);
assertEquals(expected, actual);
}
@Test
@DisplayName("ゼロ除算😱")
void testAnyDivide0OccuresException() {
assertThrows(CalculationException.class, () -> mathUtil.divide(1, 0));
}
}
このやり方のいいところは、満たすべき仕様が非常に明確であることです。下手に自然言語(日本語)でやるべきことを示すより明確です。誤解や行き違いがほぼ発生しません。実装すべきクラス名(MathUtil)、メソッド名(divide())、中で実装すべき内容がすぐわかります。上の例ではDisplayNameアノーテーションを使いましたが、もうちょっと説明が必要な相手ならば、Javadoc用のコメントを入れてもいいでしょう。
実際、育成される側にとっても良かったようで、数か月後のふりかえりで「あのやり方はありがたかった」という意見が出ました。ちょっと自分で考える開発者ならば、「あれ、割り切れない場合はどうするんだろう」と気付き、さらにコードで対話が進むかもしれません。
発展形
#このやり方にはさらに先があります。これである程度相手が慣れたなと思ったところで、テックリードはテストの示し方を日本語の箇条書きに変えたのです。例えばこんなふうに:
- 割り算の実装。クラス名とメソッド名は○○に置いてある設計図から読み取る
- 整数のみに対応。割り切れる場合のテスト
- 割り切れない場合は切り捨てになるテスト
- ゼロ除算の場合は例外が出るテスト
育成対象者はここから自分でテストコードを作り、実装コードを作ります。
さらに慣れてきたらこのようなテストケースの洗い出しから育成対象者が行い、テックリードがそれをレビューする、という形に発展させれば、テックリードに必要な育成のための工数は減らしていけます。
みなさんのチームでは
#実際にこのやり方をしているチームを見たのはコロナ禍以前で、ひとつの部屋に集まって開発していた頃ですが、リモートワークが当たり前になったからこそこのやり方って有効かも、と思っています。
リモートだとなかなか気軽に聞きづらい。初心者から忙しそうなテックリードに質問するのは特に遠慮がちになると思います。テックリードも忙しさにかまけて指示が曖昧になりがち。結果的にプルリク時のレビューで指摘が増え、時間がかかります。これをエンジニアらしく、プログラミング言語を共通語としてコミュニケーションしようというのが、このやり方です。
今回は単体レベルのテストの話ですが、さらに大きなレベルのテストでも似たようなことはできます。自分たちだったらこんな風に使えるかも、と応用してみてください。