テスト⾃自動化を促進する
周辺技術とその運⽤用法

コベリティジャパン株式会社

動的解析と静的解析• 動的解析
• 利利点• ⾒見見つかった問題はすべて修正対象（誤検知はない）• パフォーマンスや発⽣生しうるタイミングの解析が可能• ⽋欠点：• 実際に動作させる必要がある＝解析⾃自体に⼈人的リソースが必要＝⾃自動化は困難• 問題が⾒見見つかってもその原因の特定が困難な場合がある• 静的解析
• 利利点• 全⾃自動、実⾏行行環境は必要ない• ⼈人的には困難な全制御パスのシミュレーションが可能• ⼈人間が介在しないため客観的な品質データを取得可能• ⽋欠点• 誤検知が発⽣生する＝ソースコードが存在しないライブラリなど• パフォーマンス、タイミングは解析できない静的解析の種類• コーディング規約チェック系• ベスト・プラクティスに基づいたコードの書き⽅方• 標準規約など予め定義したコーディングルールに対し違反がないかを確認• ランタイムエラー検出系• バグ⾃自体を検出• 従来、実⾏行行時でないと確認できなかった、メモリリーク、データ破壊、データ競合などを静的に検出• コベリティの強さ• スピード（差分ビルド、差分解析）• 精度度、根本原因の特定のし易易さ• 検出した問題の管理理（派⽣生開発サポート、フローに基づくバグ管理理）静的解析  –  ⼿手戻りを激減させるテクノロジー

SAT ソルバ

全パス &プロシージャ間解析

統計的な解析

ホワイトボックス
ファザー

不不具合が発⽣生しないパスを排除し、誤検知を減らす	

関数またはファイルに跨る不具合の検出	

プログラムの目的を推測し、予期しない動作を報告する	

汚染データを投入し、無害化されているかを自動的に確認する

void bar() {foo(p);if(p != 0) { ... }}if x=0
X!=0

X=0

...

...

int	  *p	  =	  malloc(sizeof(int));	  if(p	  !=	  0)	  	  *p	  =	  42;	  ...	  
int	  *p	  =	  malloc(sizeof(int));	  if(p	  !=	  0)	  	  *p	  =	  42;	  	  多分正しい	
If x != 0
X=0

X!=0
NULL の参照解除

void foo(int *p) {*p = 42;}

int	  *p	  =	  malloc(sizeof(int));	  *p	  =	  42;	  多分間違い

a b c d … <>&‘…

htmlEncode()&lt; &gt; &amp;&quot; &#x27;

例例：バッファーオーバーラン

シングルト
ンの変数
Address渡し

呼出し先の	  関数内表⽰示渡された変数を配列列としてアクセス	  8

例例：リソースリーク

呼出し先の関数内でアロケートされた領域を検知	

領域をを解放せずに	  ローカル変数を破棄	

9例例：コピペミス
変数名の書き換えミス関数外でも、	  検出可能

10例例：クロスサイトスクリプティング
入り口 (source)

経路

サニタイズすべき箇所

修正方法の提示検出した問題をトラッキングする開発組織、プロジェクト、サプライヤ

12	

Coverity を取り⼊入れた開発者ワークフロー
01001011
0101101011001
01101011000011
010100101101
01011001

問題を適切な開発者に
アサイン

結合レベルでの品質とセキュリティ脆弱性をチェック

14	

SCAN:  オープン・ソースの状況

15	

２０１３年年に利利⽤用者が急増機能が必要であることを示唆しています。	

16	

オープン・ソースの規模感17検出されたバグの密度度平均（年年別）Coverity によって自動検出されたバグのうち、影響度が高・中レベルのもの	
18	

Linux  の現在

19

Linuxコンポーネント別不不具合密度度20	Linux：不不具合修正の姿勢が変わった！
Number	  of	  Days	  to	  Fix	  Newly	  Detected	  Defects	  140	  120	  100	  80	  Number	  of	  Days	  to	  Fix	  Newly	  Detected	  Defects	  60	  40	  20	  0	  Jan.	   Feb.	   March	   April	   May	   June	   July	   Aug.	   Sept.	   Oct.	   Nov.	   Dec.	  

2013  年年から  Dave  Jones  が  Linux  の  Coverity  SCAN  担当に21	

