2020-12-20

プライベートメソッドテストすべきか

「すべきでない」というのがたぶん多数派

テストすべきでない理由としてだいたい次の理由があげられる。

プライベートメソッド関数テストする必要は無いと考えていますプライベートメソッドは、実装の詳細であるからです。

多くの場合、そのクラスパブリックメソッド経由でプライベートメソッドテストも同時に行えます

プライベートメソッドのテストは書かないもの? - t-wadaのブログ

ほとんどの場合プライベート メソッドテストする必要はありません。 プライベート メソッド実装の詳細です。

プライベート メソッドがある場合は、パブリック メソッドを見つけて、そのメソッドに対してテスト記述します。

単体テストを記述するためのベスト プラクティス - .NET | Microsoft Docs

プライベートメソッドテストするな」と強く主張されるのは、ケント・ベックの影響もあるかもしれない。

例えばtwitterで、パブリックメソッドにだけテストを書き、テスト必要なほどプライベートメソッドが複雑ならそれを別のオブジェクトに切り出す必要があると発言している(twitter/kentbeck)ように、プライベートメソッドテストに強く反対している。

またベックの書いたSUnit(xUnitの源流にあたる)には「ひとつテストひとつオブジェクトで表し、それによってテスト独立性を高める」というアイディアが使われている(そのアイディアを実現するためにとても複雑な設計をしている Simple Smalltalk Testing: With Patterns)。テスト自身ひとつオブジェクトとして独立しているなら、テスト対象となるオブジェクトプライベートメソッドテストできないのは当然のことになる。

しかし「プライベートメソッドテストがしたい(したくなることがある)」と感じる人も相当数いる。

そう感じる人にとってはむしろここからが本題で、

問題になる。

テストファーストで開発するなら手を動かしながら軽い気持ちで書きたい。

例えそのクラスがprivateメソッド依存関係があっても。

コンストラクタインジェクションされたクラスのprivate メソッドでもテストファーストしたい - Qiita

privateなルーチンの自動テストは面倒だ。実際にコーディングするとき最初publicにしておいてテストしてうまく動いていそうならprivateにするのだけど、この「いそう」がくせ者。いっそのことすべてpublicにしたくなる。

私は元々メソッドはprivateにしない主義なのでメソッド場合問題ないのだけれど、ファイル内の「関数」が問題になる。和了計算だと和了形判定とか符計算とか和了役判定とか単体でテストしたい内部関数が山ほどある。(twitter/koba0367)

private メソッドテストすべきか問題原則論だけだと袋小路に入りがちだから、private メソッドテストしたくなる具体的な場面について議論したほうがいいと思う。

自分レビューでよく見る例としては、複数の public メソッドの重複部分を private メソッド抽出した結果、濃い private メソッドと薄い public メソッドが一対多関係になる場合が挙げられる。設計としては間違っていないし、わざわざ public メソッド経由でテストする意義があるかというと微妙。(twitter/ts7i)

きれいなインターフェースを作ろうとすればするほどpublicメソッドじゃない部分に複雑性を追いやることになり、壊れた時に手戻りが大きすぎると思ったら、プライベートバックドア開けてでもテスト書くようにしてます (twitter/mizchi)

しかプライベートメソッドに対するテストを書こうとすると大概リフレクションなどで可視性の制限をすり抜けるとかメソッド可視性を変更するといった回りくどさやコストの導入が必要になるので、じゃあプライベートに対するテストはそうしたコストに見合うのかが問題になる。

伊藤さんの答えは「原則書かないほうがいいという大前提のうえで、どうしてもというときは、"これはテストのためにpublic"にしているというコメントの上でpublicにする」だった。

自分は「テスタビリティのためにメソッドをpublicにする」っていう"実プログラム挙動を変えること"の方が、「privateなメソッドテストコードのみsendで叩く」よりも怖いって思ってることに気がついた。(twitter/highwide)


メソッドプライベートパブリックかという話とそれをテストするかどうかは別問題だろという意見もある。

単体テストホワイトボックステストだとするなら、publicかprivateかでテストの有無が変わるのは明らかにおかしいだろ。ややこしいロジックはprivateに隠蔽すべきだが、そこがテストできないなんて。 (twitter/kmaebashi)

