Privateメソッドをテストしたい時に気をつけたいこと #tddadventjp

このエントリーは、TDD Advent Calendar 2013 - Qiita [キータ]の参加エントリーです。

前日のエントリーは、d_nishiyama85 さんのCakePHP + PHPUnitでの TDD 超入門 - Qiita [キータ]でした。

TDD界隈では定期的に「Private メソッドのテストは必要か」という議論が巻き起こります。

プライベートメソッドのユニットテストは書かないもの? - QA@IT

privateメソッドのテストで気をつける3つのこと(Java + Groovy編) — うさぎ組

プライベートフィールドに対するテスト | Developers.IO

筆者は、「Publicなメソッドからの呼び出しでPrivateなメソッドはテストできるはず」という立場に立ちますが、レガシーコードを相手にしている場合など、Javaならパッケージプライベートなど、アクセス制限を緩めてテストをすることを否定するものではありません。そういう実装よりの作業を駆動するのも、またTDDの力です。

ただ、そういう場合に著者が心がけていることが一つだけあって、

アクセス制限を緩めるメソッドをステートレスにする

ということです。

つまり、

というクラス*1のdoExecuteメソッドをテストしたい時に、この状態だとdoExecuteメソッドがフィールドを書き換えていますが、これを

というように、引数、返り値を通してオブジェクトのやりとりをするようにするのです。このことによって、doExecuteメソッドがプロダクションコードから直接に呼ばれた場合でも、インスタンスの状態が意図しない状態になるのを避けることができます。

もちろん、このようなステートレスなロジックを導出できれば、テスト対象のロジックを別クラスのPublicなメソッドに切り出すようにリファクタリングすることもできるわけですが、これはTDDによって、望ましい設計が導出されることの一つの例といえるでしょう。

*1:相当いけてない設計ですが、Privateメソッドのテストをしたい時というのは覆おうにそうでしょう。