ATECFESテストの活用による開発効率化

62
第一回Androidテスト祭り基調講演 「より効率的に開発するために ~スマートフォン時代のソフトウェアテスト・アプローチ」後篇 テストの活用による 開発効率化 井芹 洋輝 2011/8/6 @日本ノーベル

description

 

Transcript of ATECFESテストの活用による開発効率化

Page 1: ATECFESテストの活用による開発効率化

第一回Androidテスト祭り基調講演「より効率的に開発するために~スマートフォン時代のソフトウェアテスト・アプローチ」後篇

テストの活用による開発効率化

井芹 洋輝2011/8/6 @日本ノーベル

Page 2: ATECFESテストの活用による開発効率化

開発工程内でテストを活用し開発を効率化する

開発者テスト

テストのサポート

テーマ

Page 3: ATECFESテストの活用による開発効率化

デバッギングテスト

Page 4: ATECFESテストの活用による開発効率化

class MacroWord

Page 5: ATECFESテストの活用による開発効率化

TEST_F(TestMacroWord, test_macroData_macroWord_bug21){

MacroData macroData;macroData.push_back("AUTO_DEBUG_1");macroData.push_back("AUTO_DEBUG_2");macroData.push_back("AUTO_DEBUG_2");macroData.push_back("AUTO_DEBUG_2");macroData.push_back(“BB_H_");

MacroWord macroWord(macroData);

EXPECT_EQ("AUTO_DEBUG_1", macroWord.data_[0].macroName_);EXPECT_EQ(1, analyzer.data_[0].number);

EXPECT_EQ("AUTO_DEBUG_2", macroWord.data_[1].macroName_)EXPECT_EQ(3, analyzer.data_[1].number);

EXPECT_EQ(“BB_H_", macroWord.data_[2].macroName_);EXPECT_EQ(1, analyzer.data_[2].number);

}

class MacroWord

1. 自動テスト上でバグを再現する

Page 6: ATECFESテストの活用による開発効率化

TEST_F(TestMacroWord, test_macroData_macroWord__bug21){

MacroData macroData;

macroData.push_back("AUTO_DEBUG_2");macroData.push_back("AUTO_DEBUG_2");macroData.push_back("AUTO_DEBUG_2");

MacroWordProxy::wordCount(macroData);

EXPECT_EQ(3, MacroWordProxy::getSize(0));}

class MacroWord

1. 自動テスト上でバグを再現する

2. テストでバグを絞込み特定する

Page 7: ATECFESテストの活用による開発効率化

TEST_F(TestMacroWord, test_macroData_macroWord__bug21){

MacroData macroData;

macroData.push_back("AUTO_DEBUG_2");macroData.push_back("AUTO_DEBUG_2");macroData.push_back("AUTO_DEBUG_2");

MacroWordProxy::wordCount(macroData);

EXPECT_EQ(3, MacroWordProxy::getSize(0));}

class MacroWord

1. テスト上でバグを再現する

2. テストでバグを絞込み特定する

3. 修正後テストがパスすることを確認。テストはCIへ

バグを再現 バグを特定 バグ修正のチェック

Page 8: ATECFESテストの活用による開発効率化

学習テスト

Page 9: ATECFESテストの活用による開発効率化

boost::xpressive

TEST(regex, test_regex_fileseek){

namespace xp = boost::xpressive;string target; xp::smatch match;xp::sregex rex = xp::sregex::compile ("(¥¥.c|¥¥.h)$");

target = "test";EXPECT_EQ(false, xp::regex_search(target, match, rex));

target = "test.c";EXPECT_EQ(true, xp::regex_search(target, match, rex));

target = "test.h";EXPECT_EQ(true, xp::regex_search(target, match, rex));

target = "./../source/_svn/text-base/main.c.svn-base";EXPECT_EQ(false, xp::regex_search(target, match, rex));

target = "test.cpp";EXPECT_EQ(false, xp::regex_search(target, match, rex));

}動作チェック 用例ドキュメントとして活用

テストで動作を確認する。不安がなくなるまで試す

Page 10: ATECFESテストの活用による開発効率化

コードの新規設計

コードの追加・変更

記述改善

コードの保守

コードの解析

デバッグ

バグの早期検出

ユニットレベルでのバグ検出

進捗管理

TDD

仕様化テスト

学習テスト

探索的テスト

手法は続く ..

BDD

Cover & Modify

リファクタリングでのテスト デバッギン

グテスト

ATDD ストーリ駆動

テストファーストによる設計

Test as Documentation

Page 11: ATECFESテストの活用による開発効率化

主にアジャイル開発関連のテスト&探索的テストの文献で蓄積

Page 12: ATECFESテストの活用による開発効率化

開発効率化のためにテストを活用する

•バグの混入防止

•デバッグの効率化

•テスト容易性の確保

•バグの早期検出

•バグのコンポーネントレベルでの検出

テスト工数を削減する

•コードの解析補助

•設計補助

•コードのふるまいの保護

開発工数を削減する

Page 13: ATECFESテストの活用による開発効率化

開発でのテストの活用は、軽快な開発での品質確保を強力にサポートする

開発効率化のためにテストを活用する

Page 14: ATECFESテストの活用による開発効率化

テストによる開発効率化をどう実現するか

Page 15: ATECFESテストの活用による開発効率化

テスト工数の重複

製品/テスト変更時のテストの保守工数増加

課題

製品

テスト

テスト

テスト

仕様・構造で依存

全体整合を維持

Page 16: ATECFESテストの活用による開発効率化

特定工程で構築するほかに

開発中継続的に開発に合わせながらテストを構築する

テスト対象をFixしてテストを作りこむほかに

テスト対象の変化を許容しテストで変更をサポートする

担当ばらばらに作るのはでなく

開発プロセス全体で全体最適が得られるようにテストを育てる

テスト・アプローチの発想の転換が要求される

Page 17: ATECFESテストの活用による開発効率化

テストによる開発効率化をどのように推進するか

開発と一体化した

テストプロセス

テストを支える

テストインフラの構築

堅牢なテストの構築

Page 18: ATECFESテストの活用による開発効率化

開発と一体化した

テストプロセス

テストを支える

テストインフラの構築

堅牢なテストの構築

Page 19: ATECFESテストの活用による開発効率化

テストの保守・運用を柔軟に支える環境は、堅牢なテストの構築に丌可欠

テストインフラ

Page 20: ATECFESテストの活用による開発効率化

テストの活用をサポートするテストインフラを構築する

テストをいつでも/継続的に実施できるように

堅牢なテストを保守できるように

テスト設計をよりやりやすくするように

Page 21: ATECFESテストの活用による開発効率化

テストの活用をサポートするテストインフラを構築する

テスト側・テストの実行環境・テストの保守環境・テスト環境の構成管理…

プロダクト側・テスト向けの機能・IF・テスト容易性を支える設計…

Page 22: ATECFESテストの活用による開発効率化

テストインフラ:テスト側モデル例

●CI●各種テストサーバ

自動テスト環境ユニットテストUIベーステストシミュレータ実機評価

●テスト指標の評価カバレッジ評価結果管理テスト実装のメトリクス

●変更管理 バージョン管理サーバ

開発環境

●テスト環境 ユニットテストUIベースシミュレーション

●変更管理 DVCS

Page 23: ATECFESテストの活用による開発効率化

Jenkins CI×Monkey Runner/Junit/Robotium等

CIのテストの効果

継続的な回帰テストの実施

テストのビルドチェック

テスト環境の制約の回避

テストの品質指標の継続評価

テストインフラへの要求

CIへの自動テストの組み込み

Page 24: ATECFESテストの活用による開発効率化

テストのビルド・インテグレーションも評価する

1次元と2次元で評価する

コードカバレッジ

「60%」 ←極端に低くないか?テストは妥当か?

CIによるテストの保守

←テストを壊すコミットをしていないか?能力は妥当か?

Page 25: ATECFESテストの活用による開発効率化

CIはテストの実行だけでなくテストの保守・管理を支える

テストインフラの要

テストインフラへの要求

自動テストのCIへの組み込み

Page 26: ATECFESテストの活用による開発効率化

テスト条件に応じてテスト実行環境を分割サーバ側/開発側で多重化

重いテストはサーバ側へ

制約ある環境はサーバ側で自動化

テストインフラへの要求

テスト環境の分割・多重化

サーバ

開発環境

Page 27: ATECFESテストの活用による開発効率化

開発者テストの選択肢を広げる

テスト環境の制約回避

Slow Tests問題の改善 コミット時テスト:コミット間隔内で

TDD: 0.1秒でもかかれば遅すぎる

テストインフラへの要求

テスト環境の分割・多重化

サーバ

開発環境

Page 28: ATECFESテストの活用による開発効率化

分散型バージョン管理システム

Git/Mercurial/Bazaar

テストの分割・多重化に適した構成管理環境を構築

テストインフラへの要求

テストの分割・多重化への対応

開発環境

リポジトリ

共有テスト環境

コミット後でしかテスト結果が分からないテストに失敗するコードを変更管理リスク

開発環境

共有テスト環境

リポジトリ

②③テストが終わるまでコミットできない変更情報が損なわれるリスク

分散型でない場合

Page 29: ATECFESテストの活用による開発効率化

分散型バージョン管理システム

Git/Mercurial/Bazaar

テストの分割・多重化に適した構成管理環境を構築

テストインフラへの要求

テストの分割・多重化への対応

開発環境

共有リポジトリ

共有テスト環境

プライベートリポジトリ

Page 30: ATECFESテストの活用による開発効率化

テストを支える機能やインターフェース

適切なアーキテクチャ・構造(前半解説)

接合部

制御点

観測点

防御的機構

テストインフラ:プロダクト側

Page 31: ATECFESテストの活用による開発効率化

テスト時に製品用コード/テスト用コードの切替を実現する構造/IF

Dependency Injection/Dependency Lookup

DIコンテナ, Constructor Injection,…

差分プログラミング/リフレクション

プリプロセッサ/Class path設定

接合部(Seam)

テスト対象

テストコード

製品用コード

テスト用コード

Seam

Page 32: ATECFESテストの活用による開発効率化

テスト対象を間接的に制御するインターフェース

Mock/Stab/Fake

バックドアインターフェース

制御点(Control Point)

テスト対象

テストコード

依存コンポーネント

Page 33: ATECFESテストの活用による開発効率化

テスト対象の出力(直接/間接)を取得する

Mock/Spy

ロギング

テスト用インターフェース

観測点(Observation Point)

テスト対象

テストコード

依存コンポーネント

Page 34: ATECFESテストの活用による開発効率化

プロダクトに組み込まれた自己検証機構

防御的プログラミング、契約による設計

Assertion

エラー処理の拡充

ロギング処理・ログチェック処理の拡充

防御的機構

Page 35: ATECFESテストの活用による開発効率化
Page 36: ATECFESテストの活用による開発効率化

接合部/制御点

テスタビリティを落とすコンポーネントに配備

テスト丌能なコードが発生すれば組み込み

観察点/防御的機構

継続的に組み込み

デバッグやテストに支障がでれば組み込み

プロダクト側でのテストインフラの構築

Page 37: ATECFESテストの活用による開発効率化

慣習的に満遍なく組み込む

テストからフィードバックを得て継続的に作りこむ

プロダクト側でのテストインフラの構築

Page 38: ATECFESテストの活用による開発効率化

開発と一体化した

テストプロセス

テストを支える

テストインフラの構築

堅牢なテストの構築

Page 39: ATECFESテストの活用による開発効率化

トップダウン/ボトムアップ両面でテストの堅牢性を支える

上流工程の実践

堅牢なテスト設計構造の確保

テスト対象の分析と整理

実装工程の工夫

堅牢なテスト実装構造の確保

Page 40: ATECFESテストの活用による開発効率化

堅牢なテストを生み出すテストプロセスを構築する

トップダウン/ボトムアップ両面でテストの堅牢性を支える

Page 41: ATECFESテストの活用による開発効率化

テストプロセス

テスト計画

•以下を検討

•テスト環境の明確化

•テストフェーズの設定

•アプローチの設定

•スケジュール

•プロジェクトリスク分析

テスト分析

•テスト対象の分析

•テスト条件の分析・整理

•テスト観点の抽出

•テストタイプの抽出

テスト設計

•採用するテスト観点の構造化

•具体的なテストの種類の定義

•フェーズ

•テストタイプ

•環境

•テストケースの抽出

テスト実装

•具体値の設定

•テストコード/スクリプト/手順書等での実装

Page 42: ATECFESテストの活用による開発効率化
Page 43: ATECFESテストの活用による開発効率化

テスト上流工程の実践

テスト計画 テスト分析 テスト設計 テスト実装

Page 44: ATECFESテストの活用による開発効率化

テストの上流設計成果物は変更をある程度許容し、変更をサポートする

テスト環境の定義、テスト対象の分析、テスト条件の割り出し、テスト観点の定義と整理、…

テストの上流工程の実践

Page 45: ATECFESテストの活用による開発効率化

Ex)Test Doubleの運用 計画

テスト環境の明確化

対象の実装見込み

対象コンポーネントの分析

テスト対象の分析 テスト容易性に劣るコンポーネントの抽出

Seamの実装状況

観測点/制御点の分析

テスト条件の抽出

テスト環境の抽出

実行速度に対する要求分析

観測点/制御点の分析

観点の整理

Test Double使用/未使用時のテスト切り分け

テストの上流工程の実践

Page 46: ATECFESテストの活用による開発効率化

テスト計画 テスト分析 テスト設計 テスト実装

テスト設計でのアプローチ

Page 47: ATECFESテストの活用による開発効率化

課題

製品

テスト

テスト

テスト

仕様・構造で依存

全体整合を維持

Page 48: ATECFESテストの活用による開発効率化

ビッグバンでテストを構築するのでなく、必要な時に必要なテストを確保する

テストでなく、テストを支えるテスト容易性・テストインフラを継続的に満遍なく行き渡らせる

テスト設計では視点の転換が要求される

Page 49: ATECFESテストの活用による開発効率化

テストで実行できる状態を維持する

コードカバレッジ×CIの自動テスト

観測点×シミュレーションによる自動テスト

とりあえず実行できている対象なら、後からテストの追加・変更も容易になる

テストを支えるテスト容易性・テストインフラの確保

Page 50: ATECFESテストの活用による開発効率化
Page 51: ATECFESテストの活用による開発効率化

適切なインプット・手法にのっとって、整合のとれたテスト設計を行う

適切な設計に基づいていない雑多なテストは保守コストを肥大化させる

コンパクトかつ網羅的なテスト設計を行う

Page 52: ATECFESテストの活用による開発効率化
Page 53: ATECFESテストの活用による開発効率化

テスト実装での工夫

テスト計画 テスト分析 テスト設計 テスト実装

Page 54: ATECFESテストの活用による開発効率化

堅牢なテストの確保にはテスト実装の工夫が丌可欠テストコードやテストスクリプト

テスト実装での工夫

Page 55: ATECFESテストの活用による開発効率化

Ex)