private メソッドテストするかどうか? まず最初に言っておきたいのは public/private は抽象設計問題であって、テストすべきかどうかとは当然無関係だろうということ。(twitter/qeigoi)

特定言語の貧弱な機能思考制限を受けて誤った結論を出している典型的な例。

"テストを書くべき"と"上位層から可視性"は直交する概念

https://b.hatena.ne.jp/entry/4684049296462116226/comment/megumin1

テスト粒度メソッドアクセス権は独立したものなので、「プライベートメソッドテストすべきか否か」という切り方自体ナンセンスではあるのだが、現実問題としてはアクセス権がテストに影響するので難しい。(twitter/AoiMoe)

private メソッドテストはすべきかどうかというより、「できるべき」であって、それができないというのも、ある種、言語機能テストインピーダンスミスマッチと言えるのではないだろうか、と思っている。(twitter/aetos382)


プライベートメソッドテストがしやす言語での意見

RustやGoではプライベートメソッドに対するテスト簡単にできる。

そのためかプライベートメソッドテストすることに対して拒否反応があまりないようだ。

Rustのテストファイル内とtests/以下の2箇所に書ける。

テストには開発用のホワイトボックステスト仕様確認用のブラックボックステストがあり、前者をファイル内に、後者をtests/に書けば良い。

例えば度々議論になるプライベート関数テストについてはもちろんホワイトボックステスト。(twitter/blackenedgold)

Rustではプライベートに対して何の手間もなくテストが書ける。

概念的にはプライベートに対するテストは外部コードではなく内部コードの一部として見るべきなのだろう。

Rust入門を兼ねてプロジェクト・オイラーの問題を解く - 再帰の反復blog

Rustでprivateなメソッドテストを書きたいなら、そのメソッドのすぐ隣に書けば内部アクセスになるから普通に書けるよ、ってのは目からウロコだった。できるだけ近いところにテストを書こうっていう文化と相まって最高。(twitter/kuy)

Rustみたいに単体テストは同ファイルに書ければいいのに

assertionチックにprivateメソッドのすぐ下にテスト書きたい

ドキュメントにもなるし (twitter/takaya_tim)

Rust のようにユニットテストプロダクションに混ぜる方式はおれもいいと思ってて、テストプロダクションを分離することで private 関数テストができない問題があるけど(テストしたければクラスを分けよ/メソッドを公開せよ/テスト必要なし、に分かれるよね)、そもそもこの議論不要になるよね (twitter/nunulk)


go言語だとプライベートメソッドテスト普通にやりますね。(twitter/mattn_jp)

昨日「private method の単体テストは書くか否か」という話題がちょいとあったのだが、わしは当然書く感じの昨今を送ってきたもんで何で書かんのやくらいに思ってたんだけど、Go だと private なやつのテストが書きやすいってのがデカそう。(twitter/pankona)

golangのテスト書いてたけど、テストプログラム名前空間(パッケージ)が、対象プログラムと一緒で、そのためプライベートメソッドでもテストできるの良い感じ (twitter/74th)

Goテストコードテスト対象と同じパッケージにすればエクスポートしてない関数でもなんでもテストコードから参照できるんだけど、これってプライベートメソッドテストすべきか議論するよりテスト書けと言われているようで好き。(twitter/plan9user)

プライベートメソッドテストするか?」とは別にドキュメントソースコードと同じファイルに書いていい(文芸プログラミング)なら、単体テストテスト対象と同じファイルに書いてもいいのでは?」というのも論点になるかもしれない。

  • ワイはパブリックメソッドのテストすら一度も書いたことないやで

    • わたしは実際にデータ流し込んだり画面叩いてテストしてるのでテストコードなんか書いたことないです。

  • こういうの見るとやっぱりRustやGoが今後の潮流になるのは避けられないな

  • テストが必要なほどプライベートメソッドが複雑ならそれを別のオブジェクトに切り出す必要がある これでいいと思うんだけど。 テストが必要になる単位で、単純な責務になるよう...

    • 計算やロジックが複雑かつ特定のオブジェクトに密に関わっている場合、元記事に引かれている例でいえば麻雀の点数計算のようなものとかあるいは準数値演算や組み合わせアルゴリズ...

記事への反応(ブックマークコメント)

ログイン ユーザー登録
ようこそ ゲスト さん