code complete ch22_developper_test

67
Code Complete (Ch22 Developer Testing) 2010/12/17 shiumachi http://d.hatena.ne.jp/shiumachi/ http://twitter.com/shiumachi http://www.facebook.com/sho.shimauchi

Upload: sho-shimauchi

Post on 29-Nov-2014

1.657 views

Category:

Documents


0 download

DESCRIPTION

This presentationt is written about "Code Complete" Chapter 22 Developer Testing.This chapter describes how important developer test is and how to perform efficient developer testing.

TRANSCRIPT

Page 1: Code complete ch22_developper_test

Code Complete(Ch22 Developer Testing)

2010/12/17shiumachi

http://d.hatena.ne.jp/shiumachi/http://twitter.com/shiumachi

http://www.facebook.com/sho.shimauchi

Page 2: Code complete ch22_developper_test

Agenda

● 22章 開発者テスト● 22.1 ソフトウェア品質における開発者テストの役割● 22.2 開発者テストの推奨アプローチ● 22.3 テストに関するあれこれ● 22.4 典型的エラー● 22.5 テスト支援ツール● 22.6 テストを改善する● 22.7 テスト記録を保存する

Page 3: Code complete ch22_developper_test

はじめに● この資料は、某所で開催されている「Code

Complete 読書会」での発表資料です● 原著、つまり英語版の Code Complete をベースにしているので日本語版と訳語が違う場合があります● 誤読とかも普通にありますので気づいたら指摘していただけるとうれしいです

Page 4: Code complete ch22_developper_test

Chapter 22 Developer Testing22 章開発者テスト

Page 5: Code complete ch22_developper_test

Ch. 22 開発者テスト

Ch. 20 ソフトウェア品質の展望

Ch. 21 協調コンストラクションの実践

Ch. 23 デバッグ

Ch. 29 インテグレーション

Ch. 3 コンストラクション実行のための前提条件

関連トピック

Page 6: Code complete ch22_developper_test

テストの種類(1)

● ユニットテスト● 一人のプログラマが書く程度のクラス、ルーチン、小さなプログラムのテスト

● コンポーネントテスト● 複数のプログラマが書く程度のクラス、パッケージ、小さなプログラムのテスト

● 統合テスト● 2つ以上のクラス、パッケージ、コンポーネント、サブシステムなどを組み合わせたテスト

● 通常はテスト対象のクラスが2つできたらすぐに開始する

Page 7: Code complete ch22_developper_test

テストの種類(2)

● リグレッションテスト● 以前実行して通ったテストをもう一度実行する

● システムテスト● 最終調整のためのテスト● 他のソフト・ハードとの統合テスト、セキュリティ、性能、リソース枯渇、タイミング問題などの低レベルの統合ではテストできなかった問題をテストする

● その他のテスト(この章の範囲外)● βテスト、顧客受け入れテスト、性能テスト、設定テスト、プラットフォームテスト、ストレステスト、ユーザビリティテストなど

Page 8: Code complete ch22_developper_test

テスト

開発者が実行するテスト 開発者以外が実行するテスト

ユニットテスト

コンポーネントテスト

結合テスト

リグレッションテスト

システムテスト

βテスト

顧客受け入れテスト

性能テスト

設定テスト

プラットフォームテスト

ストレステスト

ユーザビリティテスト

この章のスコープはこちら

Page 9: Code complete ch22_developper_test

ブラックボックステストとホワイトボックステスト

● ブラックボックステスト● テスターは内部構造を見れない● この章の範囲外

● ホワイトボックステスト● テスターは内部構造を理解している● この章の範囲はこちら

Page 10: Code complete ch22_developper_test

テストとデバッグ● テスト

● エラーを検知するためのもの● この章の範囲はこちら

● デバッグ● 既に検知されているエラーを分析・修正するためのもの

● 23章で扱う

Page 11: Code complete ch22_developper_test

22.1 ソフトウェア品質における開発者テストの役割

Page 12: Code complete ch22_developper_test

テストだけじゃ効果が薄い● ソフトウェア品質においてテストは重要である● 残念ながら多くの場合、テストだけがソフトウェア品質プログラムに使われる

● テストよりも協調開発の方が半分以下のコストでより多くのエラーを検出可能

Page 13: Code complete ch22_developper_test

一つのテストだけじゃ効果が薄い● 単一のテストだけでは50%以下のエラーしか検知できない● どのテストでも同じ

● 組み合わせて使用してようやく60%以下になる

Page 14: Code complete ch22_developper_test

テストを開発者が嫌がる理由● テストだけが、開発を終わらせることを目的としていない

● テストはエラーがないことを保証してくれない● テストそれ自体はソフトウェア品質を向上しない