可読性の改善

高リスクコードの分離・ラッピング

重複コードの共通化

テスト実装での工夫

@TestPublic void test_1(){

Int a;…

}

@TestPublic void test_無効なIDを指定すると例外を返す(){

Int dummyID;…

}

@TestPublic void test_hoge(){

…コピペコード……}

@TestPublic void test_fuga(){

…コピペコード……}

Private void 共通メソッド(){

…コピペコード…}

@TestPublic void test_hoge(){共通メソッド()…

}

@TestPublic void test_fuga(){共通メソッド()…

}

Page 56: ATECFESテストの活用による開発効率化

テスト実装の工夫

Page 57: ATECFESテストの活用による開発効率化

開発と一体化した

テストプロセス

テストを支える

テストインフラの構築

堅牢なテストの構築

Page 58: ATECFESテストの活用による開発効率化

テストによる開発効率化を実現するテストプロセス

開発成果物の一部としてテストを構築する

テストのフィードバックを元に製品の作りこみを行うフィードバックサイクルを維持する

Page 59: ATECFESテストの活用による開発効率化

開発工程 テスト工程

Page 60: ATECFESテストの活用による開発効率化

テストプロセスの実施

開発計画テスト計画

要求分析 設計・実装・作りこみ

テストインフラ

テスト分析

開発工程内テストの設計・実装・実施・作りこみ

テストインフラ

システムテストの設計

相互フィードバック相互フィードバック

製品側開発プロセス

テストプロセス

Page 61: ATECFESテストの活用による開発効率化

まとめ

Page 62: ATECFESテストの活用による開発効率化

テストの活用は、軽快な開発での品質確保を強力にサポートします

効果をより増幅するために プロダクトの工夫でテストをささえましょう 堅牢なテストを支えるテストインフラを構築しましょう 開発成果物の一部としてテストを取り込みましょう

開発とテストの設計・実装は並行させ、相互フィードバックを繰り返しましょう

まとめ