カプセル化■プライベートメソッドをテストする方法
■ このスレッドは過去ログ倉庫に格納されています
■短い回答 プライベートをテストしたい場合は設計に問題があるので、パブリックに変更してテストしましょう ■これに対する(変な人の)驚いた反論 プライベートを一時的にパブリックにして、テストが終わったら プライベートに戻すなんてやるわけないだろw ↑誰もそんなコトしろなんて言ってない ■テスト専門家による回答 t-wadaのブログ https://t-wada.hatenablog.jp/entry/should-we-test-private-methods 短くまとめると、プライベートなメソッドのテストを書く必要は 無い と考えています。 ほとんどのプライベートメソッドはパブリックメソッド経由でテストできるからです。 プライベートメソッドは実装の詳細であり、自動テストのターゲットとなる「外部から見た振る舞い」ではありません。 プライベートなメソッドのテストに関しては、4つの考え方があります。 ・パブリックメソッド経由でテストする ・別クラスのパブリックメソッドとする ・テスト対象の可視性を(やや)上げる ・プライベートのまま、リフレクションでアクセスしてテストを書く パブリックメソッド経由でテストする 多くの場合、そのクラスのパブリックメソッド経由でプライベートメソッドのテストも同時に行えます。テストできているか不安があるならテストカバレッジを確認しましょう。 別クラスのパブリックメソッドとする プライベートなメソッドのテストを書きたいということは、実はテスト対象の責務が多すぎることを示唆している場合があります。 テストがどうしても書きたい場合は、その責務はテスト対象のプライベートな振る舞いではなく、他の誰かのパブリックな振る舞いなのでしょう。
クソコード例。こんなコード書いてるやつが、privateのテストで パブリックに変更してテストするのはおかしいとか言ってる(笑) lenが配列(笑)理由 int型にはnullが入れられないから(笑) https://mevius.5ch.net/test/read.cgi/tech/1592491656/805 ずれるかもしれないが下のような場合、privateにnullを突っ込んだらヌルポだが privateをわざわざコード弄ってまで別にテストするようなことは少なくとも ビジネスソフトでは知ってる限り無い。組み込みとかは知らんし必要ならやれば良いけど。 class ChinTester { public void testChin(int[] len) { if (len==null){System.out.println("You are a woman"); return;} if (len.length<11){ uncS(len);} else{funcB(len);} return;} private void funcS(int[] len){ if (len.length<9){System.out.println("Smallest"); }else{System.out.println("Smaller");} return;} private void funcB(int[] len){ if (len.length<14){System.out.println("Medium");} else if (len.length<16){System.out.println("Bigger"); }else{ System.out.println("Wow!");} return;} } 983 名前:デフォルトの名無しさん[] 投稿日:2020/07/05(日) 14:18:27.81 ID:9F15TCk0 [68/74] 正直あの短さでOOかどうかと(スタティックでインスタンス化もないコードだが)言うのは 不毛だけどID:JiRnWiGCの組み込みおじさんのがOO感はあるよ。 で、staticで出されてもprivateのテストがどうかと言う話には全く寄与しないわけだが、 じゃあ逆に、>>805 のチンコテストのfuncSとfuncBはどうやってテストするの? パブリック経由で全パターンと言うことならこれでこの話はおしまい。 パブリック経由でやりましょう。 違うと言うなら具体的にコードでおながいします。 >>4 への回答 設計に問題があるので、コードを修正しましょう。 修正すれば自然とpublicになります↓ 926 名前:デフォルトの名無しさん[] 投稿日:2020/07/05(日) 12:20:23.64 ID:MQ9nuMmc [21/53] >>805 こう書いた方が良いと思うの https://paiza.io/projects/mPhqBnYZnQukkW6HY9LmOQ >>5 の補足、これはまだプライベートですが 普通はMainクラスにコードをごちゃごちゃ書かないので judgeLengthを含むクラスを作成します。 そしてmainから呼び出します。 必然的にjudgeLengthメソッドはパブリックになります。 >>6 judgeLengthをpublicにしてよいかどうか、オブジェクトをわけて良いかどうかは微妙なところで publicにした場合って他のオブジェクトからも参照可能になってしまうので そこの依存があとあとjudgeLengthの修正をできなくする可能性があるので privateにするっていうのは他のオブジェクトから依存させないようにして独立させる意味もあるので テストするためにpublicにしますっていうのは僕はやっぱり反対ですね 僕が書いたように同じオブジェクトにテストコードも書いちゃえば良いと思います >>7 微妙でもなんでもねーよ Mainクラスに関係ない処理を入れるな これは小さいサンプルだが、大きくなった時 Mainクラスに、そんな処理はいってたらおかしいだろ なんで(大きくなったコードの)その他の部分は別のクラスにあるのに この処理だけMainクラスにあるんだ?って >>9 Mainクラスと関係ある処理だからMainクラスにあるんじゃよ Mainクラスからしかアクセスしないからprivateなんじゃよ テストするためにpublicにするのはおかしいのじゃよ >>10 Mainクラスと関係ある処理だから? じゃあ名前が悪いよね。 誰が「Mainクラス」と聞いて その中にある処理を想像できるんだ?w >>11 えっと、前にも言ったけどpaizaはMainという名前じゃないと動かないんだよ Mainとわけてクラスを作ることもできるけど面倒だからやらなかっただけ 普通のプログラマならpaizaの制約ぐらい知ってるだろうし説明する必要もないと思ってた 君の無知さを想像できなかった僕のミスだ >>12 だから分けろって。設計がおかしいだろ。 Mainクラスにメインの処理を入れるな 設計が悪いって言ってるのになんで理解できない? プライベートをテストしたいっていうのは 本質的に設計が悪いってことが理解できないやつ もしくは設計なんてしたことがないやつなんだろう >>16 君は簡単なロジックしか組む機会がなかった幸せな人だと思うよ 僕は君が羨ましい、幸せな人生を歩んでいるね 僕は下痢便コードをこうするべきって修正したよ paizaで動くようにMainというクラス名に変えたけどね paizaだからそうなるよねってみんな理解してくれるものと思ってた paizaを知らない木偶の坊がクラス名に文句つけてきたとき僕は絶望した まだやってたのかw >>5 みたいな下痢便コードが出てきた時点で 「あっ・・・(察し)」でスレ終了でしょ こうするべきだと思うならやれば良いがな 自分でやりもせず他人に文句いうだけの人間は木偶の坊のそしりを免れないよ Mainに他のクラスの処理を全て同居させる 全部Mainにあるから呼び出せるよね?と publicメソッドをprivateメソッドに変更 publicメソッドはMainのみ! と言い あぁ、プライベートメソッドのテストができない〜と嘆く(笑) アホなのか?自分でテストできないようにクソ設計に変更して 自業自得じゃんw ×>>5 みたいな下痢便コードが出てきた時点で ○>>3 みたいな下痢便コードが出てきた時点で すまん訂正 >>24 君はまだMainという名前のレトリックから抜け出せてないように見える paizaで動かすためにMainという名前にしたってだけだから 実際にはそれなりの名前になるでしょう privateメソッドは当然クラスと関係あるものになるでしょうということ Mainという名前に囚われ過ぎておられるように見受けられる 自分だったらこう書くのにって言うのがあるならそれを実践してみるべきかと思われます おそらく設計とは何かを知らずに、 ただ動けばいいと思ってるんだろう テストしやすく設計するのも 設計の一つ >>27 Mainを勘違いしてたアホが何抜かしとんねん >>26 だからテストしやすようにjudgeLengthメソッドを含んだ クラスを作るだけ >>28 勘違いしてませんが? Main関数とロジックを同居させるなの意味がわかりませんか? 謙虚になれや オブジェクト指向とは礼儀作法と心得よ >>27 Mainクラス云々については単に誤解してると思うけど このスレの登場人物じゃあ多分おまいが一番マシな感性持ってそうやなw このスレの主旨的にはprivateメソッドのテストコードを書きたいんだよね? 書く必要がないって主張は違うよね? 結局のところ何でもあり 僕は単体テストさえやってないからね スレタイと書いてあることがチグハグで趣旨が解りづらいな。 スレタイに従えば、privateを呼び出したいみたいだが、>>1 の発言を見るとprivateの呼び出しは推奨しないように見える。 まぁ、私も推奨しないけど。 という訳で、適当に独り言を語ってみる。 単体テストって、例えば... Queueという名前のクラスがあって、そのクラスの中に Enqueue、Dequeue、Peek、Clearメソッドが定義されていたら、それらメソッドを呼び出して、その結果を予想するコード(テストコード)を書いて実行させる方法がオブジェクト指向プログラマーにとって一般的だと思うけど...その際にprivateメソッド(内部実装)をテストコードから呼び出さないといけない理由がわからん。 t-wadaさんがどういう人か調べてみたところ、日本が誇るJavascript使いなんだな。 すると、t-wadaさんの立場ではprivateをテストしないというのは全くもって正しいと思う。 privateでやる事はライブラリを呼び出すだけなので、テストするのは無駄。 しかし、他の言語ではアルゴリズムの実装という仕事があり、アルゴリズムの実装をテストしたいという要求は常に存在する。 例えば多くのパーサーは公開メンバとしてpush()を持つ。 文字をプッシュする関数だ。 めぼしい公開メンバはこの程度しかない。 しかしその裏に100を超える非公開のメンバがあっても驚かない。 非決定性のパーサはその程度のメンバを持つ。 文字をプッシュする公開メンバ一つで、多くの状態、多くのメンバをテストするのは面倒な話で、何方にせよ非公開のメンバ、非公開の状態変数について知識が無ければテストできない。 だったら内部の状態について一切テストしないか、内部の状態を直接テストするか二択となる。 内部の状態についてはブラックボックスとして扱うべきと述べているのがt-wadaさんだが、それでは実装が非常に困難だ。 パーサーの話ついでに、もう一つアイデアを提供しよう。 決定性パーサーでは、還元が行われたとき、外部に影響を及ぼす。 通常この時点で意味動作を行う。 t-wadaさんは、この時に限りテストを行うべきであり、それ以外でテストを行ってはいけないと述べる。 つまり、シフトが行われるときはテストしてはならない。 今どの状態にあるかは外部にかかわりのない事なのでテストとしてはならない。 入力文字として改行を与えるとどの状態に遷移するかテストしてはならない。 これは厳しすぎやしないだろうか? 詳細を知ってはならないということは、どの状態を経てその記号が生み出されたのか知ってはならないということであり、これは非常につらい。 システム利用者がシステム作者に「詳細を検査しちゃだめじゃないか!」と怒っているように見える。 クリスマスプレゼントが何かを知るために箱を振って音を聞くよりも、箱を開けて直接見るほうが早い。 箱を振って「プレゼントはプリキュア」と観測できたとする。 これは果たしてどの程度もっともらしいだろうか? privateなメソッドの動きが仕様書で定義されてたらテストしなくちゃいけないし書いてなかったら書く必要無い そしてprivateなメソッドの仕様まで定めた仕様書は俺は見たことない >>47 うるせーばか。文句を言うために都合の良いデータを調べてきたに決まってるだろ >>50 仕様書には普通アクセス修飾子を何にするかなんて書かないからね 設計書にもそんな細かいこと書かないでしょ 書いてない関数を勝手に作るなんて禁止に決まってるだろ テストのためだけに関数は作らない 関数を作るのに許可がいるなんてすごいことだからとてもすごいと思いました >>1 にはテストとしか書かれていないけど、記事元はユニットテスト(単体テスト)の話だよね? >>57 ユニットテスト以外でメソッドのテストなんかするのか? >>3 このコード出すやつが混じってるんだろ? 議論無駄やん >>59 自分であたかも他のテストがあるように言っておいて変な話だがだが、しないね。 単体テストで不具合を見つけた後、デバッガを使って更にどこにバグの原因が潜んでいるのか分析することはあるけど、それはもはやテストではなくデバッグだしね。 てかさ、タイトルがカプセル化なのに、なんで>>3 も>>5 もテストコード実行場所とテストコード実行場所が同じ階層に記述されているのさ。 ミス。テストコード実行場所とテスト対象が同じ階層に書かれているのはなんで?だ。 wadaは忘れろ privateだからテストしなくていいなどという都合のいい法則は存在しない だがprivateだからとテストをしないキチガイは確実に存在するのだ 一意見を急に”理論”とか”法則”とか言う方が頭どうかしてるよ t-wadaはTDDをわかりやすく解説することに定評があるだけ ただいろんな会社からテストのコンサルティングで雇われる程度には有能だから 君たちの意見よりは一般には受け入れられやすい 和田理論被害者の会ニューヨーク支部もひつよう。 とてもひつよう。 前スレで王家秘伝のレシピ教えたのに。 誰も活用しないんだな。 >>61 > 単体テストで不具合を見つけた後、デバッガを使って更にどこにバグの原因が潜んでいるのか分析することはあるけど、それはもはやテストではなくデバッグだしね。 単体テストで不具合を見つけた後にするもの=デバッグ デバッグの前にする不具合を見るけるもの=テスト だろ? テストの後にするデバッグは、テストではなくデバッグだしねって あんた何言ってるの? オブジェクト指向の話をしよう 彡ミ ↓↓↓ 彡 ⌒ ミ (´・ω・`) 頭皮、毛髪に触れるものは全て検査する >>74 そんな細かいこと気にすんなよ。揚げ足取りめ。 よく単体テストは不具合を見つけるためにやると言われるが、別視点の考え方もあるって話だ。 ここでは些細な話だったな。 >>74 > テストの後にするデバッグは、テストではなくデバッグだしねって > あんた何言ってるの? テストの後にするデバッグはデバッグでしかないと思いますけど、どこに突っ込みを入れたいのですか? >>77 ↓ここにツッコミを入れたい > それはもはやテストではなくデバッグだしね。 >>60 そうそれ あれ書く奴とは1byteたりとも意見交換したくないわ >>78 (テストとデバッグは違う作業だと思うのだが) もしかすると、バグの原因を調査する作業はテストに含まれるかどうかって話かな? >>81 当たり前だろ? テストではなくデバッグだしねっていうのが意味わからんって言ってる テストはテストだろ 突っ込みどころねーじゃんw それなのに喧嘩腰で突っ込んで周囲に突っ込まれただけか。 privateメソッドのチェックもできない奴は出荷すんぞ privateのチェックって具体的にどうやるの? Queueというクラスをテストするケースを例に教えて。 queue = Queue() queue.push(17) asserEqual( queue.length, 1) a = queue.pop() assertEqual( a, 17) assertEqual( quele.length, 0) だいたいこんなもんだろ。 >>88 おお、俺もそんなのイメージしてた。 そんなコードでpublic経由でprivateを呼び、ついでにカバレッジテストとか済ませる感じかな。 ...だったらいいのだが、なーんか、このスレの人達の言動を見ていると怪しいんだよな。 88は別に問題ないけど。 カバレッジテストをするかどうかは、ケースバイケース。どちらでもいいとして、一番気にしているのは、そもそも>>1 の記事主に批判的な人はオブジェクト指向を理解しているのか?という点。 怪しいというのは、そこね。 >>85 デバッグはテストじゃなくてデバッグだしねと言われても当たり前としか言えないし、 デバッグの前にやるテストはテストだしねで終わりだろ? >>91 言いたいことは何となく理解できる。 「私以外はみんな馬鹿」 ってことだろ? つまりキミの主な言語はJava。 どうやら図星だったようですね。 Javaではありがちなんですよ。 >>91 とまぁ、>>92 みたいな低能が蔓延るスレで世間の常識は通用しないってことが証明されちゃったわけだ。 立ち去るがいい。 >>92 何がいいたいの(笑) 俺を馬鹿にしたいのかな?でも文章がそうなってないな。 >>95 馬鹿にしてない。 馬鹿に付ける薬はない。 オブジェクト指向はダメなんじゃないか?というのが前スレの趣旨で、非公開のメンバは何のためにあるの?テストどうするの?という話になった。 それに対する回答が「非公開のメンバはブラックボックスとして扱いテストしてはならない」という和田メソッドが示された。 それに対して「入力に使われる一つのメンバしかもたないパーサ」という実例を挙げ、「文字列を入力され構文木を返すような状態機械のテストが非常に困難」という話が出た。 この場合、内部を観測できないのであれば、すべての入力の組み合わせ(受理できない入力もテストするなら、それは無限である)に対して、すべての取りうる構文木のセットを検査しなければならない。 つまりそれは太陽系よりもはるかに広く、銀河の向こうまでテストするということである。 それに対して「オブジェクト指向を知らない」などと抜けたことを言うので、「Java!」という結論が出された。 > それに対する回答が「非公開のメンバはブラックボックスとして扱いテストしてはならない」という和田メソッドが示された。 正確には ・パブリックメソッド経由でテストする ・別クラスのパブリックメソッドとする ・テスト対象の可視性を(やや)上げる ・プライベートのまま、リフレクションでアクセスしてテストを書く まとめ 繰り返すと、プライベートなメソッドや関数をテストする必要は無いと考えています。 プライベートなメソッドは、実装の詳細であるからです。 実装の詳細ならむしろテストが必要だと思うのだけど なんで詳細だからテストしなくて良いのだろう t_wada被害者の会に僕も入会させてください ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる