GROUPエンジニアブログです。>2013年11月12日16:19カテゴリprogrammingプライベートメソッドのテストは必要ない!!こんにちは、RPAの関口です。最近週に一度、来年の新卒達と一緒にTDDをやりながらワイワイガヤガヤしております。いう話題がありました。プライベートメソッドのテストについてはプライベートメソッドのユニットテストは書かないもの?がよくまとまっていると思います。プライベートメソッドのテスト方法について考える中で「TDDの手順に従えばプライベートメソッドのテストがしたくなることは無い」のではないか?と思うようになりました。プライベートメソッドはリファクタリングの結果現れる!数値の配列を渡すと平均を計算して返してくれる機能を持ったクラス、AverageCalculatorを作りたいとします。平均計算の手順をまとめると以下のようになります。配列の合計値を計算する合計値を配列の要素数で割って返すここで「よし!まずは配列の合計値を計算する機能をつけよう!」と思って次のようなテストを書くとcalcSumメソッドの可視性について途中計算でしか使わない合計値の計算は、プライベートメソッドにしたいでもプライベートメソッドだとテストのためにReflectionを使う必要があって面倒という悩みが発生してしまいます。最初「平均値を返すメソッドを追加」しようと思っていたのに「合計値を返すメソッドを追加」しようとしたためです。平均値計算の手順はあくまで手順、初心に帰って平均値を返すテストを書きましょう。合計値計算のメソッドは分離したいなぁと思ってリファクタリングする際に、calcSumという名のプライベートメソッドが自然と現れます。このプライベートなcalcSumメソッドのためにテストを追加する必要はありません。中身がどのような実装になっていようと外部から呼び出されるcalcAverageメソッドが期待通りの結果を返してくれれば良いのです。calcSumメソッドはパブリックなcalcAverageメソッドを通じてテストされている、とも言えます。パブリックメソッド経由でテストする多くの場合、そのクラスのパブリックメソッド経由でプライベートメソッドのテストも同時に行えます。テストできているか不安があるならカバレッジを測定しましょう。プライベートメソッドのユニットテストは書かないもの?より。calcSumの代わりに大変複雑な処理だった時はどうするの?そのような場合、いきなりcalcAverage相当のメソッドを作るの事は難しいでしょう。calcSumのメソッドの追加を行う必要が出てくるかと思います。そのcalcSumはAverageCalculatorクラスがやるべき事なのでしょうか?実はSumCalculatorという名の新しいクラスを作って、その中にパブリックメソッドとして書くのが正しいのではないでしょうか?別クラスのパブリックメソッドとするプライベートなメソッドのテストを書きたいということは、実はテスト対象の責務が多すぎることを示唆している場合があります。テストがどうしても書きたい場合は、その責務はテスト対象のプライベートな振る舞いでは無く、誰かのパブリックな振る舞いなのでしょう。テスト対象のプライベートメソッドを「クラスの抽出」や「メソッドの移動」を使って、テスト対象のコラボレータのパブリックメソッドとして抽出し、普通にパブリックメソッドとしてテストしましょう。プライベートメソッドのユニットテストは書かないもの?より。他の方法ここまで書いておいてなんですがcalcSumのテストと実装をパブリックで書くcalcAverageのテストと実装をパブリックで書くリファクタリングでcalcSumメソッドの可視性をプライベートにして、calcSumのテストは削除という手もあるかと思います。いうかこちらのほうが自然ですね。書いたテストを捨ててしまうのは勿体無い気がしますが、実装中に書いたテストと最後に残すテストを同じにしなければならないというルールはありません。calcSumはcalcAverageを通してテストされているので良しとしましょう。そんなこんなでプライベートメソッドのテストは必要ない!!・・・のではないかと最近思い始めました。