web-dev-qa-db-ja.com

コピーアンドペーストされたテストコード:これはどれほど悪いですか?

私の現在の仕事は主に、私たちが取り組んでいるさまざまなアプリケーションのGUIテストコードを書くことです。ただし、テスト内で多くのコードをコピーして貼り付ける傾向があることがわかりました。この理由は、テストしている領域は繰り返しを必要とするほど十分似ている傾向があるが、コードをメソッドまたはオブジェクトにカプセル化するには十分に似ていませんです。クラスまたはメソッドをより広範囲に使用しようとすると、テストを維持するのがより面倒になり、そもそも最初から書くのが非常に困難になることがあります。

その代わり、私は通常、テストコードの大きなチャンクを1つのセクションからコピーして別のセクションに貼り付け、必要な小さな変更を加えます。 OO原理や関数の使用など、より構造化されたコーディング方法は使用していません。

他のコーダーはテストコードを書くときにこのように感じますか?明らかに私はDRYとYAGNIの原則に従う必要がありますが、テストコード(とにかくGUIテスト用の自動テストコード)はこれらの原則に従うのが難しいことがわかります。それとも、さらにコーディングの練習が必要ですか?物事を行うためのより良い全体的なシステム?

編集:私が使用しているツールはSilkTestです。これは4Testと呼ばれる独自の言語です。同様に、これらのテストは主にWindowsデスクトップアプリケーションを対象としていますが、このセットアップを使用してWebアプリもテストしました。

12
joshin4colours

コピー貼り付けそして編集テストケースはしばしば問題ありません。

テストでは、外部依存関係をできるだけ少なくし、できるだけ簡単にする必要があります。テストケースは時間とともに変化する傾向があり、以前はほとんど同じテストケースが突然分岐する場合があります。他のケースを壊すことを心配することなく1つのテストケースを更新することは良いことです。

もちろん、多くのテストケースで同一であり、同時に変更する必要があるボイラープレートコードは除外できます。

23
9000

カットアンドペーストすることはまだかなり悪いです。いくつか問題があります。

コピーアンドペーストされたすべてのコードの変更が必要なものに対して脆弱であるため、テストは脆弱になる可能性があります。すべてのテストを書き直す必要がありますか?

ロジックをテスト外のヘルパーメソッドにカプセル化できない場合、それらのヘルパーメソッド自体のテストを作成することはできません。テストをテストするためにコードを壊さなければならないので、テストメソッドのテストを書くことは、通常、価値のあるものにするのが難しいです。しかし、あなたはcan単体テストヘルパーメソッドです。

テストが読みにくくなる可能性があります。コピーされたコードの大きなブロックは、説明的な名前のヘルパーメソッドの呼び出しよりも読みにくい場合があります。

私がリストしたものはすべてmayが問題になるものです。実際にそれらがどれも見つからない場合ある問題がある場合はもちろん問題ありません。

7
psr

私はあなたに同意していました。しかし、その後、時間の経過とともに、私が行ったすべての変更(特に単体テストでのDIの変更)を変更するには、多数のテストが必要であり、面倒でした。今では、テストを書くときでも、DRYの学校に加入しています。

GUIテストでは、繰り返しコードを減らすために PageObject pattern を確認することをお勧めします。

4
pdr

XUnitパターンをピックアップすることをお勧めします。その本を活用し始めるまで、私はまったく同じ問題を抱えていました。 Object Mother パターンは、シナリオに最も役立つように聞こえます。

他の人が述べたように、このセットアップコードを適切にカプセル化するのは面倒かもしれませんが、コピーして貼り付けたすべての場所で変更する必要があるのはさらに難しいことです。

2
Michael Brown

人々がそうすることができるとき、繰り返しを試み、制限するべきですか?はい。ただし、見返りは状況によって異なります。これは「ベストプラクティス」の議論に戻る可能性があります。しかし、問題はこの状況であなたにとって何が最善かということです。すべてのルールには例外があります。

私が尋ねる2つの事柄は次のとおりです。1)UATでテストされているこの機能が変更される可能性はどのくらいありますか?変更される可能性が低い場合は、コードの各セットを更新しなければならない可能性が低くなります。 2)UATに変更がある場合、それは常にコピーされたコードの各セットに影響しますか、それとも1つまたは2つのセットのみに影響しますか?それが分離されていて、1つのセットへの変更のみが必要な場合は、物事を分離することが役立つ場合があります。 3)すべてのシナリオを処理しようとすると、最初の方法はどのくらい複雑になりますか?ネストされたif/else/loopsをたくさん追加していますか?すべての分岐をやり直し始めると、理解しにくいコードになる可能性があります。すべての分岐ロジックを再検討するよりも、コピーされた各テキストを更新する方が簡単でしょうか?

