🖥

プライベートメソッドのテストを書くな (プログラミングの作法)

2023/09/01に公開

書かない理由: パブリックメソッドのテストで必要十分だから

「美味しいカレーを作るメソッド」があるとする。

この場合にテストで保証したいのは「美味しいカレーが出来ること」だけなのだ。
どんな包丁や鍋を使うかは全く関係ない。

どんな包丁の使い方をしたかはお客には関係ないのだ。
包丁の使い方までテストしたら、レトルトカレーを使うことにした場合にどうする?

書かない理由: リファクタリングの邪魔になる

テスト対象が内部実装の詳細にまで及んでいると、テストに縛られてリファクタリング出来なくなる。
テストが実装を縛るなどあってはならないことである。

仮にプライベートメソッドの構成が変わるたびにそのテストを変更するとしても大層な手間だ。

僕らはテストをするためにテストをしているわけではない。機能保証のためにテストをしているのだ。

書かない理由: 書く理由がないから

書いたほうが良い妥当な理由を思い浮かばないのであればそれは書かなくて良いということだ。

「なんとなく書く」「テストが簡単になるから書く」という理由であれば見直した方が良い。

書かない理由: テストファーストじゃないから

もしプライベートメソッドのテストの是非について迷ったら「仮にテストファーストならどうしていた?」と考えてみよう。

テストファーストで開発する時に考慮するのはインプットとアウトプットである。
コードの詳細も決まっていない段階でプライベートメソッドのテストなど思いもつかないだろう。

テストファーストで作りようのないテストとは不要なテストだ。

ここにパブリックメソッドfooがある。
(fooメソッドのテストもあるとする)

class Example
  def foo
     # 色々な処理
     # 色々な処理
     # 色々な処理
  end
end

あなたはこの処理をリファクタリングした。
新しくプライベートメソッドbarを作り、パブリックメソッドbarから呼び出すようにしたのだ。

class Example
  def foo
     # 色々な処理
     bar
     # 色々な処理
  end

  private

  def bar
     # 色々な処理
  end
end

ここであなたはプライベートメソッドbarのテストも追加しようとする。
ちょっと待て。本当に必要か?

今までのfooのテストで動作を保証できていたのに、何故新しくテストを追加するのだ?
たしかにコードはリファクタリングしたが、やっていることは何ひとつ変わっていないはずだ。

メソッドの数だけ律儀にテストを作る必要は何だ?

(そして時が経ち)

あなたはやはりメソッドを元に戻すことにした。

class Example
  def foo
     # 色々な処理
     # 色々な処理
     # 色々な処理
  end
end

プライベートメソッドbarは削除した。
だからそれに対応するテストも削除した。

だがメソッドが1個消えることで不要または実行不可能になるテストであれば、そもそも最初から不要だったのではないだろうか。

それでもプライベートメソッドのテストが必要な場合

クラス設計の見直しタイミングなのかもしれない。

プライベートなメソッドのテストを書きたいということは、実はテスト対象の責務が多すぎることを示唆している場合があります。テストがどうしても書きたい場合は、その責務はテスト対象のプライベートな振る舞いではなく、他の誰かのパブリックな振る舞いなのでしょう。テスト対象のプライベートメソッドを「クラスの抽出」や「メソッド/関数の移動」を使って、テスト対象のコラボレータのパブリックメソッドとして抽出し、普通にパブリックメソッドとしてテストしましょう。

https://t-wada.hatenablog.jp/entry/should-we-test-private-methods#別クラスのパブリックメソッドとする

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

Twitter

https://twitter.com/YumaInaura

公開日時

2022-08-30

Discussion