● テストは開発者に「自分のコードからエラーを見つけようとすること」を要求する● でも多くの開発者はエラーなんて見つけたくない

Page 15: Code complete ch22_developper_test

プロジェクトに占める開発者テストの割合

2,000行程度だと25%、500,000行だと8%ほど

Page 16: Code complete ch22_developper_test

開発者テストの結果の使い道● 開発中における製品の信頼性のアセスメント● ソフトウェア修正のためのガイド● エラーの統計情報を活用

● 適切な研修の実施● 次回のテクニカルレビューにおける指針● 次回のテストケースの作成

Page 17: Code complete ch22_developper_test

22.2 開発者テストの推奨アプローチ

Page 18: Code complete ch22_developper_test

システマティックにテストしよう(1)

● 要件1つ1つに対し、その要件が実装されていることを確認できるテストをすること● セキュリティ、ストレージ、インストールプロセス、システム可用性などに注意– 要件定義時には見過ごされている

● 設計1つ1つに対し、その設計が実装されていることを確認できるテストをすること● テストケースはできる限り早く、遅くとも設計フェーズで計画すること

Page 19: Code complete ch22_developper_test

システマティックにテストしよう(2)

● 「基礎テスト」を詳細テストケースに加える● データフローテスト● コードカバレッジ100%にするためのテスト

● 開発組織内で作り上げられてきたエラーチェックリストを活用する

● →テストケースを設計する 要件バグ・仕様バグ→が減る エラー修正コストが減る

Page 20: Code complete ch22_developper_test

テストファーストしよう

理由:安上がりだからバグを仕込んでから修正までの時間が短いほどコストは下がる

Page 21: Code complete ch22_developper_test

テストファーストする理由● テストラストより苦労して書くことはない● 不具合を仕込んでも発見が早くなる● コードを書く前に要件や設計について考えるようになる

● 要件バグを早く見つけやすくなる● 下手な要件はテストを書きにくい

● テストケースを書いておけばテストラストも以前と同様にできる

テストファーストはとっても有用でも銀の弾丸じゃないので過信は禁物!

Page 22: Code complete ch22_developper_test

開発者テストの限界● クリーンテスト(正常系テスト)になりやすい

● 未成熟な組織は正常系:異常系のテスト比率が5:1● 成熟した組織だと1:5 (25倍!)

– 正常系を減らしているのではなく、異常系の数が25倍● カバレッジに対して楽観的になりやすい

● ちゃんとカバレッジチェックツール使おう

Page 23: Code complete ch22_developper_test

22.3 テストに関するあれこれ

Page 24: Code complete ch22_developper_test

そんなにテストできねえよ!● 名前・住所・電話番号の全パターンのテスト

● 26^20 * 26^20 * 10^10 。約 10^66● 英数字だけでこれなので、日本語だとさらに多い● ノアが方舟から下りてきてから秒間1兆回テストしても、まだ1%も終わってないぐらいの量

● 当然こんなの無理なので、効率よくテストケースを選ぶ必要がある

Page 25: Code complete ch22_developper_test

構造化基礎テスト● 全てのコードを少なくとも1回通るような最小の数のテスト● コードカバレッジテストは最小でなくてもいい

● 作り方は簡単1.コードを真っ直ぐ通るパスとして1を足す2. ifなどの条件文、forやwhileなどのループ文、and や or それぞれに対し1を足す

3. case文ごとに1を足す。defaultがない場合はさらに1を足す

4.出てきた数字が、最小のテストケース

Page 26: Code complete ch22_developper_test

構造化基礎テストの実例

● 必要なテストケースは少なくとも2つ● x < 10 のケース● x >= 10 のケース

Statement1;Statement2;if ( x < 10 ) { Statement3;}Statement4;

1つ目:条件式を通らずに下まで実行

2つ目:if 文の中を通過するように実行

Page 27: Code complete ch22_developper_test

もっと複雑な例

Page 28: Code complete ch22_developper_test

もっと複雑な例

&& があるので2つカウント

Page 29: Code complete ch22_developper_test

データフローテスト● データの使い方もバグが入りやすいポイントなので注意● データの状態は以下の5つ

● Defined– 初期化されたが未使用の状態

● Used– 使用された状態

● Killed– free された状態

● Entered– あるルーチンに入った直後の状態

● Exited– あるルーチンから出るときの状態( return で値を返すとか)

Page 30: Code complete ch22_developper_test

データの状態の組み合わせ● 普通のデータフローは Defined-Used-Killed● 以下のようなケースは怪しい

Defined

Used

Killed

Entered

Exited

Defined

Used

Killed

Entered

Exited

Page 31: Code complete ch22_developper_test

データフローテストの作り方

全ての Defined-Used の組み合わせをテストする

if ( Condition1 ) { x = a;} else { x = b;}if ( Condition2 ) { y = x + 1;} else { y = x – 1;}

基礎テストで (false, false) のケースと(true, true) のケースを作成

(true, false) の条件でこのデータフローをテスト

(false, true) の条件でこのデータフローをテスト

Page 32: Code complete ch22_developper_test

もっと複雑な例でデータフローテスト

Defined-Used 1つ目

Defined-Used 2つ目

Defined-Used 3つ目

Page 33: Code complete ch22_developper_test

同値分割● あるデータにおいて、そのデータのとりうる全ての範囲を、同じエラーを生成するだろう部分集合に分割する

● 基礎テストとデータフローをきちんとやっていれば、相対的には重要ではない

● しかし以下のようなケースでは特に有効● ソースを読む時間がなく、仕様からテストするとき● データが複雑で、しかもその複雑さがプログラムロジックに反映しきれてないとき

Page 34: Code complete ch22_developper_test

同値分割の例

● m_employee[id]governmentRetirementWithheld● < MAX_GOVT_RETIREMENT

● >= MAX_GOVT_RETIREMENT

● 普通は基礎テストの時点で完了してるのでテストケースは増えない

同値分割のターゲット

Page 35: Code complete ch22_developper_test

エラーの推測

● ニュータイプベテランは直感でバグがわかる● コードインスペクションの過程で作成した「頻出エラーリスト」を元にテストケースを作ろう● ベテランの直感をテストに生かす方法になる

見える、私にもバグが見えるぞ!

Page 36: Code complete ch22_developper_test

境界値分析● 世界共通の頻出エラーといえば off-by-one

● > と >= を間違えたりとか● 境界値、境界値+1、境界値-1を全部テストする● とりうる値の最大・最小値も境界値とみなす● 値の組み合わせも考慮する

● a * b の式があるとき、abともに巨大な正数にする● あるいは巨大な負数にしたり、ともに 0 にする● 入力文字列を全て巨大にする

Page 37: Code complete ch22_developper_test

バッドデータのクラス● 以下のバッドデータのうち、今までのテストケースでカバーしていないものはテストする● 非常に小さいデータ(あるいはデータなし)● 非常に大きいデータ● 無効なデータ(型が違うとか)● 間違ったサイズのデータ● 初期化されていないデータ

Page 38: Code complete ch22_developper_test

グッドデータのクラス● 正常系データも(漏れてたら)テストする

● 一番中間の値● 正常値のうち最小・最大値

– 異常系はテストしないので境界値分析とは違う● 古いデータ

– 特に旧システムからのリプレースなどで必要

Page 39: Code complete ch22_developper_test

22.4 典型的エラー

Page 40: Code complete ch22_developper_test

エラーは偏在している

エラーの少ないクラス 394 (93%)

エラーの多いクラス 31 (7%)

エラーの少ないクラスエラーの多いクラス

IBMの調査結果より

ここを重点的に修正した→ エラー 1/10 に→ 保守コスト 45% 減→ 顧客満足度もアップ

Page 41: Code complete ch22_developper_test

エラーにおける20:80の法則

クラス数の比率 エラーの比率0

20

40

60

80

100

120

エラー多いクラスエラー少ないクラス

● 20%のクラスが80%のエラーを抱えている

● 極端な例だと、たった1000行に50個エラーが集中し、修正には全システムの開発コストの10倍がか

かったとか (1960 年代のIBM の OS/360 開発)

Page 42: Code complete ch22_developper_test

エラーの傾向

25.18

22.44

16.19

9.88

8.98

8.12

2.761.74

4.71

構造データ実装した機能コンストラクション統合機能要件テスト定義 or実行システム ,アーキテクチャ不明

※ なんか研究によって結果が随分違うらしいので参考程度に。

Page 43: Code complete ch22_developper_test

まだまだあるよ、エラーの統計

エラーの割合0

20

40

60

80

100

120

複数クラスに修正単体のみ

85%のエラーは原因のクラスのみの修正で済む

● エラーの三大原因● APに関する知識不足● 要件の変更や衝突● 人や組織の協調に関する問題● つまりコンストラクションでない

● コンストラクションエラーの原因● 95% プログラマ● 2% OS かコンパイラ● 2% 他のソフトウェア● 1% ハードウェア

どれも研究の一例であることに注意

Page 44: Code complete ch22_developper_test

まだまだまだあるよ● typo は非常に多く、その修正コストは巨額

● コンストラクションエラーの36%になることも● 損害額はひどいのになると $1.6B (1300億円)

● 設計の誤解もかなり大きい● エラーの16〜19%は設計の間違った実装

● 組織によってこの傾向はかなり変わるので、自分の組織については実際に測定するのが一番いい

Page 45: Code complete ch22_developper_test

