web-dev-qa-db-ja.com

CIサーバーで単体テストを実行するポイントは何ですか?

なぜCIサーバーで単体テストを実行するのですか?

確かに、何かがマスターにコミットされるまでに、開発者は以前にすべての単体テストをすでに実行しており、新しいコードで発生した可能性のあるエラーを修正しています。それが単体テストの要点ではありませんか?それ以外の場合は、壊れたコードをコミットしただけです。

99
Steve

確かに、何かがマスターにコミットされるまでに、開発者は以前にすべての単体テストをすでに実行しており、新しいコードで発生した可能性のあるエラーを修正しています。

か否か。これが発生する理由はさまざまです。

  • 開発者にはそれを行う規律がありません
  • 彼らは忘れてしまった
  • 彼らはすべてをコミットせず、不完全なコミットセットをプッシュしました(ありがとう Matthieu M。
  • 彼らはいくつかのテストのみを実行しましたが、スイート全体は実行しませんでした(ありがとう nhgrif
  • マージする前にブランチでテストしました(ありがとう nhgrif * 2)

しかし本当のポイントは、開発者のマシンではないマシンでテストを実行することです。構成が異なるもの。

これは、テストやコードが開発者ボックスに固有の何か(構成、データ、タイムゾーン、ロケールなど)に依存する問題を見つけるのに役立ちます。

CIビルドがテストを実行するその他の理由:

  • メインの開発プラットフォーム以外の異なるプラットフォームでのテスト。これは、開発者が行うのが難しい場合があります。 (ありがとう [〜#〜] tzhx [〜#〜]
  • Acceptance/Integration/End to End/Really long running tests are run on the CI server that not run not run on the developer box。 (ありがとう Ixrec
  • 開発者は、プッシュ/コミットする前に小さな変更を加える場合があります(これは安全な変更であり、テストを実行しないと考えてください)。 (ありがとう Ixrec * 2)
  • CIサーバー構成には通常、開発者ツールと構成のすべてが含まれていないため、本番システムに近い
  • CIシステムは毎回ゼロからプロジェクトをビルドします。つまり、ビルドは反復可能です
  • ライブラリーの変更により、ダウンストリームで問題が発生する可能性があります-ライブラリーだけでなく、all依存コードベースを構築するようにCIサーバーを構成できます
225
Oded

ソース管理へのコミットを行う前にすべての統合テストと単体テストを実行しない開発者として、ここで防御策を提示します。

アプリケーションを正しくビルドしてテストし、検証する必要があります。

  • Microsoft Windows XPおよびVisual Studio 2008コンパイラを搭載したVista。
  • Microsoft Windows 7とVisual Studio 2010コンパイラ。
    • ああ、そしてMSIはそれらのそれぞれのためにビルドします。
  • RHEL 5および6、それぞれ4.1および4.4(同様にCentOS)
    • もうすぐ7。 Woop-de-woop。
  • 最近の3つのバージョンのGCCを備えたFedoraワークステーション。
  • 最近の3つのバージョンのDebian(およびUbuntuのような派生物)。
  • 最近の3つの最新バージョンのMac OSX。
    • そしてパッケージ(rpm、dmgなど)

Fortran(IntelとGNUコンパイラーの両方)、Python(およびOSに応じてさまざまなバージョン))、およびbash/batスクリプトコンポーネントを追加します。 、私はあなたが物事がスパイラルアウトを見ることができると思います

つまり、1日に2、3回テストを実行するだけで、16台のマシンが必要になります。そのためのインフラストラクチャを管理するだけで、ほぼフルタイムの仕事になります。ほとんどの人は、それが不当であることに同意するだろうと思います。特に、プロジェクトの人々の数にそれを乗じます。そのため、CIサーバーに処理を任せます。

単体テストは、壊れたコードのコミットを止めるものではありません。knowあなたが何かを壊したかどうかを教えてくれます。人々は「ユニットテストは高速でなければならない」と言って、原則と設計パターンと方法論について進んでいきますが、実際には、反復的で単調なタスク用に設計したコンピューターにそれらを実行させ、それらが関与する場合にのみ関与させる方が良い場合もあります。彼らが何かを見つけたと教えてください。

75
TZHX

優れたOdedの回答は別として:

  • リポジトリからコードをテストします。コミットするのを忘れたあなたのファイルであなたのマシンで働くかもしれません...作成スクリプト(liquibaseなど)を含まない新しいテーブル、一部の構成データまたはプロパティファイルに依存している可能性があります。
  • コード統合の問題を回避します。 1人の開発者が最新バージョンをダウンロードし、ユニットと統合テストを作成し、コードを追加し、自分のマシンですべてのテストに合格し、コミットしてプッシュします。別の開発者が同じことを行ったところです。どちらの変更もそれ自体で正しいですが、マージするとバグが発生します。これは、リポジトリのマージである場合と、競合として検出されない場合があります。例えば。開発1は、まったく使用されなかったファイルを削除します。 Dev 2はこのファイルに対してコードを作成し、Dev 1を変更せずにテストします。
  • リポジトリから自動的にデプロイするスクリプトを開発します。普遍的なビルドおよびデプロイスクリプトを使用すると、多くの問題が解決します。一部の開発者は、誰もが共有していないlibまたはコンパイルオプションを追加した可能性があります。これにより時間を節約できるだけでなく、さらに重要なことに、展開を安全かつ予測可能にします。さらに、リポジトリをバージョン2.3.1に戻し、このバージョンで動作するスクリプトを使用してこのバージョンをデプロイできます。これには、バージョン管理が必要なビュー、ストアドプロシージャ、ビュー、トリガーなどのデータベースオブジェクトが含まれます。 (または、実行可能なバージョンに戻ることはできません)。
  • その他のテスト:統合、パフォーマンス、エンドツーエンドテストと同様。これには時間がかかり、Seleniumなどのテストツールが含まれる場合があります。モックオブジェクトやHSQLではなく、実際のデータベースを使用したデータの完全なセットが必要になる場合があります。

私はかつて、マージとデプロイメントのプロセスのためにデプロイメントに多くのバグがあった会社で働いていました。これは、テストとCIを困難にする奇妙な専用フレームワークが原因でした。開発で完全に機能したコードが本番環境に届かなかったのは、幸せな経験ではありませんでした。

23
Borjab

あなたはそうは思わないでしょう-しかし、開発者は人間であり、時には忘れてしまいます。

また、開発者は最新のコードのプルに失敗することがよくあります。彼らの最新のテストは問題なく実行され、チェックインの時点で他の誰かが重大な変更をコミットします。

また、テストはローカル(チェックインされていない)リソースに依存する場合もあります。ローカルユニットテストで検出されないもの。

上記のすべてが空想的であると思われる場合、CIの上のレベル(少なくともTFS上)がGatedと呼ばれ、テストに失敗したビルドは保留され、コードベースにコミットされません。

22
Robbie Dee

何かがマスターにコミットするまでに

通常、CIはすべてのコミットで実行するように設定します。ブランチは、ブランチがテストされるまでマスターにマージされません。マスターでのテストの実行に依存している場合は、ビルドを中断するためのウィンドウが開きます。

CIマシンでテストを実行すると、再現可能な結果が得られます。 CIサーバーにはVCSから取得した既知のクリーンな環境があるため、テスト結果は正しいことがわかります。ローカルで実行しているとき、それらがパスするために必要ないくつかのコードをコミットすることを忘れるか、それらが失敗するはずのときにパスするようにするコミットされていないコードがあるかもしれません。

特に、変更のたびにローカルで実行される可能性が低い低速の数分テストの場合は特に、異なるスイートを並行して実行することにより、開発者の時間を節約できます。

現在の作業では、本番環境への展開はすべてのテストに合格したCIで行われます。デプロイスクリプトは、合格しない限り、デプロイを防止します。これにより、誤って実行を忘れることができなくなります。

CIがワークフローの一部であることにより、開発者の負担も軽減されます。開発者は通常、リンター、静的アナライザー、単体テスト、コードカバレッジ、統合テストをすべての変更に対して実行しますか? CIは、完全に自動的に、それについて考える必要なく、意思決定の疲労を軽減できます。

14
Daenyth

何かがマスターにコミットされるときまでに、開発者あるはずはすべてのユニットテストをすでに実行しています...しかし、そうでない場合はどうなりますか? CIサーバーでユニットテストを実行しないと、他の誰かが変更を自分のマシンにプルし、テストがそれらに違反したことを発見するまでわかりません。

さらに、開発者がミスを犯し、マシンに固有のローカルリソースを参照した可能性があります。彼らがコードをチェックインし、CIの実行が失敗した場合、問題はすぐに識別され、修正できます。

4
David Arno

(他の回答とは異なり)開発者がかなり規律があり、コミットする前に単体テストを実行すると仮定すると、いくつかの理由が考えられます。

  • ユニットテストの実行には、特別なセットアップのために時間がかかる場合があります。たとえば、メモリチェッカー(valgrindなど)を使用して単体テストを実行すると、はるかに長い時間がかかる可能性があります。すべての単体テストは成功していますが、メモリチェックは失敗する可能性があります。
  • 結果は、一部の特別な設定ではそれほど重要ではありません。たとえば、単体テストを実行してコードカバレッジを確認するには、特別なコンパイルフラグが必要です。通常の開発者にとって、コードカバレッジはそれほど重要ではありません。チームリーダーのように、コードが特定の品質を維持するように注意している人にとってはより重要です。
3
BЈовић

変更Aがテストを壊さず、変更Bがテストを壊さない場合を想像できますが、AとB togetherはそうです。 AとBが異なる開発者によって作成された場合、CIサーバーのみが新しいバグを検出します。 AとBは、同じ長い文の2つの部分である場合もあります。

2つの機関車AとBによって駆動される列車を想像してみてください。たぶん1つで十分であり、これが適用する修正です。ただし、2つの「修正」を適用して両方を削除すると、列車は移動しません。

また、すべての開発者がすべての単体テストを実行するわけではありませんが、優れた開発者のほとんどが実行します。

3
h22

同等の質問をしましょう:

なぜCIサーバーでコードを作成するのですか?

確かに、何かがマスターにコミットされるときまでに、開発者はすでにコードをビルドしており、新しいコードで発生した可能性のあるエラーを修正しています。それがコードを構築するポイントではありませんか?それ以外の場合は、壊れたコードをコミットしただけです。


CIを実行する理由はいくつかありますが、CIの主な目的は、コードの状態を経時的に把握することです。これが提供する主な利点(いくつかのうち)は、ビルドがいつ中断するかを見つけ、何が原因であるかを突き止めて修正できることです。

コードが壊れることがない場合、なぜCIを使用するのですか?テスト用のビルドを提供するには、夜間のビルドで十分です。

2
Peter