今⽇日は  Coverity 開発チームの内情を…

23	

テスト⾃自動化
５つのチェックポイント

24	コベリティの製品リリースプロセス
⼀一般的なリリースプロセス:• 6 ヶ⽉月のリリースサイクル• 3 ヶ⽉月の次期リリース計画• リリース直前の  6 週間の    “ハードニング” サイクル
• 2 週間の “フィーチャーフリーズ”• 2 週間の “インテグレーションフリーズ”• 2 週間の “リリースフリーズ” と GA のためのアップロード• リリースのコードネームは                            カリフォルニア州の都市名• Alameda, Berkeley, Davis, Eureka, Fresno,

リリースを実⾏行行するプロセス:• アジャイルプロセス• 部⾨門横断的なスクラムチーム• 2 週間のスプリント• メールまたは対⾯面での⽇日次スタン
ド・アップ• Jira と PivotalTracker を介した進捗
管理理• Bugzilla によるバグ管理理• Jenkins-CI による継続的統合• 週１回のステータスミーティング• リリースハードニングでは、週に３回１つのリリースの詳細

Next Release Planning

Next Release Execution

Release Execution

Release Planning

Prev. Release Execution

October

DecemberNovember25	

February
January

AprilMarch

JuneMay

AugustJuly

6 Weeks
Hardening