コピー/貼り付け/変更が行き詰まっている場合、「これはメソッドxyzにコピーされます」などのコメントを追加したいと思うでしょう。そうすることで、貼り付けられたすべてのバージョンのコードを更新するように促されます。または、(別のSilkTestユーザーから)この繰り返されたコードだけに焦点を当てる個別のincファイルを追加できますか?これにより、すべてのバリエーションが1か所にあり、更新が必要なさまざまなメソッドを簡単に確認できます。

2
Dan B

1つの大きな手順

1つの考え:次のようなメソッドを作成することで、カットアンドペーストのコードを回避しようとしているようです。

testScreen(title, fieldList, linkList, param1, param2, param3,...) {
    test that the layout at the top of the screen is correct
    test if PageTitle == title?
    for each field in fieldList:
        check that it appears in order on the screen
    for each field in linkList:
        check that it appears in order on the screen
    test if param1 is whatever...
    test if param2 is whatever...
    etc.
    test that the bottom of the screen is correct
}

多くの小さな手順(ツールキット)

反対のアプローチも検討しましたか? 1つの大きなtestScreen()プロシージャに100万のパラメータを渡す代わりに、必要に応じて作成する独自のフレームワークまたは小さなヘルパープロシージャのツールキットを作成することができます。お気に入り:

testScreenTop()
verifyLinks(list)
testScreenBottom()

これらの手順をすべての画面にカットアンドペーストしますが、コードの小さなチャンクをカットアンドペーストし、カットアンドペーストされていない共通のチャンク(小さな各プロシージャの内容)を切り分けます。

カット&ペースト

カットアンドペーストされたコードが私を噛まなかったのは、コードを変更する前に捨てられたときだけでした。 UIテストに関する私の最大の懸念は、どれだけ早く時代遅れになるかです。コードを変更する前にすべてのコードを捨ててしまった場合は、切り取りと貼り付けで問題のないニッチを見つけたかもしれません。また、カットアンドペーストされたコードの下流にコードがない場合(アプリケーションのUIなど)も、それほど悪くはありません。 3行以上貼り付ける場合は、実際に何かを検討します。少なくともそれを最小化するための対策を講じてください!

自動UIテスト

一体、自動UIテストの方がanyテクニックを使用した手動テストよりも高い生産性を証明できる場合(自動テストを作成/維持するコストは、毎回手動でテストするよりも低いですが、品質は同じです)あなたは論文を書くべきです。読んでみよう!タイトルを見ることができます。「UIテスト用のネットウィンをカットアンドペーストするコード!」

0
GlenPeterson

それほど悪くはありません。実際、特定のコードパターンが非常に頻繁に使用されており、変更が非常に日常的である場合(いくつかの文字列やパラメーター値など)、small(-に基づいて繰り返しテストコードを生成するコードジェネレーターを作成することもできます。 ish?)変化する値の入力リスト。バッチファイル、SQLPlusスクリプト、Excelマクロ(見た目は悪いですが、さまざまなテストスクリプトの変数が既にスプレッドシートに含まれています)を使用して、これを何度も実行しました(これにより、時間を大幅に節約できます)。 。重要なのは、反復的なテストケースコードの全体的な構造に変更があった場合、必要なものを再生成できることです。

これは他のほとんどの回答と同じですが、テクニカルマネージャー以外が理解できる方法で行われます。

次のエラーシナリオを想像してください。

  • テストの多くが依存するデータベーステーブルに誰かが変更を加えます。
  • 結果:2933自動テストの117が突然失敗します。

あなたは何をしますか?

  • (1)117テストを修正しますか?
  • (2)117のテストを削除し、新しいコピーと貼り付けを使用して再実装します。これは(1)よりも簡単かもしれません
  • (3)テストをリファクタリングして一般的なコードを抽出し、今後は1つ(またはいくつか)の方法でテストを修正する必要がある(@pdrまたは@Michael Brownの回答を参照)
  • (4)テストを再実装せずに117テストを削除する

私の経験から:

「コピー&ペーストテスト」のような自動テスト管理を導入する場合:短時間で多くのテストを取得できます。

いくつかの「エラーシナリオ」の後、管理者は(4)を好む。なぜなら、「コピーと貼り付けテスト」の修正は非常にコストがかかるからである。

そもそもそれを正しく行う(3)はそれほど速くはありませんが、テストが生き残る可能性が高くなります

0
k3b