Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

 テストを活用して開発を効率化する テーマ

Slide 3

Slide 3 text

 近年、開発とテストが一体化し、テストによって開 発の生産性を高め、開発を加速させるアプロー チやプラクティスが普及している  例:TDD、BDD、CIに組み込まれた自動テスト、リファク タリング  プログラマは、プログラミングの一要素として、呼 吸するようにテストを活用するスタイルが広がっ ている テストと開発の関係

Slide 4

Slide 4 text

デバッギングテスト

Slide 5

Slide 5 text

class MacroWord

Slide 6

Slide 6 text

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. 自動テスト上でバグを再現する

Slide 7

Slide 7 text

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. テストでバグを絞込み特定する

Slide 8

Slide 8 text

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へ バグを再現 バグを特定 バグ修正のチェック

Slide 9

Slide 9 text

学習テスト

Slide 10

Slide 10 text

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)); } 動作チェック 用例ドキュメントとして活用 テストで動作を確認する。不安がなくなるまで試す

Slide 11

Slide 11 text

 コードの追加  リファクタリング  コードの保守  コードの解析  デバッグ  バグの早期検出  ユニットレベルでのバグ検出  進捗管理  ・・・ TDD 仕様化 テスト 学習テスト 探索的 テスト 活用は加速度的に広がる BDD Cover & Modify リファクタリング でのテスト デバッギン グテスト ATDD ストーリ駆動 テストファーストによる設計 Test as Documentation

Slide 12

Slide 12 text

テストによって開発を加速させ生産性を高めるアプローチは 近年アジャイルのコミュニティで蓄積

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

 設計やプログラミングを先導する  バグを予防する  バグを即時検出する  信頼、安心を確保しプログラマを前進させる  保守性、テスト容易性を向上させる 開発を加速させるテスト

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

 特定工程で構築するほかに 開発中継続的に開発に合わせながらテストを構築する  テスト対象をFixしてテストを作りこむほかに テスト対象の変化を許容しテストで変更をサポートする  担当ばらばらに作るのはでなく 開発プロセス全体で全体最適が得られるようにテストを 育てる 加速力のあるテストの実現に は発想の転換が要求される

Slide 17

Slide 17 text

テストによる開発効率化を どのように推進するか 開発と一体化した テストプロセス テストを支える テストインフラ の構築 堅牢なテスト の構築 テスト容易性 の確保

Slide 18

Slide 18 text

開発と一体化した テストプロセス テストを支える テストインフラ の構築 堅牢なテスト の構築 テスト容易性 の確保

Slide 19

Slide 19 text

テストの保守・運用を柔軟に支える環 境は、堅牢なテストの構築に不可欠 テストインフラ

Slide 20

Slide 20 text

テストの活用をサポートする テストインフラを構築する  テストをいつでも/継続的に実施できるように  堅牢なテストを保守できるように  テスト設計をよりやりやすくするように

Slide 21

Slide 21 text

テストの活用をサポートする テストインフラを構築する テスト側 ・テストの実行環境 ・テストの保守環境 ・テスト環境の構成管理 … プロダクト側 ・テスト向けの機能・IF ・テスト容易性を支える設計 …

Slide 22

Slide 22 text

 CI  自動テストの実行、管理、保守の要  今や導入当たり前の最低限の開発インフラ  クロス環境対応の自動テスト環境  ユニットテスト/UIベーステスト/エミュレータテスト/実機テスト  Git/DVCS  柔軟なブランチ戦略によるテストのサポート  各種運用サポート  カバレッジ監視、実行監視、テスト実装の各種メトリクス テストインフラ・テスト側

Slide 23

Slide 23 text

 Jenkins CI×Monkey Runner/Junit/Robotium等  CIのテストの効果  継続的なテストの実施  テストのビルド・実行チェック  サーバサイドのテスト環境の活用効率確保  テストの品質指標の継続評価 CIへの自動テストの組み込み

Slide 24

