会社で自動テストが失敗し続けるのはなぜですか?


178

私たちは、私の会社で開発者自動化テストを何度か紹介しようとしました。QAチームはSeleniumを使用してUIテストを自動化しましたが、私は常に単体テストと統合テストを導入したいと考えていました。過去に、私たちがそれを試みるたびに、皆は最初の1、2ヶ月の間興奮しました。その後、数ヶ月で、人々はそれをやめます。

いくつかの観察と質問:

  1. 自動テストは実際に機能しますか?他社で働いていた同僚のほとんどは、自動化されたテスト戦略を実装しようとして失敗しました。私はまだ実際にそれを使用し、それについて話すだけではない現実のソフトウェア会社を見ていません。多くの開発者は、自動化されたテストを理論的には素晴らしいが実際には機能しないものと見なしています。私たちのビジネスチームは、開発者が30%の余分な時間をかけてでもそれを行うことを望んでいます(少なくとも彼らはそう言っています)。しかし、開発者は懐疑的です。

  2. 自動化されたテストを適切に行う方法を実際に知っている人はいません。はい、インターネットで単体テストの例をすべて読みましたが、大きなプロジェクトにそれらを使用することはまったく別のことです。主な原因は、データベースまたはその他の重要なものをモック/スタブすることです。実際には、実際のテストを書くよりもモックに多くの時間を費やすことになります。それから、コードを書くよりもテストを書くのに時間がかかり始めたら、それはあきらめます。

  3. 複雑なデータ中心のWebアプリケーションで使用される単体テスト/システム統合テストの良いはありますか?オープンソースプロジェクトはありますか?このアプリケーションはデータ中心ですが、ドメインロジックもたくさんあります。ある時点でリポジトリのアプローチを試してみましたが、ユニットテストにはかなり適していることがわかりましたが、データアクセスを簡単に最適化できるという代償を払って、さらに複雑な層が追加されました。

20人の経験豊富な開発者が行う大きなプロジェクトがあります。これは、単体テスト/統合テストを導入するための理想的な環境のようです。

なぜ機能しないのですか?会社でどのように機能させましたか?


14
あなたの技術スタックは何ですか?
フロリアンマーゲイン

7
WebFormsは適切に単体テストすることはほぼ不可能です。MVP(モデル/ビュー/プレゼンター)パターンを使用して、プレゼンテーションロジックをテスト可能なコンポーネントに移動できます。
ピート

12
@MasonWheeler:どちらの場合でも、そもそも受け入れられなかった前提を反証する素晴らしい議論を構築しました。つまり、ユニットテストが存在することで正当性が証明されます。
スティーブンエバーズ

10
@MasonWheeler-その引数を使用して、バグがないことを決して証明しないので、QAを試みるべきではありません。それは目標でもありません。優れた自動化されたUIおよび単体テスト戦略は、QAをローテットテストから解放し、探索的テストに集中できるようにすることです。
アレックス

15
数ヶ月以上、自動化されたテストを見たことのない人が何人かいたことにショックを受けました。私はドイツの約5つの大企業でコンサルタントとして働いており、テストを書かないと彼らはあなたを解雇します。自動テストは理論的な主題ではなく、世界中で成功裏に実践されており、コードの品質が大幅に向上します(正しく行われた場合)。

回答:


89

ユニットテストを行うことの最も難しい部分は、テストを最初/早期に書く規律を得ることです。ほとんどの開発者は、コードに飛び込むことに慣れています。また、コードのテストを作成する方法を見つけようとしているため、開発プロセスが早期に遅くなります。ただし、テストが上達するにつれて、これは高速化されます。また、記述テストのため、コードの初期品質はより高く始まります。

始めるときは、テストを書くようにしてください。初めに物事をあざける/スタブすることについてあまり心配しないでください。テストをシンプルにします。テストはコードであり、リファクタリングできる/すべきです。これらの線に沿って、テストするのが難しいものがあれば、それも設計かもしれません。TDDは、ほとんどのデザインパターン(私の経験では、特にFactoryパターン)を使用する方向に向かっています。

テストが一定レベルの可視性を得るようにしてください。リリースプロセスにそれらを統合し、コードレビュー中にそれらについて尋ねます。見つかったバグはテストを受ける必要があります。これらのことはTDDが輝くところです。

ここに、私が役に立つと思ったいくつかのリソースがあります。

http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf

http://www.agitar.com/downloads/TheWayOfTestivus.pdf

編集:

テストを作成する際に留意すべきことの1つ。コードの実装については何も指定せず、動作のみを指定します。コードを書くときは、常にテストします。デバッグ文などで実行しようとしています。テストを書くことはこれを形式化し、あなたが持っているテストの記録を提供します。そうすれば、開発プロセスの途中で覚えているテストケースを誤ってスキップすることなく、機能を自信を持って確認できます。


これを診断機能として導入する別の方法です...顧客コードをほとんど出荷できるパワーオンセルフテスト(POST)...
JustinC

また、TDD Anti-Patternsも避けてください。
ゲイリーロウ

4
Misko Heveryには、YouTubeでテスト可能なコードを書くことに関する貴重なビデオがあります。youtube.com/watch?v=acjvKJiOvXw
Despertar

「テストがある程度の可視性を得るようにしてください」-これは成功のために重要です。テストの実行状況が誰にもわからない場合、値は表示されません。テストは、継続的インテグレーションの一部としてチェックイン時に自動的に実行され、レポートされます。私はTesults(tesults.com)で働いていますが、それが存在する理由は、テストの可視性がもたらす大きな影響のためです。
スキルM2

