Open3

【Class】private メソッドの Unit Test(単体テスト)はどうするべきかについて

ピン留めされたアイテム
まさぴょん🐱まさぴょん🐱

問題提起

同じチームのy-oさんからの一言📝

y-oさんが、本質的なことを言ってくれているので、ありがたいっす🙏
それに対する自分のレス📝

見やすいように文字メモ📝

あるmoduleのテストを書く目的は、そのmoduleの外部からcallされる関数たち (moduleのAPIと呼ぶ) がちゃんと機能しているかを担保する、というもの。
この目的を達成すればどうでも良い。
この目的を達成するためにprivateの (APIではない) functionをテストしたほうが、総合的に良い
(例えば、メンテンナンス性が高い、とか) のならそうしたら良い、というだけですね。

目的ベースで考えるのが重要なので「べき論」で思考停止するのは危険ですね。。。🤔
目的が変われば、最適なアプローチも変わる📝

(誰かが出した答えをそのまま採用するのではなく、目的から毎回自分で考えるのが良いのではないか、ということが言いたい。)

まじで、この通りだと思います🙏
「目的ベースでどうするべきか?」をケースごとに自分で考えればいい📝
目的に応じた柔軟な対応をする📝

ピン留めされたアイテム
まさぴょん🐱まさぴょん🐱

結局、あなたはどっち派なの?

正直、自分自身はどっち派閥でもないので、ケースバイケースで柔軟に対応すればいいのでは?
という軟弱派閥っす・・・🥺

ただ、次のような考え方に一定同意しています🤔

「プライベートかどうかと関数にユニットテストがほしいかは別問題」

引用元:
https://nunulk-blog-to-kill-time.hatenablog.com/entry/why-i-write-unittest-for-private-method#:~:text=プライベートかどうかと関数にユニットテストがほしいかは別問題

まさぴょん🐱まさぴょん🐱

private メソッドの Unit Test(単体テスト)はどうするべきか?

private関数のテストを作成する際に、

  1. その private アクセスの関数をテストすべきなのか?
  2. それとも、その private アクセスの関数を使用している関数をテストすべきなのか?

GPT o1-Previewに質問してみた👀🌟

クラス内のprivate関数をテストする際の一般的なベストプラクティスとしては、直接private関数をテストするのではなく、そのprivate関数を使用しているpublic関数を通じてテストすることが推奨されます。

理由は以下の通りです:

1. カプセル化の尊重

private関数はクラスの内部実装の一部であり、外部から直接アクセスすることを意図していません。
テストコードで直接アクセスすると、クラスのカプセル化を破壊し、実装の詳細に依存したテストになってしまいます。

2. 保守性の向上

private関数は実装の変更に伴って頻繁に変更される可能性があります。
これらに直接依存するテストは、実装の変更時にテストコードも変更する必要があり、保守性が低下します。

3. 外部動作の検証

ユーザーにとって重要なのはクラスの外部から見た動作です。
public関数をテストすることで、クラス全体の機能が正しく動作しているかを確認できます。

ただし、以下のような場合にはprivate関数を直接テストすることを検討してもよいでしょう

複雑なロジックが含まれる場合

private関数内に複雑なアルゴリズムや重要なビジネスロジックが含まれており、個別にテストすることでバグを早期に発見できる場合。

テスト容易性の向上

特定のケースでpublic関数からではテストが難しい場合。

それでも、可能であればリファクタリングを行い、そのロジックを別のクラスやモジュールのpublic関数として切り出すことで、テストしやすくする方法もあります。

まとめ

基本的にはpublic関数を通じてテストを行い、クラスの外部インターフェースが期待通りに動作することを確認すべきです。
これにより、テストが実装の詳細に過度に依存せず、保守性と信頼性の高いテストコードを維持できます。

その他、意見を調査する

強い持論があるわけではないので、追加で検索して調べてみましたが、
private関数のテストを「書く派閥 / 書かない派閥」で意見が分かれるようでした。。。🤔

書かない派閥

https://t-wada.hatenablog.jp/entry/should-we-test-private-methods

https://zenn.dev/1048576/articles/b09c14fe4cc960

書く派閥

https://blog.ojisan.io/oreha-private-func-nimo-test-kaku/

https://nunulk-blog-to-kill-time.hatenablog.com/entry/why-i-write-unittest-for-private-method

検索して、記事をサラッと読みましたが、
o1-Previewが言うように、private関数のテストを許容する / しないは、ケースバイケースだと思っていて、
原則、単体テストは public な関数のテスト経由で担保するように作成する
private 関数があまりにも複雑で、単体テストを追加した方がいい場合は、例外的にテストを追加する
のような方向性がいいように感じました。。。🤔

参考・引用

https://t-wada.hatenablog.jp/entry/should-we-test-private-methods

https://zenn.dev/1048576/articles/b09c14fe4cc960

https://blog.ojisan.io/oreha-private-func-nimo-test-kaku/

https://nunulk-blog-to-kill-time.hatenablog.com/entry/why-i-write-unittest-for-private-method