Slide 24 text

 テスト結果評価×時系列推移で評価  例:不安定なテストはないか エミュレータ、実機で多い。再現性の低いバグやテ ストのバグを見つけ出す  例:カバレッジやテスト結果に変動はないか チームの不調、繁忙期で必要なプラクティスが適切 に運用されなくなった傾向を読み取る CIによるテスト管理の 二次元化

Slide 25

Slide 25 text

 CIによりサーバサイドのテスト 環境管理を高度化  テスト条件に応じてテスト実 行環境を選択・分割  重いテストはサーバ側へ  早くフィードバックが欲しいテストは多数の環境 を使って並列化 テスト環境の分割・多重化 サーバ 開発環境

Slide 26

Slide 26 text

 スマフォ開発で直面しが ちなSlow Test問題を改 善する  TDDではテスト実行に1秒 でもかかれば遅すぎる  重いテストはサーバ任せに テスト環境の分割・多重化 サーバ 開発環境

Slide 27

Slide 27 text

 分散型バージョン管理システム  Git/Mercurial/Bazaar  テストの分割・多重化に適したブランチ環境・構成管理環境を 提供  より簡素なブランチで、柔軟なテストゲートを実現する テストの分割・多重化への対応

Slide 28

Slide 28 text

テストによる開発効率化を どのように推進するか 開発と一体化した テストプロセス テストを支える テストインフラ の構築 堅牢なテスト の構築 テスト容易性 の確保

Slide 29

Slide 29 text

 テスト容易性はテストに依存する活動の生産性 を大きく左右する  開発を加速させるテストの実現には、テストサイド の改善だけでなく、プロダクトサイドのテスト容易 性の改善が必要 開発加速力のあるテスト を支えるテスト容易性

Slide 30

Slide 30 text

 同じ手間でより有効なテストを作りやすくする  同じテストをより少ない手間で作成・保守できる 開発加速力のあるテスト を支えるテスト容易性

Slide 31

Slide 31 text

 高い凝集性、低い結合性の実現  テストにとって十分な制御点、観測点の確保  テストの障害を排除したり、テスト容易性を注入 可能にする接合部の配備  テストすべきテスト条件を削減する機構 テスト容易性の実装

Slide 32

Slide 32 text

 テスト対象を間接的に制御するインターフェース  Mock/Stab/Fake  バックドアインターフェース  テストツールに合わせたインターフェース 制御点(Control Point) テスト 対象 テスト コード 依存 コンポーネント

Slide 33

Slide 33 text

 テスト対象の出力(直接/間接)を取得する  Mock/Spy  ログ  テスト用インターフェース 観測点(Observation Point) テスト 対象 テスト コード 依存 コンポーネント

Slide 34

Slide 34 text

 テスト時に製品用コード/テスト用コードの切替を実現す る構造/IF  Dependency Injection/Dependency Lookup  DIコンテナ, Constructor Injection,…  プリプロセッサ/Class path設定  テストの障害を排除できる/テスト容易性を注入できる 接合部(Seam) テスト 対象 テスト コード 製品用 コード テスト用 コード Seam

Slide 35

Slide 35 text

 適切なインターフェース設計  型による条件の削減  適切な並行処理設計  データ共有部分の最小化・適切なロック、排他処理や保護  副作用の削減  メモリ保護や処理系依存・未定義の回避  防御的プログラミング、契約による設計/契約プログラミング  サニティチェック機能 テストすべきテスト条件を 削減する機構

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

トップダウン: アーキテクチャレベルから組み込む 反復開発など中長期のフィードバックで作 りこむ ボトムアップ: プログラミング中に慣習的に組み込む テスト容易性はトップダウン/ ボトムアップ両面で確保

Slide 38

Slide 38 text

開発と一体化した テストプロセス テストを支える テストインフラ の構築 堅牢なテスト の構築 テスト容易性 の確保

Slide 39

Slide 39 text