77

多くの点であなたのチームに同意します。

  1. ほとんどの単体テストの価値には疑問があります。テストの大部分は単純すぎるようです。

  2. 単に動作するコードよりも、テスト可能な優れたコードを書くことははるかに困難です。開発者コミュニティの大部分は、それを機能させるだけでなく、それ自体がコード/設計の品質であると信じています。また、品質コードが何であるかさえ知らない、さらに大きな割合です。

  3. 単体テストコードの記述には、実際のコード自体よりもはるかに長い時間がかかる場合があります。

  4. より複雑なコード(つまり、完全にテストすることに本当に関心があるもの)を適切にテストする方法を見つけることは、多くの開発者の能力を超えています。

  5. 単体テストの保守には時間がかかりすぎます。小さな変更は大きな波及効果をもたらします。自動化された単体テストの主な目標は、変更によりコードが破損したかどうかを確認することです。ただし、99%の確率でテストが失敗し、コードではありません。

上記のすべての問題があるにもかかわらず、テストを自動化するよりも、コードを変更し、何かが予期せずに壊れなかったというある程度の自信を持たせることができるより良い方法はまだありません。

上記のいくつかは、単体テストの教科書を無視することである程度緩和できます。

多くのタイプの設計/アプリケーションは、モジュール/パッケージレベルでテストを自動化することにより、より適切にテストされます。私の経験では、ほとんどのコーディングエラーは、クラスのコードが誤ってコーディングされたためではなく、コーダーがクラスが他のクラスとどのように機能するかを理解していなかったためです。私はこの種のテストで大金を払っています。ただし、これらのテストは、ユニット(クラスレベル)テストよりも記述が困難です。

開発者がそのプロセスを信じているかどうかにかかっています。もしそうなら、彼らは良いユニットテストを書き、エラーを早期に発見し、支持者になります。そうでない場合、ユニットテストは大体役に立たず、エラーを見つけることはなく、ユニットテストの役に立たないという理論は(彼らの心の中で)真実であることが証明されます。

肝心なのは、完全に自動化された単体テストのアプローチが自分で数か月以上動作するのを見たことがないということです。しかし、自動化された単体テストのアイデアは、テストが本当に必要なものを厳選していますが、依然として持続しています。このアプローチは批評家をはるかに少なくする傾向があり、ほんの数人ではなく、すべての開発者に受け入れられています。


24
私はこれに同意する傾向があります。私たちは、何かが壊れた後にだけテストを行う習慣を身につけました(たとえそれが開発中であっても)。決して前払いではなく、少なすぎる報酬のために時間がかかりすぎます。
イズカタ

5
@Izkata私が成功したもう一つのアプローチはFrobinate()、システムが他の手段で検証された後に、(その下に呼び出される数十の小さなメソッドの代わりに)トップレベルのメソッドを呼び出す比較的少数の高レベルのテストを書くことです煙のテストとして、より低いレベルの変化が何も壊さないこと。通常、これらのテストでは、提供されたキーボードユーザーテストでポンドの一部であった同じデータを使用したため、顧客はシステムが望んでいることを確認できます。その後、コードカバレッジツールは、エッジケースがまだカバーされていない場所を特定できます。
ダン・ニーリー

3
「完全な自動化された自動テスト」とは言わず、「完全な自動化されたUNITテスト」と言いました。大きな違い。少なくとも10年間は​​、モジュールレベルで自動テストを使用しました。ユニットテストはクラスレベルで行われます。私は、個人としてではなく、互いに一緒に働くことになっているクラスをテストするときに、より多くの価値を得ると信じています。ただし、それでも、実用的なアプローチを使用して、自動テストを作成する対象/場所を選択します。
ダンク

2
優れた単体テストのカバレッジがなければ、どのようにリファクタリングしますか?または、リファクタリングせずに、コードが次第に保守不能にならないようにする方法を教えてください。
ケビンクライン

1
@レオナルド彼らはそうしなかった-彼らは何も変えるにはあまりにも怖かった。または、技術的な負債をすべて節約し、数週間/数か月後に脇に置いてまとめて対処しました。
GraemeF

33

主な原因は、データベースまたは単純でないもののモック/スタブです。

そしてあなたの問題があります。

単体テストを環境に統合する方法について、誰もが良い点を指摘しています。人々に実際的な価値を認め、それが「定着」するのに十分な方法を人々に強制する方法。しかし、それが非常に苦痛であり、および/または利点を提供しない場合、それは固執しません。

データベースのスタブの作成は非常に簡単です。インターフェイスが結果を提供するために何らかのDBバッキングにアクセスする代わりに、単純なハードコーディングされたオブジェクトを配置します。それができない場合、設計/アーキテクチャに問題があります。あなたのコードは、それがデータベースに行くことを想定しているか、それを変えるためのインターフェース抽象化を持っていません。

これは単にテスト/品質の問題ではありません。DBプロバイダーを変更するか、代わりにクラウドにアクセスするか、接続されていないモバイルアプリをサポートするとすぐに、設計が失敗します。最も単純な柔軟性のケースをサポートできない場合、ビジネスが必然的に必要とするより複雑なものをサポートすることはできません。


