Comments
Description
Transcript
テスト自動化を再考しよう
コべリティプライベートセミナー テスト自動化を再考しよう ~ソフトウェア・サプライチェーン統制のことはじめ~ 主催:コベリティ日本支社 共催:株式会社東陽テクニカ Introduction to Coverity September, 2013 Coverity について Company Facts Product Facts • 2003年に Stanford University • C, C++ の静的解析からスタート Research Laboratory 内で設立 • 現在では Java と C#をサポート • 従業員 300 人 – 30% 以上が • 品質、セキュリティ、テスト効率 R&D に所属 • 1ダースを超える特許 • San Francisco, Boston, New 化に関わる製品群 York, Seattle, Calgary, London, Paris, 大阪, 東京, Bangalore, Beijing 3 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 Customer Facts • 1,100 を超える顧客 • 500 のオープン・ソースプ ロジェクトを解析 • 100,000 ユーザ • 50 億行のソースコードが コベリティで解析されてい る コベリティのミッション 早期にバグ・脆弱性の修正を行い、後工程での手戻りを減らす 設計 開発 5倍のコスト 4 QA 10倍のコスト 製品リリース & 管理 30倍のコスト コベリティのミッション 早期にバグ・脆弱性の修正を行い、後工程での手戻りを減らす 早い段階で不具合を除去 設計 開発 5倍のコスト 5 QA 10倍のコスト 製品リリース & 管理 30倍のコスト あらゆる分野で適用 (C/C++, Java, C# をサポート) Industrial Automation • Automotive • Gaming Over 1,200 High Integrity Brands Coverity Development Testing Platform 解析 | 修正 | 統制 解析パッケージ SDLC 統合 Policy Manager サードパーティ メトリクス Dynamic Analysis IDE Coverity Connect Architecture Analysis 解析結果統合 コード カバレッジ Quality Advisor Security Advisor Test Advisor FindBugs™ | FxCop テスト 実行 ビルド/ 継続的統合 バグ トラッキング SCM 解析結果統合 ツールキット Coverity SAVE™ Static Analysis Verification Engine 商用コード | オープンソースコード 8 ALM 連携 HP | IBM Improving Software Quality Through Test Automation (Japanese version) Andreas Kuehlmann Senior Vice President of Research & Development, Coverity September, 2013 Coverity 社内の テスト自動化プロセス Coverity’s Internal Test Automation Process 10 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 コベリティのリリースプロセス (Our Release Process) 一般的なリリースプロセス: • 6 ヶ月のリリースサイクル • 3 ヶ月の次期リリース計画 • リリース直前の6 週間の “ハードニング” サイクル • 2 週間の “フィーチャーフリーズ” • 2 週間の “インテグレーションフリーズ” • 2 週間の “リリースフリーズ” と GA のための アップロード • リリースのコードネームはカリフォルニ ア州の都市名 リリースを実行するプロセス: • アジャイルプロセス • 部門横断的なスクラムチーム • 2 週間のスプリント • メールまたは対面での日次スタン ド・アップ • Jira と Pivotal を介した進捗管理 • Bugzilla によるバグ管理 • 週1回のステータスミーティング • Alameda, Berkeley, Davis, Eureka, Fresno, … 1つのリリースの詳細 11 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 • リリースハードニングでは、週に3回 2年前の状況 (Where We Were Two Years Ago) コベリティの製品構造概要: 2年前のテストアプローチ: • • • 12 フロントエンドと解析のコンポーネントは自動化されたテストでテストされていた ここでは、この最後の Coverity Connect はほとんどが手動でテスト 2つのエリアに End-to-End のテストは手動で行われていた Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 フォーカスします 2年前の状況 (Where We Were Two Years Ago) • QA プロセスは東ヨーロッパでアウトソース し実施していた • 伝統的な QA スキル、開発スキルは わずかかもしくは皆無 • 10時間の時差 • 言語的な壁 • 6 週間のハードニングサイクルは “ロシアン・ルーレット”のようなものだった • “フィーチャー実装完” と “フィーチャーテスト” の時間的解離 • 開発者は品質に対して、即座の直接的な責任を感じていなかった • 何に出くわすかわからない – “簡単なバグ” なのか “致命的バグ” なのか • とるに足らないバグに QA サイクルの多くが費やされていた • 手動のプロセスでは、テストを 2-3 回しか回せない • 製品品質による苦しみ • よい品質でリリースするために、チームは多くのストレスを抱えていた 13 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 矯正への最初の試み (A First Attempt to Remediate) • QAと開発の間の境界を取り除く • 組織的 • 時間的 (開発とテストを織り込んでいく) • 2011 初頭に組織を再編 • 2/3 の QA リソースを開発組織に移管 • 目的を、テストの自動化を通して、 “開発しながらテストする” ように設定した • 結果は期待はずれだった • QA チームはプログラミングに関してトレーニングされておらず、自動テストを開発 するのが困難であった • テストの自動化に関しては、実際ごくわずかしか進歩しなかった • 時差と言語の壁が存続していた 14 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 さらなる抜本的な改革 More Drastic Changes 15 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 抜本的な改革 – 人 (More Drastic Changes – People) • リソースを東ヨーロッパから カナダ、カルガリーに移動 • 1 時間の時差 • サンフランシスコから 2.5 時間のフライト • 言語の壁がない • エンジニアのインタビュープロセスに的を絞り 2011 年の夏に移行を開始 • 移行は12ヶ月以上かかった • 多くは予算に影響を与えなかった • スキルセットの変更 • テスト自動化に焦点をあてたプログラミング スキル • テストの自動化に対する高いモチベーション 16 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 抜本的な改革 – プロセス (More Drastic Changes – Process) • 可能なかぎり多くのテストの自動化に集中する。とりわけ、Coverity Connect (CC) と End-to-End (E2E) • 自動化されたテストにより2つの効果が得られる: • フィーチャーに期待する挙動を成文化: • テストと実装の間の “ネゴシエーション” • テストがパスすれば、フィーチャーは “完了” と宣言できる • 機能が完成したあとのリグレッションを検知できる • 次のフィーチャーセットの作業をしている間の 意図しない機能の変更 • 将来のフィーチャー開発のための “ガードレール” • 全てのテストがコードに密に連携して開発できるわけではない • テストのためのよいアーキテクチャが要求される 17 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 Coverity Connect の自動テストの例 (Example of Automated Test in CC) 18 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 テスト自動化の進捗 (Progress in Test Automation) • 2011年秋〜2013年春までの Coverity Connect と End-to-End のテスト自 動化の結果 19 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 テクノロジー (Technology) • 短いテストのほとんどはビルドプロセスの一部として実行される • 自動化テストのスケジュールとレポートのため、システムを拡張 • すべてのプラットフォームのためのテストを 自動化するため、サーバに大きな投資 • システムの自動割当 20 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 テクノロジー (Technology) • “Product on Product” – 自分の製品を自ら試す • “Coverity-クリーン” がリリース基準 21 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 テクノロジー 新しい製品の誕生 Technology – A New Product is Born 22 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 我々のテスト開発にフォーカス (Focusing Our Test Development) • ユニットテストへの注力とその進捗を計測する 良い方法を持ちあわせていなかった • コードカバレッジはテスト工数に関しては良い指標ではない • 新機能のコードは、全体のカバレッジで把握しにくい • “開発しながらテストする”ことを牽引する計測可能な 基準の欠如 • ツールが必要: • 以下のコードに着目した自動テスト開発をガイドする • 新規コード • リスクの高い部分を特に識別 • 関連のないコードを除外 • テストが不十分なコードを開発者に自動的に通知し、その対処を促すワークフロー • アジャイルな受入れプロセスの一部として“テスト十分性”の施行を可能にする、管理 上の可視性 23 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 コードカバレッジに付随するチャンレジ テストされたコード (%) (The Challenge with Code Coverage) テスト工数の増加 に対し効果は減少 テスト作成の工数 24 テストできないコードも存 在 - 到達できないステートメ ント - デッドコード -テストを行う価値がない ... コード - 重要でないコード - デバッグコード、既存 コード - 決まりきった例外処理 - … Coverity コード (FE + Analysis)への試み (Experiment on Coverity Code (FE + Analysis)) “チェンジセット”にフォーカスしたテストポリシーを評価する単純な試み • フロントエンドと解析コード数:1,372,376 行 • 1,149,036 行がテストでカバー (83.7% カバレッジ), 223,340 行が未テスト • 直前の変更にフォーカスすると、 145 ファイル内の 851 行をカバーする必要があ る Untested LOC 250,000 200,000 2500 223,340 1979 2000 1743 150,000 1500 1000 100,000 404 50,000 - Untested LOC Untested LOC (%) # Incomplete Tested Files 9,636 Total 223,340 100.0% 1979 Since 5.3 9,636 2.0% 1743 7,934 Since 5.4 7,934 1.6% 404 145 500 851 Since 5.4.1 851 0.2% 145 0 # Incomplete Tested Files Focus testing on latest changes Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 # Incomplete Tested Files 明らかに対処しやすい: • • 25 Untested LOC 未テストコードの 0.2% 未テストファイルの 7% Test Advisor – 製品コンポーネント テスト アドバイス 不十分なテストのリスクを見極める アクション可能な作業項目 テストポリシー評価 • クリティカルコード解析 • チェンジインパクト解析 • テスト実行解析 テストモニタリン グ 26 コードオーナと 変更履歴 静的コード解析 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 カスタマイ ズ テスト ポリシー Test Advisor への入力成分 テスト アドバイス (Ingredient to Test Advisor) 不十分なテストのリスクを見極める アクション可能な作業項目 テストポリシー評価 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 27 Gc_rc gc_pbkdf2_sha1 (const char *P, size_t Plen, const char *S, size_t Slen, unsigned int c, char *DK, size_t dkLen) { char U[20] T[20]; unsigned int hlen = 20, u, l, r, i, k; int rc; char *tmp; size_t tmplen = Slen + 4; if (c == 0) return GC_PKCS5_INVALID_ITERATION_COUNT; r = dkLen - (l - 1) * hLen; memcpy (tmp, S, Slen); for (i = 1; i <= l; i++) { memset (T, 0, hLen); for (u = 1; u <= c; u++) { if (u == 1) { tmp[Slen + 0] = (i & 0xff000000) >> 24; tmp[Slen + 1] = (i & 0x00ff0000) >> 16; tmp[Slen + 2] = (i & 0x0000ff00) >> 8; tmp[Slen + 3] = (i & 0x000000ff) >> 0; rc = gc_hmac_sha1 (P, Plen, tmp, tmplen, U); } else rc = gc_hmac_sha1 (P, Plen, U, hLen, U); if (rc != GC_OK) { free (tmp); return rc; } for (k = 0; k < hLen; k++) T[k] ^= U[k]; #ifdef DEBUG printf("Value: %d¥n", u); #endif } memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen); } free (tmp); return GC_OK; } Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 テストモニタ リング コードオーナ と 変更履歴 静的コード解 析 カスタ マイズ テスト ポリ シー 入力成分1:テスト実行からの入力 テスト アドバイス (Input from Test Execution) 不十分なテストのリスクを見極める アクション可能な作業項目 テストポリシー評価 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 28 Gc_rc gc_pbkdf2_sha1 (const char *P, size_t Plen, const char *S, size_t Slen, unsigned int c, char *DK, size_t dkLen) { char U[20] T[20]; unsigned int hlen = 20, u, l, r, i, k; int rc; char *tmp; size_t tmplen = Slen + 4; if (c == 0) return GC_PKCS5_INVALID_ITERATION_COUNT; r = dkLen - (l - 1) * hLen; memcpy (tmp, S, Slen); for (i = 1; i <= l; i++) { memset (T, 0, hLen); for (u = 1; u <= c; u++) { if (u == 1) { tmp[Slen + 0] = (i & 0xff000000) >> 24; tmp[Slen + 1] = (i & 0x00ff0000) >> 16; tmp[Slen + 2] = (i & 0x0000ff00) >> 8; tmp[Slen + 3] = (i & 0x000000ff) >> 0; rc = gc_hmac_sha1 (P, Plen, tmp, tmplen, U); } else rc = gc_hmac_sha1 (P, Plen, U, hLen, U); if (rc != GC_OK) { free (tmp); return rc; } for (k = 0; k < hLen; k++) T[k] ^= U[k]; #ifdef DEBUG printf("Value: %d¥n", u); #endif } memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen); } テストモニタ リング コードオーナ と 変更履歴 静的コード解 析 カスタ マイズ テスト ポリ シー テスト実行中のコードインストゥルメント (e.g. coverage tools) を通して データを獲得 このコードは以下でテストされてい る: • Test_name1.c • Test_name2.c • … このコードはテストされていない free (tmp); return GC_OK; } Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 入力成分2: SCMからの入力 テスト アドバイス 不十分なテストのリスクを見極める (Input from Source Code Repository (SCM)) アクション可能な作業項目 テストポリシー評価 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 29 Gc_rc gc_pbkdf2_sha1 (const char *P, size_t Plen, const char *S, size_t Slen, unsigned int c, char *DK, size_t dkLen) { char U[20] T[20]; unsigned int hlen = 20, u, l, r, i, k; int rc; char *tmp; size_t tmplen = Slen + 4; if (c == 0) return GC_PKCS5_INVALID_ITERATION_COUNT; r = dkLen - (l - 1) * hLen; memcpy (tmp, S, Slen); for (i = 1; i <= l; i++) { memset (T, 0, hLen); for (u = 1; u <= c; u++) { if (u == 1) { tmp[Slen + 0] = (i & 0xff000000) >> 24; tmp[Slen + 1] = (i & 0x00ff0000) >> 16; tmp[Slen + 2] = (i & 0x0000ff00) >> 8; tmp[Slen + 3] = (i & 0x000000ff) >> 0; rc = gc_hmac_sha1 (P, Plen, tmp, tmplen, U); } else rc = gc_hmac_sha1 (P, Plen, U, hLen, U); if (rc != GC_OK) { free (tmp); return rc; } for (k = 0; k < hLen; k++) T[k] ^= U[k]; #ifdef DEBUG printf("Value: %d¥n", u); #endif } memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen); } テストモニタ リング コードオーナ と 変更履歴 静的コード解 析 ソースコードレポジトリから 獲得したデータ このコードは Albert Miller によって 1987/12/14 に書か れた このコードは Peter Pan に よって 2-9-2012/2/9 に書か れた このコーdは Dave Fastcode によって 2012/3/18 に変更 された free (tmp); return GC_OK; } Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 カスタ マイズ テスト ポリ シー 入力成分3: 静的解析からの入力 テスト アドバイス (Static Analysis Intelligence) 1 int gc_hmac_sha1 (const char *P, size_t Plen, 2 1 Gc_rc gc_pbkdf2_sha1 (const char *P, size_t Plen, 3 2 const char *S, size_t Slen, 4 3 unsigned int c, 5 4 char *DK, size_t dkLen) 6 5 { 7 6 char U[20] T[20]; 8 7 unsigned int hlen = 20, u, l, r, i, k; 9 8 int rc; char *tmp; size_t tmplen = Slen + 4; 10 9 11 10 if (c == 0) 12 11 return GC_PKCS5_INVALID_ITERATION_COUNT; 13 12 r = dkLen - (l - 1) * hLen; 14 13 15 14 memcpy (tmp, S, Slen); 16 15 for (i = 1; i <= l; i++) { 17 16 memset (T, 0, hLen); 18 17 for (u = 1; u <= c; u++) { 19 18 if (u == 1) { 20 19 tmp[Slen + 0] = (i & 0xff000000) >> 24; 21 20 tmp[Slen + 1] = (i & 0x00ff0000) >> 16; 22 21 tmp[Slen + 2] = (i & 0x0000ff00) >> 8; 23 22 tmp[Slen + 3] = (i & 0x000000ff) >> 0; 24 23 rc = gc_hmac_sha1 (P, Plen, tmp, tmplen, U); 25 24 } 26 25 else rc = gc_hmac_sha1 (P, Plen, U, hLen, U); 27 26 28 27 if (rc != GC_OK) { 29 28 free (tmp); 30 29 return rc; 31 30 } 32 31 for (k = 0; k < hLen; k++) T[k] ^= U[k]; 33 32 #ifdef DEBUG 34 33 printf("Value: %d¥n", u); 35 34 #endif 35 } 36 memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen); 37 } 38 39 free (tmp); 40 return GC_OK; 41 } 30 不十分なテストのリスクを見極める アクション可能な作業項目 テストポリシー評価 テストモニタ リング コードオーナ と 変更履歴 静的コード解 析 カスタ マイズ テスト ポリ シー コードのシンタックスとセマンティックス 根拠を深く理解する 強力なプロシージャ間静的解析 テストされる入力パラメー タのチェックを識別 システムの他の部分の変更 の影響を受けるテストすべ きコードの識別 テスト不要の デバッグコードを識別 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 入力成分4: 強力なテストポリシー仕様 テスト アドバイス (Powerful Specification for Test Policy) 不十分なテストのリスクを見極める アクション可能な作業項目 テストポリシー評価 1 // Policy that requires 100% of code to be covered at the 2 // file granularity if it has changed since 2012-01-01, 3 // but ignores code that has only whitespace change 4 { 5 type: "Coverity test policy definition", 6 format_version: 1, 7 recent_date_cutoff: "2012-01-01", 8 old_date_cutoff: "2010-12-01", 9 10 rules: [ 11 { 12 violation_name: "RECENT_CODE_NON_WS_CHG", 13 aggregation_granularity: "file", 14 minimum_line_coverage_pct: 100, 15 16 // Only look at recently changed lines. 17 line_filters: [ 18 { 19 min_modified_date: "2012-01-01", 20 }, 21 Policy that ], requires that all ways a function can terminate // // 22 normally be covered by tests. // Only look at lines in functions whose syntactic {23 24 type: "Coverity // structure changed. test recently policy definition", 25 format_version: function_filters: [ 1, 26 { 27 rules: [ min_ast_date: "2012-01-01", 28 }, { 29 ], violation_name: "cover-all-returns", 30 aggregation_granularity: }, "function", 31 ], minimum_line_coverage_pct: 100, // Tests must exercise all // lines that 32 }, line_filters: [ { contains_astnode: { // contain an AST node that is_function_end_statement: true, // is the last stemt before // the function terminates }, }, ], }, ], } テストモニタ リング コードオーナ と 変更履歴 カスタ マイズ テスト 静的コード解 析 ポリ シー 製品コンポーネントやチームに合った 詳細度でテストポリシーを指定 • 30 以上のきめ細やかな基準を テスト開発にフォーカスするために用意 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 31 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 新規コードは 100% テストす ることを指定したポリシー すべての関数の戻り値がテスト されることを要求したポリシー 結果 – テスト違反 (The Result - Testing Violations) テスト違反と 不具合の 統一ビュー 違反の 明確な記述 コード中のど こで違反が発生 しているかを識 別 今後派生する テストの出発点 32 Confidential : For Coverity and Partner use onl y. Copyright Coverity, Inc., 2013 違反を自動的 に オーナに割当 て 社内での経験 – ケーススタディ (In-House Experience – A Case Study) • 十分テストされている製品のコンポーネントに Test Advisor を適用 • 1テストエンジニアが1週間のうち4時間、テスト違反の箇所にテストを追 加した • テストポリシー: テスト可能なコードは 100% テストする (除外: デバッグ コード, 実行されないコード, その他) • 1人週間換算で29件のテストを追 加 • 製品から19件のバグを発見 – いく つかは重大なもの • 例: Keil コンパイラの正しい 機能を阻害するバグ 33 Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013 結果 (Results) • テストの自動化に顕著な進展がみられた • E2E テストの 97% が自動化された • Coverity Connect の 25% のテストが自動化された– 次の春までに 80% 以上の自 動化を目指す • 顧客が発見した不具合に計測可能なレベルの減少がみられた 34 詳細は http://www.coverity.com にて • “テスト自動化”で検索ください Confidential: For Coverity and Partner use only. Copyright Coverity, Inc., 2013