テストの堅牢性は開発・テスト のスピードに直結する  堅牢なテスト:  変更に強いテスト、保守性の高いテスト  堅牢性に劣るテストは、テストの保守のコスト・時 間・工数を悪化させ、開発のスピードを落とす

Slide 40

Slide 40 text

 テストコードの設計・実装の保守性・堅牢性を高 める  テスト設計の保守性・堅牢性を高める テストの堅牢性を確保する アプローチ

Slide 41

Slide 41 text

 可読性やDRYをはじめとした保守性の改善  接合部の確保  高リスクコードの分離・ラッピング テストコードの実装の保守性・ 堅牢性を高める @Test Public void test_1() { Int a; … } @Test Public void test_無効なIDを 指定すると例外を返す() { Int dummyID; … } @Test Public void test_hoge() { …コピペコード… … } @Test Public void test_fuga() { …コピペコード… … } Private void 共通メソッド() { …コピペコード… } @Test Public void test_hoge() { 共通メソッド() … } @Test Public void test_fuga() { 共通メソッド() … }

Slide 42

Slide 42 text

テスト実装の工夫

Slide 43

Slide 43 text

 高い凝集性、低い結合性を実現する  FIRSTの原則 テストスイートは独立して入れ替えや繰り返し可能  再現性、移植性をはじめとしたテスト環境の環境 品質を高める テストコードの設計の保守性・ 堅牢性を高める

Slide 44

Slide 44 text

 堅牢性を維持しやすい設計・実装を実現するほ か、運用・保守のサポートも重要  テスト自動化とCIへの組み込みを行い、継続的 にテストをグリーンに保つアプローチが有効 テストの堅牢性を維持する

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

 価値あるテストを作る。無駄なテストは作らない  テストの強みを活かし、テストの弱み・制約を回 避するテストを設計する テスト設計の保守性・堅牢性 を高める

Slide 47

Slide 47 text

 テスト設計の品質確保には、適切なテスト分析・テスト 設計が必要  テスト分析  対象の調査・分析  テストの要求・制約の分析  テスト観点、テスト条件の識別と整理  テスト設計  テストのタイプ/サイクルの設計  テストスイート・テストケースの設計 テスト設計の保守性・堅牢性 を高める

Slide 48

Slide 48 text

 Ex)Test Doubleの運用  テスト対象の分析  対象の調査  テスト環境の明確化  テスト容易性に劣るコンポーネントの抽出  Seamの実装状況  観測点/制御点の分析  テスト条件の抽出  テスト環境の抽出  トレードオフの品質の分析とすり合わせ  観測点/制御点の分析  観点の整理  Test Double使用/未使用時のテスト切り分け テスト分析・テスト設計の工夫

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

適切なテスト分析・設計アプローチにのっと って、整合のとれたテスト設計を行う 適切なテスト設計に基づいていない雑多な テストは、テストの堅牢性を損なう コンパクトかつ網羅的な テスト設計を行って堅牢性を確保する

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

開発と一体化した テストプロセス テストを支える テストインフラ の構築 堅牢なテスト の構築 テスト容易性 の確保

Slide 53

Slide 53 text

テストによる開発効率化 を実現するテストプロセス 開発を加速させるテストアプローチを、開 発プロセスに組み込む  開発活動とテスト活動を一体化させる

Slide 54

Slide 54 text

開発工程 テスト工程

Slide 55

Slide 55 text

テストプロセスの実施 開発計画 テスト計画 要求分析 設計・実装・作りこみ テスト インフラ テスト分析 開発工程内テストの 設計・実装・実施・作りこみ テスト インフラ システムテストの設計 相互フィードバック 相互フィードバック 製品側 開発プロセス テスト プロセス

Slide 56

Slide 56 text

まとめ

Slide 57

Slide 57 text

 テストの活用で開発を加速させ、開発生産性を 高めることができる  加速力の高いテストを実現するために: まとめ 開発と一体化した テストプロセス テストを支える テストインフラ の構築 堅牢なテスト の構築 テスト容易性 の確保