4
モックオブジェクトの小さなスタブからのデータベースの戻り値のハードコーディングは、コードを変更および破損する可能性のあるデータベース内のあらゆるもの(列の名前変更など)からテストを隔離するための良い方法です。特定の状況では適切ですが、いつか変更したときに何かを壊したくない限り、使いやすい一時テストデータベースを保持することが重要です。データベースをスワップアウトするときにコードが破損する場合、それはテストでキャッチする必要があるコードの障害です(それを避けたい場合は、複数のデータベースでテストスイートを実行する必要があります)

8
@fennec-データベースをテストするための単体テストはありません。機能するデータベースの値に依存するコードをテストするためにあります。
テラスティン

3
データベースを操作するコードを単体テストするまでは、すべて順調です。:Pこれは、多くの人にとって、多くのコードです。

4
@fennec-書き込みが適切なオブジェクトを書き込むようにインターフェースをスタブするのは非常に簡単です。クラスがインターフェイスにSQLを直接送信しようとする場合にのみ難しくなります(読む:恐ろしいデザインがあります)。
テラスティン

5
@Telastynは誤解しているかもしれませんが、最終的には一部のクラスがダウンしてダーティになり、SQLを書き込むか、ファイルを書き込むか、データを送信するか、GPUとインターフェースする必要があります。ほとんどの抽象化には、あるレベルで避けられないリークがあります。それらは単に実用的であり、必ずしも恐ろしいものではありません。
実習キュー

21

小さく、自動化が簡単で、価値の高いものから始める必要があります。甘くて垂れ下がった果物をいくつか下ろすと、そのプロセスを売ることができます。深夜や週末の電話をどのように救ったかを示してください。その後、そこから展開できます。

自動テストを適切に行うには、リソースであり、伝道者であり、より高いレベルの経営陣から賛同を得る人が必要です。

自動テスト開発を他のアジャイルプロジェクトと同様に扱います。定期的に完了したテストを作成します。

コメントからの追加:それは管理上の問題です。コードは文書化される前に「完了」とみなされますか?チェックインする前に?単体テストを含めて合格する前に?

どのようにこれにアプローチするかは、あなたの役割に依存します。あなたは仲間ですか?その場合は、コードを再利用および保守しやすくする方法を他の人に示します。リードですか?コードの問題が最も多いプログラマを選び、それらの問題を回避するためのテストの追加を支援してください。あなたはボスですか?「単体テストが開始され、合格するまでコードは実行されない」という標準として設定します。


17
「甘くてぶら下がっている果物をいくつか取り除けば、プロセスを売ることができます。」:彼らはすでにこの段階に達していると思います(ユニットテストを使用することで潜在的な利点がありました)。試してみてください。問題は、ユニットテストを体系的に実行するために、いかに簡単に成果を上げることができるかです。単体テストが体系的に使用された私が取り組んだ唯一のプロジェクトには、実際の製品コードよりも多くの単体テストコードがありました。チームが実際のアプリケーションコードよりも単体テストのコーディングに多くの時間を費やす準備ができていない場合、IMOアプローチはおそらく機能しません。
ジョルジオ

4
それは管理上の問題です。コードは文書化される前に「完了」とみなされますか?チェックインする前に?単体テストを含めて合格する前に?これにどうアプローチするかは、あなたの役割に大きく依存します。あなたは仲間ですか?その場合は、コードを再利用および保守しやすくする方法を他の人に示します。リードですか?コードの問題が最も多いプログラマを選び、それらの問題を回避するためのテストの追加を支援してください。あなたはボスですか?ユニットテストはであり、通過するまでコードが実行されない」ことを標準として設定する。
スキップハフマン

1
@SkipHuffmanのコメントは、現在の回答の編集として追加する必要があります。
ラドゥフロレスク

15

これらの基本ルールに従ってください。テスト:

  1. 定期的に実行する必要があります!すべてのビルドで、すべてのチェックインの前後に、または毎朝にテストを実行できます。手動でトリガーするよりも、自動でトリガーする方が非常に望ましいです。理論的には、チームの全員にテストの実行を保証する責任を負わせることができますが、自動化されていない場合、おそらく十分な頻度で行われていないでしょう!また、テストを十分な頻度で実行しないと、両方のバグを発見するのが遅すぎて、多くの壊れたテストが促進され、ポイント2につながります。

  2. 定期的に実行されているこれらのテストが邪魔にならなければ、あなたはまだ成功するでしょう。テストの意味:

    a。彼らが提供する価値のために(主観的に)実行するのに時間がかかりすぎてはいけません!テストを迅速に実行します。実行させるためにあなたの時間の無駄になるテストをチェックインさせないでください!

    b。信頼できないものであってはなりません。可能な限り、マルチスレッドテストは避けてください。他のコードと同様に、テストにエンジニアリングプラクティスを適用します。特に、コードはテストをレビューします。

    c。テストした実際のコードよりも修正や保守が難しくてはいけません。コードベースをわずか1行変更するだけで10種類のテストを修正する必要がある場合、コーディング速度は非常に悪くなります。

最後に、ルール番号3。テストは、ルール2のように負の値を提供するだけでなく、正の値を提供する必要があります。テスト...

  1. 彼らが失敗したときに実際にあなたが気にかけていることを伝えなければなりません!(あいまいなエラーメッセージを含むテストはありません。または、「Windows 2008マシンでテストを実行するのを忘れた」などのばかげた苦情を単に言ってください!)。

