- テスト駆動開発はなぜ流行らなかったのか?2
839 :デフォルトの名無しさん[sage]:2014/09/13(土) 11:43:55.91 ID:JUTGZGvm - あー、いまやっとTDDの問題点とどうすればいいか閃いたよ。
TDDはプライベートメソッドに対してやればいいんだ。 どういうことかというとTDDは、小さくRed→Greenを繰り返すわけだけど、 その小さい開発サイクルに対してパブリックメソッドのテストでは量が多すぎるんだ。 パブリックメソッドの多くはさらに小さいプライベートメソッドを沢山呼んでいる。 それはパブリックメソッドが複雑だから、それをさらに小さい部分に分けてシンプルにするため。 いきなりパブリックメソッドを作るわけじゃなくて、プライベートメソッドから作る。 その小さいプライベートメソッドを開発してる時に、Red→Greenしないの? いや、これこそがTDDでするべきことでしょ? でもユニットテストの考え方ではプライベートメソッドのテストをしないから、 パブリックメソッドにしないとある程度できないとテストがかけない。 TDDを使わない方法、たとえばprintデバッグによる目視ではこのプライベートメソッドの 動作確認をよくやってる。実行する時に、プライベートメソッドへの引数に直接数値を入れて そして戻り値をprintする。これはまさにプライベートメソッドのテストそのもの。 そうTDDに本当に必要なのはプライベートメソッドのテストなんだよ。 パブリックメソッドのテストでは範囲が広すぎてテストが書けるようになるまでタイムラグが出来る。 パブリックメソッドのテストを書こうとしている。これがTDDができない根本的な原因。
|
- テスト駆動開発はなぜ流行らなかったのか?2
840 :デフォルトの名無しさん[sage]:2014/09/13(土) 11:44:33.50 ID:JUTGZGvm - そしてユニットテストとの違いはリファクタリングで
テストコードが変わったりなくなったりするということ。 ユニットテストではパブリックメソッドそのものの仕様が変わらない限りテストコードは変わらないが、 プライベートメソッドは頻繁に仕様が変わったりなくなったりするのだから当然の話。 そしてTDDによる"1つの"開発が終わる時というのは、パブリックメソッドができあがるまで。 パブリックメソッドできあがったとき、プライベートメソッドのテストとは別に パブリックメソッドのテストもできているのが理想的だが、必ずしもそうはならないだろう。 多くのプライベートメソッドのテストがあって、プライベートメソッドを呼び出してるだけの 単純なパブリックメソッドのテストコードは無いか少ないことが多い。 この後プライベートメソッドのテストは、変更を加えてパブリックメソッドのテストに変更してもいい。 ユニットテスト的にはプライベートメソッドのテストはしないのだから破棄しても構わないが、 将来の修正に備えて残しておくのもいいだろう。 ユニットテストのテストは外部のインターフェースに対するテスト、 TDDとは内部の開発を行うためのテスト(というより動作確認に近い)
|
- テスト駆動開発はなぜ流行らなかったのか?2
841 :デフォルトの名無しさん[sage]:2014/09/13(土) 11:50:51.07 ID:JUTGZGvm - さて、どうやってプライベートメソッドのテストを書くかだけど、
これはユニットテストのフレームワークの機能を使わないほうがいいだろうね。 フレームワークによってはプライベートメソッドのテスト機能があるが それを使わない。 代わりにクラスにtest()とかなんでもいいんで1個メソッドを用意する。 このメソッドは別にユニットテストでテストするわけじゃない。 引数を返したり、特定の機能を提供するものじゃない。 単に外部から呼び出すためだけのもの。 そしてクラスのtest()メソッドの中で、 プライベートメソッドを直接読んで、戻り値を確認確認は単純にifとかでいいよ。 なんだっていいどうせ破棄してもいいものなんだから。 もちろん将来に備えて綺麗に整理しておくとか、ユニットテストに 変更しやすいような命令を使うとかはありかもしれないが、 それはTDDとは直接関係のない話。
|
- テスト駆動開発はなぜ流行らなかったのか?2
843 :デフォルトの名無しさん[sage]:2014/09/13(土) 12:00:50.55 ID:JUTGZGvm - >>842
http://docs.python.jp/2/library/doctest.html > そこで Python 2.4 では doctest の Tester クラスを廃止し、モジュールや doctest の > 入ったテキストファイルから unittest テストスイートを作成できるような > 二つの関数を doctest 側で提供するようにしました。 って書いてあるように、doctestはユニットテストを含む テストを生成するための機能だしね。
|
- テスト駆動開発はなぜ流行らなかったのか?2
845 :デフォルトの名無しさん[sage]:2014/09/13(土) 12:19:53.66 ID:JUTGZGvm - 今日は頭が冴えてるw
ユニットテストではやりにくくて printデバッグでやりやすいのにこのようなテストがある function foo(a, b) { aとbをいろいろ計算してcに代入 if (cが○○なら) { _hoge(); } else { _hage(); } } こんな感じのコードで、a, bにとある値を入れた時 _hoge()が呼び出されるか? という確認。 これはprintデバッグをすれば簡単に確認できることだが テストコードでは気軽にできない。モックを使えって話になるだろうが プライベートメソッドのモック??? 継承してプライベートメソッドを オーバーライド??? 言語によっては出来ないし。 これさ、よくデバッグログを有効にしたらログを出力する機能ってあるじゃん? そのログを解析すればいいんじゃないか? _hoge()実行前、もしくは_hoge()の中でデバッグログを出力するようにしておいて そのログを解析してテスト。(もちろんログは解析しやすい構造にしておくのがベター) やってることはprintデバッグと同じなんだけどね。 デバッグログとしてモジュールがもってる公式な機能とすることで自動テスト可能にする。 ユニットテストでも使える技だと思う。
|
- テスト駆動開発はなぜ流行らなかったのか?2
847 :デフォルトの名無しさん[sage]:2014/09/13(土) 12:28:38.72 ID:JUTGZGvm - >>844
> プライベートメソッドのテストが必要な時点で、クラス(モジュール)の規模が大きくなりすぎているように思える。 プライベートメソッドの存在否定をしているわけじゃないでしょ? まず事実としてプライベートメソッドはできる。 そりゃ単純なユーティリティクラスとかならいらないだろう。 そういうユーティリティクラスはテスト簡単で、それなら俺もテストもTDDもできる。 問題は少し複雑になったもの。 複雑なものはプライベートメソッドは絶対にできる。 その規模になったとたん、TDDがしづらくなるのが現実。 プライベートメソッドをパブリックメソッドにして別モジュールにするのはいいアイデアだよ? 最終的にはそうすることになるかもしれない。でも今は最終的な話をしてるんじゃない。 作ってる初期段階の話なんだ。TDDは初期段階からRed→Greenをするものなんだから。 開発中に小さな単位で作ってる時に、プライベートメソッドができたからってすぐに 別クラスを作ろうっていうのは間違った考え方。 小さなプライベートメソッドごときで、クラスに分けるか? なんて責務を持ったクラスしよう?などと考えるのはやり過ぎだろう。 最初は小さく作って、それから大きくしていくのがいい。大きくなったら 別クラスに分けるのもありだし実際俺もそうしてる。
|
- テスト駆動開発はなぜ流行らなかったのか?2
849 :デフォルトの名無しさん[sage]:2014/09/13(土) 12:32:32.50 ID:JUTGZGvm - >>844
あと、 > プライベートメソッドのテストが必要な時点で これおかしな言い方だよね? まるでプライベートメソッドはテストをしなくていいような言い方。 「プライベートメソッドは "ユニット" テストをしなくていい。」 ならば賛成だが、TDDにおけるRed→Greenは プライベートメソッドでもやるべきだろう? むしろプライベートメソッドこそやるべきことだろう? じゃないと小さくRed→Greenなんてできないよ。
|
- テスト駆動開発はなぜ流行らなかったのか?2
851 :デフォルトの名無しさん[sage]:2014/09/13(土) 12:39:11.42 ID:JUTGZGvm - >>848
> 使い捨てのプライベートテストを計画量の何倍も書くなんてやってられるか > どんだけコストかけるつもりだ その考え方の間違いが、TDDできない原因なの。 プライベートメソッドは絶対にできるし、無駄になるからそのテストコードを書かない。 →だからパブリックメソッドのテストしか書きません。 →プライベートメソッド単位で小さくRed→Greenしません。 開発時はプライベートメソッドでも目視で動作確認している。 TDDはこれをコードに置き換えただけ。 単純な1作業だからこそ破棄しても良くなる。(そもそも目視=使い捨て) 小さくRed→Greenをするために、TDDのテストコードと ユニットテストコードは別のライフサイクルであつかわないといけない。
|
- テスト駆動開発はなぜ流行らなかったのか?2
852 :デフォルトの名無しさん[sage]:2014/09/13(土) 12:49:00.56 ID:JUTGZGvm - 閃きの後いろいろ考えてるけど、デバッグログを使ったテストはいいアイデアかも。
デバッグログを使わなくてもアスペクト指向的に メソッドの前後に処理を割りこませることが出来るのは知ってる。 もちろん動的言語だったらメソッドを動的に入れ替えたりとかできる。 でもこれらの欠点は、メソッド単位でしかやれないってこと。 あとそれをやるためのコードがいちいち面倒くさい。 デバッグログならたった一行書くだけで任意の時点でその時の状態を表示できる。 コードの途中で確認したいと思った内容を自由に制御可能になる。 ようするにprintデバッグは偉大だってことw
|
- テスト駆動開発はなぜ流行らなかったのか?2
854 :デフォルトの名無しさん[sage]:2014/09/13(土) 14:14:31.94 ID:JUTGZGvm - >>853
ただの簡単な例にそんなに必死にならなくてもw ね、たったこれだけなのに大きくなりすぎでしょ。 最初はシンプルに作ろうぜ。
|
- テスト駆動開発はなぜ流行らなかったのか?2
855 :デフォルトの名無しさん[sage]:2014/09/13(土) 14:22:24.36 ID:JUTGZGvm - 実際に開発していればわかるけど、
複雑なコードというのは最初から複雑なのではなくて シンプルなコードに変更を加えていって複雑になる。 ここからもTDDはプライベートメソッド対して 行うものでテストは使い捨て同然だってことがわかるよね。 コードが長くなっていく。じゃあ分割しよう。 よし別クラスのパブリックメソッドに変更だ! いきなりこうする奴はいない。 コードが長くなれば、同じクラスのプライベートメソッドにする。 じゃあテストはどうなる? テストもプライベートメソッド用に分割し変更しないといけない。 TDDでは小さい単位でRed→Greenを繰り返すわけで頻繁に変更が入る。 ユニットテストのようなモジュール単位でのテストでは 開発に対しては粒度が大きすぎるんだよ。
|
- テスト駆動開発はなぜ流行らなかったのか?2
857 :デフォルトの名無しさん[sage]:2014/09/13(土) 14:59:02.52 ID:JUTGZGvm - 反論さえ言わない人に興味はないな。
|
- テスト駆動開発はなぜ流行らなかったのか?2
859 :デフォルトの名無しさん[sage]:2014/09/13(土) 15:20:49.51 ID:JUTGZGvm - >>858
だからなんで自分の都合のいい例で 過剰な設計してるの?
|