September２年年前の状況
コベリティの製品構造概要:
1 Gc_rc gc_pbkdf2_sha1 (const char *P, size_t Plen,2const char *S, size_t Slen,3
unsigned int c,
4char *DK, size_t dkLen)
5 {6char U[20] T[20];7
unsigned int hlen = 20, u, l, r, i, k;
8int rc; char *tmp; size_t tmplen
910if (c == 0)11return GC_PKCS5_INVALID_ITERATION_COUNT;
12
r = dkLen - (l - 1) * hLen;
13
14
memcpy (tmp, S, Slen);End-to-end (E2E) tests
performed manually

Front EndAnalysis

Compilation

Core AnalysisCoverityConnect (CC)

Tests automatedand run during build

Tests automatedand run during build

Mostly manuallytestedDefect Management

２年前のテストアプローチ:•••
26

フロントエンドと解析のコンポーネントは自動化されたテストでテストされていたCoverity Connect はほとんどが手動でテスト
End-to-End のテストは手動で行われていた２年年前の状況• QA  プロセスは東ヨーロッパで                                                                                                                              アウトソースし実施していた• 伝統的な  QA  スキル、開発スキルは  わずかかもしくは皆無• 10時間の時差• ⾔言語的な壁• 6  週間のハードニングサイクルは  “ロシアン・ルーレット”のようなものだった• “フィーチャー実装完”  と  “フィーチャーテスト”  の時間的解離離• 開発者は品質に対して、即座の直接的な責任を感じていなかった• 何に出くわすかわからない  –  “簡単なバグ”  なのか  “致命的バグ”  なのか

• とるに⾜足らないバグに  QA  サイクルの多くが費やされていた• ⼿手動のプロセスでは、テストを  2-‐‑‒3  回しか回せない• 製品品質による苦しみ• よい品質でリリースするために、チームは多くのストレスを抱えていた27

No.5：本当に⾃自動化が効くのか？

• ６ヶ⽉月のメジャーリリースサイクル• サポートプラットフォームが⾮非常に多い• プラットフォームの違いのみのテストケースが多い• Jenkins 上のビルドは各プラットフォームに分散

28	

矯正への最初の試み• QAと開発の間の境界を取り除く• 組織的  +  時間的  (開発とテストを織り込んでいく)• 2011  初頭に組織を再編• 2/3  の  QA  リソースを開発組織に移管• ⽬目的を、テストの⾃自動化を名⽬目に、 　 　  “開発しながらテストする”  ように設定• しかし、結果は期待はずれだった• QA  チームはプログラミングに関してトレーニングされておらず、 　 　 　 　 　 　 　 　⾃自動テストを開発するのが困難であった• テストの⾃自動化に関しては、実際ごくわずかしか進歩しなかった• 時差と⾔言語の壁が存続していた29	

No.4:スキルセットが正しいか？  
• リソースを東ヨーロッパからカナダ、カルガリーに移動• 1 時間の時差• サンフランシスコから  2.5 時間のフライト• ⾔言語の壁がない• 2011 年年の夏に移⾏行行を開始• 移⾏行行は12ヶ⽉月以上かかった• 多くは予算に影響を与えなかった

Personnel(Transi,on(from((Eastern(Europe(to(Calgary(14"12"• スキルセットの変更更• テスト⾃自動化に焦点をあてたプログラミング
スキル• テストの⾃自動化に対する⾼高いモチベーション
30	

10"
8"
6"
4"
2"
0"
Q3"2011"

Q4"2011"

Q1"2012"Eastern"Europe"

Q2"2012"Calgary""

Q3"2012"

モチベーションの変化• テストの⾃自動化に集中する。
•とりわけ、Coverity Connect (CC) と End-to-End (E2E)• ⾃自動化されたテストにより２つの効果:•

フィーチャーに期待する挙動を成⽂文化:• テストと実装の間の  “ネゴシエーション”• テストがパスすれば、フィーチャーは “完了了” と宣⾔言できる•機能が完成したあとのリグレッションの検知:• 次のフィーチャーセットの作業をしている間の意図しない機能の変更更• 将来のフィーチャー開発のための  “ガードレール”• ただし、全てのテストがコードに密に連携して開発できるわけではない• テストのためのよいアーキテクチャが必要となる

31	

No.3: クリーンなコードか？
• もちろん、⾃自社製品を開発にも⾃自社製品を使⽤用• クリーンなコードでなければ、⾃自動化も進まない
Defects'Addressed'by'Coverity'Quality/Security'Advisor''
Number'of'Defects'

400"
350"
300"
250"
200"
150"
100"
50"
0"
Alameda"Berkeley"High"Impact"

Carmel"Medium"Impact"

Davis"
Low"Impact"

Eureka*"32	  Coverity Connect の⾃自動テストの例例

33

テスト⾃自動化の進捗• 2011年年秋〜～2013年年春までの  Coverity Connect と End-to-End のテスト⾃自動化の結果

CC"Test"Automa,on"Progress"

E2E#Test#Automa-on#Progress#

1750'

4000'

1500'

3500'
3000'

1250'

2500'

1000'

2000'

750'

1500'

500'

1000'

250'
0'

500'
0'

Alameda'Berkeley'

Carmel'Davis'

Today'

Alameda'Berkeley'

Carmel'Davis'

Manual'CC'GUI'Tests'

347'

661'

1006'

931'

1194'

Manual'E2E'Tests'

300'

370'

175'

143'

60'

Automated'CC'GUI''Tests'

0'

2'

44'

220'

403'

Automated'E2E'Tests'

0'

120'

1468'

1761'

3466'

E2E'Manual'Tes1ng'Eﬀort'

120"

20"

100"

16"

Person'Days'

Person'Days'

CC'Manual'Tes0ng'Eﬀort'

80"
60"
40"
20"
0"	

12"
8"
4"
0"

Alameda"34

Today'

Berkeley"

Carmel"Davis"

Today"

Alameda"Berkeley"

Carmel"Davis"

Today"

インフラ• 短いテストのほとんどは、Jenkins 上のビルドプロセスの⼀一部として実⾏行行される• ⾃自動化テストのスケジュールとレポートのため、システムを拡張• すべてのプラットフォームのためのテストを 　 　⾃自動化するため、サーバに⼤大きな投資• システムの⾃自動割当
Hardware'for'STS'Test'Farm'
250#
200#
183#

150#

215#

156#
125#

100#
50#

201#

65# 66#

69# 74#

70#

81#

71#

84#

100#
77#

88#

128#
88#

96#

108#

126#

127#

0#
Pre/2011# Q1#2011# Q2#2011# Q3#2011# Q4#2011# Q1#2012# Q2#2012# Q3#2012# Q4#2012# Q1#2013#
Number#of#Physical#Machines#35	

Total#Number#of#Machines#incl.#Virtual#Machines#Today#⾃自動化を⽀支えた新しい考え⽅方と技術…

The Ultimate Machine – Claude Elwood Shannon	

http://www.kugelbahn.ch/sesam_e.htm	

No.２: カバレッジの罠にはまらない• 進捗を計測する良良い指標がないことに気づいた• コードカバレッジはテスト⼯工数に関しては良良い指標ではなかった• 新機能のコードは、全体のカバレッジで把握しにくい• “開発しながらテストする”ことを牽引する計測可能な基準の⽋欠如

37	テストされたコード（％）% Code Tested

コードカバレッジに対するチャレンジ
100%

1

Diminishingreturn for
テスト⼯工数の増加
increased
test effort
に対し効果は減少- ...

3

Effortto develop tests
テスト作成の⼯工数382

テストできないコードも存在
Not
all code is testable-- unreachable
到達できないステートメント
statements- デッドコード- dead code, ...

テストを⾏行行う価値がないコード
Not
all tested code adds
重要でないコードequal value to the test
- デバッグコード、既存コード- non-critical code
- 決まりきった例例外処理理code, legacy code-- debug…
- exception handling, ...

No.1: 優先度度を設定しているか？

• どこからテストすべきか？
• 以下のコードに着⽬目した⾃自動テスト開発をガイドする• 新規コード• リスクの⾼高い部分を特に識識別• 関連のないコードを除外• テストが不不⼗十分なコードを開発者に⾃自動的に通知し、その対処を促す• アジャイルな受⼊入れプロセスの⼀一部として“テスト⼗十分性”の施⾏行行を可能に

39	

実験
“チェンジセット”にフォーカスしたテストポリシーを評価する単純な試み• フロントエンドと解析コード数：1,372,376 ⾏行行• 1,149,036 ⾏行行がテストでカバー (83.7% カバレッジ), 223,340 ⾏行行が未テスト• 直前の変更更にフォーカスすると、145 ファイル内の  851 ⾏行行をカバーする必要がある

Untested	  LOC	  250,000	  	  2500	  223,340	  	  1979	  200,000	  	  2000	  1743	  150,000	  	  1500	  100,000	  	  1000	  404	  50,000	  	  -­‐	  	  	  	  9,636	  	  7,934	  	  145	  851	  	  Total	  Since	  5.3	  Since	  5.4	  Since	  5.4.1	  Untested	  LOC	  223,340	  	  9,636	  	  7,934	  	  851	  	  Untested	  LOC	  (%)	  100.0%	  2.0%	  1.6%	  0.2%	  #	  Incomplete	  Tested	  Files	  1979	  1743	  404	  145	  500	  0	  #	  Incomplete	  Tested	  Files	  Focus	  tes6ng	  on	  latest	  changes	  	#	  Incomplete	  Tested	  Files	  明らかに対処しやすい:••

40

Untested	  LOC	  

未テストコードの 0.2%
未テストファイルの 7%

⾃自動テスト開発⽀支援ツールの実装
独自に作り込み	
せめて新規コードと	それに影響をうけるところ	

だけでも….		

外部SCMから入力	

ソース
変更更情報

変更更の影響カバレッジ

外部カバッレジツールから入力	優先的にテストすべき箇所、優先的に修正すべきテストを開発者に通知
41	

変更更の影響解析• チェンジインパクト解析は、変更更があったコードが、他のコードに影響を与えるかどうかを的確に判断する。

• 例例１: 関数の挙動の変更更は、その関数を呼び出すコードに影響を与える場合がある• 例例２: クラスの継承関係の変更更は、仮想関数呼出し時の実装決定に影響を与える場合がある

42	

Foo

f15

f56

影響を受ける
コード

f34

f25

f87

f33

f77

f76

...

...

...

f89

...

...

f90

f34

...

...

変更されたコード

f32f54

f67

...

...

...

f23

...

レガシーコード...

変更の“波及域”

これまでは構造的に⾒見見るのが主流流

呼出先関数を表⽰示

Coverity Confidential 	もう⼀一つ先へ。変更更の影響解析の例例
returns	  void	  void	  f(int	  x)	  {	  	  	  	  	  g(x);	  }	  returns	  non-­‐null	  	  Integer	  g(int	  x)	  {	  	  	  	  	  Integer	  boxed	  =	  new	  Integer(x);	  	  	  	  	  return	  boxed;	  }	  returns	  void	  void	  f(int	  x)	  {	  	  	  	  	  g(x);	  }	  returns	  non-­‐null	  	  Integer	  g(int	  x)	  {	  	  	  	  	  if	  (x	  <	  0)	  {	  	  	  	  	  	  	  	  	  warn(“negative”);	  	  	  	  	  }	  	  	  	  	  Integer	  boxed	  =	  new	  Integer(x);	  returns	  non-­‐null	  returns	  void	  	  	  	  	  return	  boxed;	  Integer	  f(int	  x)	  {	  void	  f(int	  x)	  {	  }	  	  	  	  	  return	  g(x);	  	  	  	  	  g(x);	  }	  }	  	  returns	  non-­‐null	  may	  return	  null	  	  Integer	  g(int	  x)	  {	  Integer	  g(int	  x)	  {	  	  	  	  	  Integer	  boxed	  =	  new	  Integer(x);	  	  	  	  	  if	  (x	  <	  0)	  {	  may	  return	  null	   	  	  	  	  	  	  	  	  error(“negative”);	  	  	  	  	  return	  boxed;	  Integer	  f(int	  x)	  {	  }	  	  	  	  	  	  	  	  	  return	  null;	  	  	  	  	  return	  g(x);	  	  	  	  	  }	  }	  	  	  	  	  Integer	  boxed	  =	  new	  Integer(x);	  may	  return	  null	   	  	  	  	  return	  boxed;	  	  Integer	  g(int	  x)	  {	  }	  	  	  	  	  if	  (x	  <	  0)	  {	  	  	  	  	  	  	  	  	  error(“negative”);	  	  	  	  	  	  	  	  	  return	  null;	  	  	  	  	  }	  	  	  	  	  Integer	  boxed	  =	  new	  Integer(x);	  	  	  	  	  return	  boxed;	  }	  44	

社内での経験 – ケーススタディ• ⼗十分テストされている製品のコンポーネントにこの社内ツールを適⽤用• 3ヶ⽉月間、１テストエンジニアが１週間のうち４時間、テストすべきと判断された箇
所にテストを追加した• テストポリシー:  テスト可能なコードは  100%  テストする  (除外：  デバッグコード,  実⾏行行されないコード,  その他)

Test'Advisor'Applica:on'in'Frontend'Project'
20"
18"

30"

16"

25"

14"
12"

20"

10"
15"

8"
6"

10"

4"

5"

2"
0"

28
*A
pr
*1
2"
5*
M
ay
*12"
12*M
ay*12"
19*M
ay*12"
26*M
ay*12"
2*Jun*
12"
9*Jun*12"
16*Jun*12"23*Jun*12"
30*Jun*12"
7*
Ju
l*12"
14*Ju
l*12"
21*Ju
l*12"0"Date'45

Tests"added"through"TA"

Bugs"found"by"TA"tests"

Number'of'Bugs'Found'Number'of'Tests'from'TA'

35"

••

１⼈人週間換算で29件のテストを追加
製品から19件のバグを発⾒見見  –  いくつかは重⼤大なもの• 例例：  Keil  コンパイラの正しい機能を阻害するバグなど

製品顧客が発⾒見見した不不具合
Customer4found+Defects+
Normalized+Number+of+Defects+

1.6"
1.4"
1.2"
1"
0.8"
0.6"
0.4"
0.2"
0"
Alameda"Berkeley"

Carmel"Davis"

46	

Coverity 製品にもこの技術を組み込む• Coverity  Test  Advisor 　（Java, 　C/C++,  C#）
• 変更更の影響箇所、⾼高リスク箇所をお知らせします47	インパクト解析を取り⼊入れた
テスト⾃自動化ワークフロー
01

01001011
0101101011001
01101011000011
010100101101
01011001

問題を適切な開発者にアサイン
テスト作成とアップデート
結合レベルでの品質とセキュリティ脆弱性をチェック
コードの追加・変更のため、新しいテストが必要かチェック
49	

まとめ
• No.5:  テスト⾃自動化が解決策？
• No.4:  スキルセットは正しい？
• No.3:  クリーンなコード?
• No.2:  正しい計測？
• No.1:  優先度度を設定せよ！

Make every developera rock star !	
50	

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	  Veriﬁcation	  Engine	   　 　 　 　 　 　 　商⽤用コード 　|      オープンソースコード
51	

ALM	  連携	  HP	  |	  IBM