ルール3に違反する一般的な方法の1つは、間違ったことテストすることです。これは、テストが大きすぎるか、焦点が合っていないことが原因である場合があります。しかし、通常は、顧客が気にするものをテストしないことと、無関係な実装の詳細をテストすることから生じます。(ただし、実装の詳細をテストすることで効率的なテストが行​​われることもあります-IMOでは、どちらを決定するか練習するだけです。

結論:これらの基本ルールは、持続可能性のある試験分野の一般的な方向性を示しています。これは、あなたが切望していることです。テストするとき、このテストが本当に持続可能で保守可能であるかどうかを自問してください。覚えておいてください:

  • テストが持続可能でない場合、それらは使用されなくなり、それによって無駄な努力になります
  • テストが持続可能でない場合、テストの実行を停止し、チームはテストの改善を停止します!そして、最後のポイント:

テストは実際に難しいです。基本的に、テストの作成を開始すると、チームのテストがひどくなることが予想されます。がっかりしないでください。あなたがそれらが吸うと持続不可能であることに気づいたときはいつでも、古いテストを捨ててください


12

1. 本当に機能しますか?

はい、できます-適切に行われた場合。要点は、エンジニアが新しい機能を実装した後、テスターが自動スクリプトを調整および拡張する必要があることです。

2. 自動テストを適切に行う方法を実際に経験したり、知っている人はいません。

コンサルタントを取得します(適切に行われている方法を知っている人)。または、より多くの時間を投資します。別の方法は、同じテストを手動で行う(エラーが発生しやすい)より大きなテストチームを配置することです。

3.20人の優秀な経験豊富な開発者が取り組んでいる大きなプロジェクトがあります。したがって、単体テスト/統合テストを導入するのに最適な環境である必要があります。なぜ機能しないのですか?会社でどのように機能させましたか?

彼らがユニットテストを拒否した場合、私は彼らを「優秀な経験豊富な開発者」とは呼びません。テスト(ユニットテストと統合テストの両方)のプラスの利点に関する多くの優れた記事があり、最終的には、バグがあなたの会社どれくらいのコストをかけるかについて要約します。たとえば、私は品質が重要な会社で働いているため、単体テストと統合テストは避けられません。単体テストだけでバグの数が30%減少していることを伝える多くの記事を簡単に見つけることができます!(実際には、平均で30%で20〜90%の範囲ですが、それでもかなりの量です。)

あなたの会社でそれを機能させるには、コンサルタントを雇うか、このタスクを上級エンジニアに割り当ててください(彼には時間がかかります)。そして、みんなにルールを守らせる。


20
私は、事実上すべてが「適切に行われれば」機能することを指摘しなければなりません。しかし、それはすべての人々にとって非常に有益ではありません。プロセスが実際に機能していると主張できるようにするには、「並べ替え」を行ったときにも機能する必要があります。
ダンク

11
みんなの状況をあなた自身に過度に一般化すること(つまり、彼らを「優秀な経験豊かな開発者」と呼ぶわけではない。品質問題)は、経験の幅の不足を示すだけでなく、あまり生産的ではないことを指摘する。すべての業界には、独自の「作品」の定義があります。また、ユニット、統合、システムレベルでどの程度のテストを行う必要があるか。多くの「例外的に優れた」開発者は、自動化された統合テストと比較した場合、単体テストが費用に見合うだけの価値をもたらすことに気付きました。彼らはまた、これはおそらく彼らの特定の産業にのみ適用されることを認識しています。
ダンク

11
「ユニットテストを拒否した場合、彼らを「優秀な経験豊富な開発者」とは呼びません。」これはまさに真のスコットランド人の誤fallです。ソフトウェア業界は単体テストなしで何十年も仲良くしており、その業界のほとんどは今日も単体テストなしでやり続けています。それは良いアイデアかもしれませんが、それは単に必須ではありません。
ノアYetter

1
「ユニットテストに時間を無駄にしない」:これを「無駄なユニットテストに時間を無駄にしない」と言い換えます。すべてを盲目的に単体テストすると、膨大な時間の無駄になります。
ジョルジオ

1
@Dunk私は、テストファーストエブリシングTDD現象全体を本当に嫌っていますが、あなたの最初の声明には同意できません。あなたは正しいことをしているか、そうでないかのどちらかです。1つのユニットテストをうまく実行でき、そのメリットを確認できる場合もありますが、半ば行われた1つのことのメリットを確認することはできません。
エリックReppen

10

これらは、自動テストの導入が失敗する多くの理由です。プログラマーはコーディングの習慣を変えない傾向があり、単体テストを完全に受け入れることができないという事実に要約されると思います。

自動テストを開始したい多くの人々は、既存のコードベースのためにそれらを紹介しようとします。既存のアプリケーションの多くの機能を一度にテストする統合テストを作成しようとします。このような統合テストは、保守が困難で費用がかかりすぎることで有名です。アドバイス:新しいコードベースの自動テストを紹介します。

単体テストは、自動化するのに適したテストです。上記のすべて(統合テスト、コンポーネントテスト、システムテスト)も自動的にテストできますが、より多くの機能を一度にテストすると、費用便益比は急速に低下します。ユニットテストが不十分な機能でこのようなテストを構築すると、この悪影響が増幅されます。アドバイス:単体テストレベルで自動テストを導入し、単体テストの強固な基盤で自動統合テストを構築します

上記の点から、自動テストの成功の大部分は、単体テストの効果に依存します。単体テストで生産性を感じる場合、効果的な単体テストがあります。単体テストを開始するとき、既存のコードとコーディングの習慣を単体テストに後付けする傾向があります。皮肉なことに、これは単体テストを学ぶ最も難しい方法です。また、単体テストでは、コーディング方法を変更する必要があります(たとえば、SOLID原則を適用する)。ほとんどのプログラマーは、学習曲線があまりにも急であると考え、単体テストをあまりテストできない設計コードでラップするのが面倒だと思うため、すぐに単体テストの作成を停止します。アドバイス:新しいコードを使用してユニットテストをゼロから学び、コーディング習慣を変更する必要があるという事実に対処します。

他にも多くの要因がありますが、ほとんどのプログラマーにとって、コードへの道を変えるのは面倒であることがわかりました。テストなしで記述されたコードは見た目が異なります。コードをテスト可能な設計に絞り込めない場合、効果的な単体テストの作成に失敗する可能性が非常に高くなります。これにより、効果的な自動テストの基盤が破壊されます。

私はそれを自分で経験し、自動テストを導入した会社で働くことができてうれしく思います。私は他の要因についてもっと書くことができましたが、コーディングの習慣と単体テストが最も重要なものだと思います。幸運なことに、私よりも多くの経験を持ち、自分のノウハウで本を埋めている人がいます。これらの書籍の1つは、Microsoftテクノロジスタックを使用しているため、.NETでのBrownfield Application Developmentです。


Introduce automated tests on the unit test level and build automated integration tests on a solid foundation of unit tests.+1
c69

10

上記の回答で明らかにされていないことの1つは、ユニットテストは基本的に公共財であり、私的コストであるということです。ここでそれに関するブログ記事を書きまし

一方、それは何まで来ることはされていることをテストスイートは、チームや個々の開発者に利益をもたらす、テストを書くことはほとんどの時間、それをやって1のコストです。

要するに、テストの作成が何らかの形で強制されない限り-そして上記の回答がそれを行うためのいくつかの異なる方法をリストしている-個人開発者がこれを行う理由はありません。

私が働いていたある会社では、単体テストを書くことは機能を提供するのに必要な部分でした。単体テストがコミットまたは新機能の一部でない限り、新しいコードは受け入れられませんでした。開発者に与えられたすべての「タスク」について簡単なコードレビューがありました。職場で同様のポリシーを実装することは価値があります。


8

ビジネスが開発者よりもプロテスティングであることは興味深いです!あなたの最大の課題は、変更に対する開発者の抵抗を克服することだと思われます。ユニットテストを含めるには、ジョブの理解を再定義する必要があります。

開発者がこれらのテストを書くことに対する抵抗を克服するのを助けるために、初期のユニットテストの成功以上にあなたを助けることはできません。何か新しいことをするためにそれらをプッシュする場合は、ほぼ確実に報酬が得られるものを最初にプッシュするようにしてください。

@SkipHuffmanがこれに触れましたが、私はそれを完全に言うつもりです。いくつかのものは、他のものよりも自動テストにはるかに適しています。最初のパスでは、データベースまたはUIをテストしません。データベースからの入力は、設定および分解が非常に困難な場合があります。UI出力テストは、テストとはまったく関係のないルックアンドフィールの変更によってすぐに壊れてしまう傾向があります。

私が「ミドルウェア」と呼ぶものは、単体テストに最適です。入力および出力条件を明確に定義したコード。DRY原則(Do n't Repeat Yourself)に従うと、アプリケーションに固有の繰り返し発生する問題を解決するためのいくつかの小さなクラスまたは関数を作成できます。

単体テストは、既存の内部コンポーネントを変更するリスクを制限する優れたツールです。長い間機能していた内部コンポーネントを変更する前に、単体テストを作成してください。これらのテストは、現在機能している機能が保持されていることを証明します。変更を行い、すべての単体テストに合格すると、「下流」に何も破損していないことがわかります。ダウンストリームの問題を見つけた場合は、ユニットテストを追加してください!

ロン・ハイフィッツは、「人々が保持する価値観の対立に対処するか、人々が支持する価値観と彼らが直面する現実とのギャップを減らすために。適応作業には価値観、信念、または行動の変更が必要です」変更に対する人間の抵抗を克服した後、必要に応じてより困難なテスト領域に分岐できます。


6
「変更に対する開発者の抵抗に打ち勝つ」:すべての抵抗に理由がないわけではなく、「変更への抵抗」引数を使用して正直な議論を避けるべきではありません。
ジョルジオ

7

自動テストの1つのことは、テスト可能にするためにコードを記述する必要があることです。これ自体は悪いことではありません(実際には、原則として回避すべき多くのプラクティスを思いとどまらせるので良いのですが)が、既存のコードに単体テストを適用しようとする場合はそうではありませんテスト可能な方法で書かれています。

シングルトン、静的メソッド、レジストリ、サービスロケーターなどのようなものは、モックアウトが非常に困難な依存関係を導入します。デメテルの法則への違反は、コードベースの他の部分がコードベースの他の部分がどのように機能するかについてあまりにも多くのことを知っていることを意味します。これらすべてのことにより、モジュールを他のコードベースから分離することが難しくなります。モジュールを分離してテストできない場合、ユニットテストは多くの価値を失います。テストが失敗した場合は、テスト対象のユニットの障害、またはその依存関係のいずれかの障害が原因であるか、依存データソースを介して引き込まれるデータがテスト作成者が予期したものではないことが原因である可能性があります?できれば'

ユニットテストを念頭に置いて構築されていないほとんどのコードベースは、本質的にテストできない傾向があります。 。単体テストを念頭に置いて記述されたコードは、非常に異なって見える傾向があります。

多くの人は、ユニットテストを初めて実行するときに素朴なアプローチを取ります。既存のコードベースのテストを大量に書くことができ、すべてがうまくいくと思いますが、上記の問題。彼らは、ユニットテストでセットアップを過度に実行しなければならないことを発見し始めます。また、コードに隔離がないため、テスト失敗の原因を突き止めることができないため、結果はしばしば疑わしいものです。彼らはまた、システムがどのように機能するかについての非常に抽象的な側面を示す「賢い」テストを書き始めようとする傾向があります。「賢い」単体テストはそれ自体がバグの潜在的な原因であるため、これは失敗する傾向があります。テストしたモジュールのバグが原因でテストが失敗しましたが、またはテストのバグのため?テストは非常に単純で、バグが潜んでいる可能性がないことは明らかです。実際、最高のテストは2行を超えることはめったにありません。最初の行はテスト対象のユニットに何かを行うように指示し、2行目はそれが期待したものであると断言します。

チームが単体テストの採用に真剣に取り組んでいる場合、既存のプロジェクトから始めるのは賢明ではありません。あなたのチームの既存のプロジェクトは、おそらく大きなリファクタリングなしではテストできません。単体テストについて学習するための基礎として新しいプロジェクトを使用したほうがよいでしょう。新しいコードベースを設計して、シングルトン、レジストリ、その他の隠れた依存関係よりも依存関係の注入を優先し、実装などではなくインターフェイスに依存するように記述できます。また、テストを実行するコードと一緒にテストを作成することもできます(テストを実行すると、テストするモジュールではなく、テストしたモジュールが意図したとおりに動作することを確認するユニットテストが実行されます)仕様書ですべきこと。

単体テストである程度の自信が得られると、チームはおそらく、単体テストの障害となる既存のコードの欠陥を認識し始めるでしょう。これは、既存のコードをリファクタリングしてよりテストしやすくするために作業を開始できるときです。野心的で一度にこれをやろうとしたり、まったく新しいシステムで動作するシステムを置き換えようとしないでください。簡単にテストできるコードベースの一部を見つけてから始めてください。依存関係または依存関係が明らかな場所)およびそれらのテストを記述します。コードと一緒にテストを書くことは、後でテストを書くことよりも望ましいと言いましたが、後で書かれたテストでさえ出発点として価値があります。クラスがどのように動作するかについて、その仕様が行うべきだと言うこと以外は何も知らないかのようにテストを記述します。テストを実行して失敗した場合、仕様または実装が間違っています。両方を再確認してどちらが間違っているかを判断し、それに応じてテストまたはコードを更新します。

ぶら下がっている果物を選んだら、あなたの本当の仕事が始まります。コードベース内の非表示の依存関係を見つけて、一度に1つずつ修正する必要があります。この時点で野心的にならないでください。テストの障害が修正され、次のビットに進むまで、一度に1つのモジュールを実行するか、1つのモジュールで1つの問題だけを実行してください。

TL:DR:ほとんどの人はテストが簡単だと思っているので、既存のコードにテストを簡単に後付けできます。これらの仮定はどちらも間違っています。これらの両方の事実を念頭に置いて、プロジェクトにユニットテストを組み込むプロジェクトに着手すると、成功する可能性が高くなります。


ヒント:TLを入れてください; DR:一番上に-それにたどり着くためにすべての投稿を読む必要がありました!(ちょっとポイントを打ち負かす)
gbjbaanb 14

4
  • あなたの会社には、自動化されたテストを行った経験のある人がいますか?

そうでない場合、自動化されたテストイニシアチブはおそらく失敗します。自動化されたテストは、プログラミングの他の多くのスキルと同様にスキルであり、経験のある人がいない場合、自動化されたテストが実際の価値を備えた優れた自動化されたテストであるか、そうでないかを判断するのは容易ではありませんランダムに失敗する/頻繁に更新する必要がある/実際に興味深いコードを実行しない

  • その人はリーダーシップ力を持っていますか?彼らは変化を要求することができますか?

誰も聞いていない場合、テストが良くないと言うかどうかは関係ありません。(リーダーシップ力を正式にする必要はないことに注意してください。気にするチームを持つことも良いことです。)

  • 自動テストの実装と開発サイクルへの統合を容易にするツールとプロセスを開発していますか?

開発者は怠け者です。やりたいことを簡単に達成する必要があり、やりたくないことは達成しにくいものにする必要があります。テストライブラリを使用すると、テストのセットアップと分解、特にテストデータベースなどの環境関連のセットアップに関連するタスクを簡単に実行できるようにする必要があります。(データベースのモックについては、これらのコメントの一部で説明されていますが、注意して使用する必要があります。実際のデータベースは簡単に起動でき、コンポーネントとプロセスライフサイクルの相互作用をテストできます。多くの場合、単体テストよりも重要で効果的です。個々のデータアクセサー。)

また、IDEがテストスイートを起動する良い方法を持っていることを確認する必要があります。テストスイートは頻繁に実行する必要があります。これにより、不幸な状態が続くのではなく、失敗したことに気付くことができます。また、開発者はフィードバックに適切に対応します。たとえば、自動統合システムがテストに違反した場合に変更を元に戻すなどです。または、より良い、肯定的なフィードバック:バグをキャッチし、物事を壊すことからあなたを救う自動化された統合システム。


開発者が怠け者だと言うのはフェアではないと思います。たぶんそれはあなたの経験のケースですが、確かにそれは普遍的な真実ではありません。
サム

4

第1に、開発者がテストの価値を認識していない場合、それはおそらく、開発者が自分の価値や一般的なテストの価値を知らないためではなく、テストが価値がないためです。その伝道者の間では、テスト駆動開発が失敗することはなく、怠zyで怠laな開発者によって失敗するだけであると信じる傾向があります。これは間違っており、逆効果だと思います。

テスト駆動開発を紹介されたとき、事実上、失敗しないメソッドが失敗しないことを検証するテストを書くことを意味していました。素敵な緑のチェックと達成感が得られるので、最初はこれがいいです。後で、コードをリファクタリングすると、数十の赤いXesがありますが、どれもコードが変更されたこと、テストが無効になったこと、多くの時間を無駄に費やしていること以外は何も言いません。

あなたはそれを避けたいです。

それ以来、私はテストに対して異なるアプローチをとってきました。代わりに、インターフェースの実装のペア、私が持っているトリプルインターフェース、実装、テストを。インターフェイスは動作を指定し、実装は動作を実行し、テストは動作をチェックします。

明らかなように思えますが、私にとっては、指定どおりに動作することを証明する必要があるコードと、適切と思われるテストを行うコードを区別します。証明する必要があるコードは、外部に提供するインターフェイスです。残りはあなただけの関心事です。

この場合、開発者に、この種のテストが適切となるコードに自然な区分があるかどうかを尋ねます。チームAが実装し、チームBが使用するインターフェースはありますか?その場合、インターフェースが期待どおりに動作することを確認することがチームBの利益になります。チームBにテストの作成を依頼し、チームAに実装がテストに準拠していることを確認するように指示します。または、そうでない場合、および意図的にそうでない場合は、予期しない変更について他のチームと話し合い、チームが準備できるようにします。

これはテストの価値を示していると思います。それ自体が目的ではありませんが、素敵な緑のチェックはあります。ある開発者が別の開発者に約束したことを明示し、両方の満足が約束されていることを保証するために存在します。


1
私は、誰かがそのような詳細までテストする必要があると感じたコードよりも読みやすいコードが好きです。
エリックReppen

1
私が感じている素敵な緑のカチカチは問題です-それはテストをある種のゲームに変えます。
gbjbaanb 14

2

多数の単体テストを既存の大規模なプロジェクトに追加するのは大変な作業です。自分に合った優れたモックフレームワークが既に見つかっている場合は、最も難しい問題を解決する必要があります。

機能を追加したりバグを修正したりするときに、テストを追加することをお勧めします。バグの修正が最も簡単なものです。バグが原因で失敗するテストを作成し、バグを修正します。同時に、おそらくあなたはパスするより簡単なテストを書いていることに気付くでしょう。もちろん、これには小さくて簡単にテストされたコードを使用したいでしょう。

人々が簡単なことのためにテストを書くことに慣れてきたら、あなたは彼らがよりテストしやすいようにコードを書くことを見つけるべきです。

また、テストのコードカバレッジを測定することをお勧めします(過去にJavaでcoberturaを使用しました)。定期的に(毎日、チェックインごとに)テストを実行し、メトリックを生成する継続的な統合サーバーが必要になります。あなたの仲間の開発者が熱心なら、彼らは時間とともにカバレッジが増加するのを見たいと思うでしょう。


2

長い試合をする必要があると思います。ある程度の承認を得るためにできることの1つは、作成する次の機能を徹底的に単体テストし、バグの数を経時的に追跡することです。主要なバグが早期に発見され(特にこれをTest-Driven Designと組み合わせた場合)、回帰の数が非常に少なくなることを願っています。一定の期間(たとえば1年)後に、統計情報を、同様の複雑さの単体テストされていない機能と比較します。新しいバグとリグレッションの数がかなり少ないことを示すことができれば、それに対する財政的正当性を提供しているので、製品チームが無視するのが難しくなります。

主要な機能にTDDと単体テストを使用できる状況がありました。開発段階の終了後、5年以上にわたって報告されたバグは1つもありませんでした。新しい、そして危険な機能強化が要求されたとき、私はそれを実装し、単体テストですべてのリグレッションをキャッチすることができました。


1

ユニットテストの価値は、いくつかの要因により多くのチームによって過小評価されているという私の強い意見です。

多くの場合、開発者は「物事を成し遂げる」というプレッシャーにさらされるため、コードブロックが機能することを証明することは、顧客にとって十分な証拠です。これはほとんどの場合、コンサルティング会社と人間主導のQAに当てはまります。顧客がユニットテストを必要とせず、十分なライブデモを検討している場合、顧客は障害を隠す可能性のあるコードの承認に署名するため、完全に失敗します。

多くの場合、開発者はイライラします。プログラマーになるのは大変な仕事です。タスクを完了して次のタスクに進むことは満足のいくものなので、誰もが急いで終了したいと考えています。元のQAから数か月後に発生する大きなバグでバスに襲われるまで。このシナリオでは、自動化された継続的なQAは、開発者というよりも経営者の問題です(彼らは、おそらく残業の可能性があります)。

しかし、例外があります

自動化されたテストモデルの受け入れは、実行されているテストの「人間性」の関数であると強く信じています。フロントエンドでWebモジュールをテストする場合、Seleniumなどのツールにもかかわらず、自分でフォームに入力し、結果を確認して決定論を信じる可能性が高くなります。後でテストを再実行するのを忘れるか、または古いテストを再度実行するのが面倒であるため、後でバグが発見されることがあります。これを活用するために、コードの強力なモジュール化と「古いコードの変更」に関する厳格なルールが、銀行環境(私の個人的な仕事の経験)で受け入れられることが証明されました。

代わりに、開発者が高度に自動化された大量のデータモジュールの開発を担当している場合、詳細なユニットテストを作成してテストバッチに送信する可能性が高くなります。これは、外部データソースから変換されたデータ(モックされているかどうかに関係なく)で大きなXMLペイロードを埋めるのは人間が行いやすい仕事ではないためです。一部のテスト開発者は、最終的にこの特定の種類のテスト用の小さくて面白いフロントエンドを構築します。修士論文で働いていたとき、私は毎秒6000件以上のsyslogメッセージを処理するロギングバスで作業していたため、パケットの損失と破損を測定する必要がありました。ほとんどすべてのコンポーネント、特にSyslogパーサーのユニットテストとストレステストを自然に作成しました。

開発者をよりユニットテストしやすいものにするため

私は彼らに強制されなければならないと信じています。あなたが賢明な顧客であるなら、あなたはコンサルタントにすべてのQAで完全なテストスイートを実行することを要求するでしょう。あなたが優れたチームリーダーである場合、次のタスクをスマートな開発者に割り当てることを考えるかもしれません:内部テストプラットフォームを構築します。内部効果プラットフォームのアンチパターでは何も見当たりませんが、代わりにヘルパークラス、データベースモック、構成、パーサー、コンバーター、スイスアーミーナイフのセットがあり、開発者はすぐにテストを作成できます。

NUnitなどの現在のテストプラットフォームは汎用であり、一般的なアサーションを検証できます。依存性注入とプロジェクト固有のファクトリを正しく使用すると、開発者はテスト用のコードを記述しにくくなり、より幸せになります。完全なプロジェクトでこれを実験する機会はまだありません。実際のフィードバックを提供することはできません。


1

自動テストはソフトウェア開発のようなものです。残念ながら、あなたがテストのために雇う人々はもともと、テストケース、計画、戦略を書き、レビュープロセスに従い、手動でテストしてバグを記録することを目的としています。

自動テストの責任が与えられるとすぐに、ある程度のソフトウェア開発が含まれます。ここでの難点は、使用するツールに関係なく自動テストであり(そして、この点を強調するために)、日常的なメンテナンスと更新が必要です。開発者がコードを変更すると、

  • テストが実行され続けることを確認する必要があります。
  • テストは実行されなかったため削除されないようにする必要があります
  • テストメトリックは、最後のビルドとこのビルドで実行した内容を示す必要があります。テストケースの数が減っていないことを確認するため。
  • テストケースは開発と同様にレビューする必要があります。人々が混乱しないように、1つのテストを2つに分けて数字を増やすだけです(テストは外部委託されるため、この追跡は重要です)。
  • 開発者とテストの間のより「健康な」コミュニケーションが重要です
  • キープnon-functionalテストを分離し、それらは毎日それを実行することを期待していない、それはこれらの最新状態に保つために時間がかかり、良いです。しかし、あきらめてはいけません、それらが維持されていることを確認してください。

これらの理由により失敗する

  • テストエンジニアは、分析スキルのない手動テストエンジニアです。彼らはa ifwhileループの違いを知らない。率直に言って、自動テストを教えるコースはないため、手動テストのみを教えています。
  • テストエンジニアがビルドの手動テストに忙しすぎて、バグを記録して自動テストの追跡をゆるめている
  • テストマネージャーは、無効なデータを表示する(プロジェクトの開始時に)だけで、自動化されたテストのメトリックを気にしません。
  • 保存期間が非常に短いモバイルアプリケーションのテストを自動化することを選択します。作成するまでに、アプリケーションの要件が変更される自動テストスイートを安定させます。代わりに、アプリケーションを実行するWebサービスのテストに集中する必要があります。
  • 自動テストチームが開発チーム、機能完了、コード完了、コードロックダウン、コードフリーズと同じマイルストーンに従うことを理解していない。
  • 手動テストと自動テストを区別しないでください。
  • 彼らは両方とも同じ給料を受け取り、同じマネージャーに報告します。理想的には、開発マネージャーに報告し、彼らの給料を開発の給料と一致させるべきです。
  • あなたは実際にjunitは自動化されたテストを開発するのに十分ではないと考え、信じています:)。

これらは、自動化されたテストを非常に真剣に受け止め、自動化されたテストエンジニアとしてdevが重要であることを理解している企業で働いた経験からです。そして、知らない人のために働いた私の経験から、どれだけ説明しても違いを理解してください。


単体テストと統合テストの場合、テストを作成する必要があるのは開発者であり、個別の「テストエンジニア」ではありません。(質問に書かれているように、QA、つまりテストエンジニアは実際にすでに自動UIテストを使用しています。)
PaŭloEbermann

現実的に言えば、自動化されたテストを作成する人は開発スキルを持っている必要があります。
シッダールス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.