1アサート 1失敗
単体テストのコードを書く上で、重要だと思うことのうち1つを書きます。
それは、TDDの手順の1つでもある、
”失敗するテストを書く”
です。
TDDまではいかなくてもいいから、とにかく単体テストコードを書きたい、
と思っている方や、
TDDに慣れすぎて、我流になりそうになっている方
にお伝えしたいです。
失敗するテストを書かないとどうなるか?
テストコードを書いた時間が無駄になります。
ミスのあるテストコードを書いてしまい、テストとしての役割を失います。
テストされていないので、実装側でミスがあってもわかりません。
さらに、開発者は”テスト成功”と思っているので、テストを書かないことより状況は悪いです。
よくあるテストコードのミス
間違ったAssert文を書いたり・・・
Assert.AreEqual(expect.PersonNumber, actual.PersonNumber); Assert.AreEqual(expect.PersonNumber, actual.ProjectNumber); // ↑ PeronNumberとProjectNumberを間違える。 Assert.AreEqual(expect.PersonNumber, expect.PersonNumber); // ↑ おまえは何を言っているんだ
そもそもテスト対象を間違えていたり・・・
// act Service.Search(request) // ↑本当はSearchInPageメソッドをテストしなくてはいけないけど、 // voidだったりすると気付かない。
Verify()を忘れたり・・・・
MyRepositoryMock.Setup(r => r.FindById(int)).Return(~~~); //Verifyを忘れる+他のミス=テストが”成功”となる場合がある。
どうするか
テストを走らせて、”失敗”を確認してから、実装コードを書きます。
1アサート 1失敗
下のようなよくある検索パラメータは、
必ず1つずつAssert文を書き、失敗を確認してから、実装コードを触ります。
成功したら初めて、次のAssert文を書きます。
Assert.AreEqual(expect.PersonNumber, actual.PersonNumber);
Assert.AreEqual(expect.ProjectNumber, actual.ProjectNumber);
Assert.AreEqual(expect.Name, actual.Name);
Assert.AreEqual(expect.ProjectNumber, actual.ProjectNumber);
// ↓みたいなコードは、”成功”となるので、間違いに気がつきます。
Assert.AreEqual(expect.PersonNumber, expect.PersonNumber);
1アサート1メソッド、という言葉は、この問題をも片付けてくれます。
最初は throw new Notimplementedexception();
どんなメソッド、プロパティも、throw new Notimplementedexception();
から始めます。
テスト失敗を確認した後、throw ... を外し、すぐにテスト”成功”を確認します。
モックも1つずつ確認
モックの呼び出しも、大事なテスト項目だったりします。
モックを書いた後は、”このモック呼び出されていないよー”という、”失敗”を確認すると良いと思います。
さらにUP
テスト”失敗”だけではなく、失敗した”理由”も確認します。
TDDになれると、テスト”失敗”だけを目視し、失敗の”理由”をスルーしてしまいます。
テスト失敗の”理由”がちゃんと意図したものであった場合、テストの書き方はきっと正解です。
//良くないかもしれない例 Assert.AreEqual(expect.Id, response.Persons.First().Id); //こっちの方がよいと思う例 Assert.IsNotNull(response); Assert.IsNotNull(response.Persons); var actual = response.Persons.First(); Assert.AreEqual(expect.Id, actual.Id);