コンストラクションが主たる原因● 1000行程度だと75%、500k行でも35%ぐらい● この辺もPJによってまちまち

Page 46: Code complete ch22_developper_test

どれだけエラーを発見できるか?● 平均的なPJだと1-25個/1000行● (少なくとも昔の)MSではリリース時に0.5個/1000行● コードリーディングと独立テストにより達成

● 「クリーンルーム開発」を使うと0.5個/1000行● スペースシャトルのソフトは0個/500,000行

● ピアレビューや統計的テストなどを活用● TSP という手法では 0.06個/1000行

Page 47: Code complete ch22_developper_test

テスト自身がエラーの原因になる● テストはソースコードと同じくらい丁寧に● ウォークスルーやインスペクションも活用● テスト計画を作ろう● テストケースを保存しよう● ユニットテストフレームワークを使おう

Page 48: Code complete ch22_developper_test

22.5 テスト支援ツール

Page 49: Code complete ch22_developper_test

Scaffolding

● 「足場」という意味● 「スタブ」「ドライバ」などを作る● xUnit 系はあまりにも有名● モックフレームワークでは Mockito が有名

● PHPならPHPUnit● python にもあるよ

Page 50: Code complete ch22_developper_test

Diff

● 説明不要● オプションの中には便利なものも色々あるので

一度は man を見よう● --side-by-side で2つのテキストを横に並べて比較できる● –幅調整は width=N。デフォルト130なので要調整● みんな知ってるよね?

Page 51: Code complete ch22_developper_test

テストデータジェネレータ● 力技だがやっぱり便利● プログラミングコンテストの練習時に、どうしても間違いが分からない問題はジェネレータ作って正解者のコードと比較したりしてた

Page 52: Code complete ch22_developper_test

カバレッジモニタ● モニタリングしないで気分だけでやってるとカバレッジは60%ぐらいらしい

● PHPUnitには標準でついてる● html出力してグラフィカルに表示できる

● python には coverage.py がある

Page 53: Code complete ch22_developper_test

データレコーダとかロギングとか● 間違ったテストは記録しましょう● 低レベルのテストでのツールはよく知らない● システムテストとかだと TestLink あたりが該当するか?

Page 54: Code complete ch22_developper_test

デバッガ● みんな大好き gdb● 1ステップづつ見ていくのはウォークスルーにもなる

● PHP だったら xdebug● firefox + vimとの連携で1ステップづつ見れる

Page 55: Code complete ch22_developper_test

システム乱雑化● メモリを0にしたりぐちゃぐちゃにしたり● webの世界でここまでやるとこあるんだろうか● OS とか組み込みの世界では gdb から値書き換えたりしてテストしたりするが、ここまでやるのか不明

Page 56: Code complete ch22_developper_test

エラーデータベース● TestLink だと統計機能がある● redmine や trac もこれに該当するかもしれない

Page 57: Code complete ch22_developper_test

22.6 テストを改善する

Page 58: Code complete ch22_developper_test

テスト改善の手法● テスト計画を作ろう● 再テスト(リグレッションテスト)

● 高品質なプロダクトには不可欠● テストを自動化しよう

● リグレッションテストは自動化必須

Page 59: Code complete ch22_developper_test

22.7 テスト記録を保存する

Page 60: Code complete ch22_developper_test

保存すべき情報● 日付、報告者、ビルドナンバー、修正日時● 問題の詳細● 関連するエラー● エラーの重要度● エラーの種類● 発見/修正にかかった時間

Page 61: Code complete ch22_developper_test

自分のテスト記録も保存しよう● 自分のクセがわかる● そこからチェックリストも作れる

Page 62: Code complete ch22_developper_test

まとめ

Page 63: Code complete ch22_developper_test

まとめ● 開発者テスト超重要● でも高品質なソフトにはレビューなどの手法を組み合わせることが必須

● テストファーストの方が開発時間短縮できる● テストケースの多くは形式的手法で簡単に作れる● エラーは偏在するのでそこだけ再設計しよう● リグレッションテストはテスト自動化で実行しよう

Page 64: Code complete ch22_developper_test

おまけ:最近の組み込み開発事情● 某社の組み込み開発事情(C言語)

● ユニットテストで網羅テストやっても費用対効果が上がらないのでカバレッジだけ確保

● 商用の静的解析ツール「coverity」を使う● 誤検知が少ないらしい

● 「組み込みの世界においては、起こる可能性のあるものは全て起きる。だからそういうものは全て潰す」

● 出てくるエラーは全て潰す● エラーを取捨選択するコストも馬鹿にならないため

Page 65: Code complete ch22_developper_test

参考文献

Page 66: Code complete ch22_developper_test

1. “Code Complete, Second Edition”, Steve McConnell, Microsoft Press, 2004

Page 67: Code complete ch22_developper_test

Thank you !