ソフトウェアテスト 入門
2014年4月10日 柏原秀蔵
自己紹介• 柏原秀蔵(@suma90h)
• 経歴
• 2011年秋 PFI入社
• 2012年4月~ Jubatus参加
• お仕事
• Jubatus (OSS) とか
前回の発表• 2012年5月
• 「マルウェアとアンチウイルスから学ぶデバッガ開発技巧」
• 2012年12月
• 「LLVM/Clangのはなし」
• 2013年9月
• 「Linux開発環境の自動構築」
• 流行のPackerとRHEL系のキックスタートの紹介
最近の活動
• ベイクドチーズケーキ作り
• オーブンレンジを導入し、休日はお菓子作りに挑戦している
本日の内容• ソフトウェアテストとは何か
• 新入社員・テスト初心者向け(単体テスト経験者)
• PFIに向いてそうなテストスタイル
• テストの基礎用語
• 実践ソフトウェアテスト
注意• 本日の目的
• PFIにおけるテスト活動の支援・学習
• 扱わない内容
• ウォーターフォール(伝統的)テスト・テスト計画作成・文書化
• テスト技法の網羅
• テストツールの使い方
• 形式的検証
• テスト技法を学びたい人は、テスト入門書(最終ページ)を読みましょう!
何のためのテスト?• 何のためにテストをしているのか?
!
• エラー(欠陥=バグ)を見つけるため
• コードの品質を保つため
• ソフトウェア製品の品質を保つため
• 品質の高い製品を出荷するためPhoto by alisdair
https://www.flickr.com/photos/alisdair/135306281/
ソフトウェアテストとは年 定義
1979 テストとは、エラーを見つけるつもりで、プログラムまたはシステムを実行する過程である。
1983テストとは、プログラムのシステムの属性の評価をすることを目的とするあらゆる活動である。テストはソフトウェアの品質
を測定することである。
2002テストとは、対象とするソフトウェアの品質を測定して改善するための、テストウェアエンジニアリングし、使用し、かつ保守しながら、同時並行的に進めるライフサイクルプロセスである。
『体系的ソフトウェアテスト入門(日経BP)』p2 表1-1より引用
テストとは• ソフトウェアテストの目的とは
• エラー(バグ, 欠陥)を見つけ出す
• ソフトウェアの属性・品質を測定する
• ソフトウェアの品質を改善する
• これらをの目的を包括した行動のライフサイクルをテストと呼ぶ
テスト用語(一部)• テストの種類:機能テスト (Functional testing) / 非機能テスト (Non-functional testing)
• テスト段階
• 単体テスト(Unit testing)
• 統合テスト or 結合テスト (Integration testing, Interface testing)
• システムテスト (System testing)
• 受け入れテスト (Acceptance testing)
• テストアプローチ・技法
• ブラックボックス/ホワイトボックステスト
• 検証と妥当性確認(Verification & Validation)
• 検証:仕様を満たしているかの確認
• 妥当性検証:満たした仕様が意図した通りに動作するかの確認
機能テストと非機能テスト機能テスト 非機能テスト(-ity)
ソフトウェアの機能や 振る舞いのチェックを行う
機能以外にも性能やソフトウェアの特性を検証する
Availability
Security
Usability
Performance
...
Normal
Error
テストの関係(概略)
伝統的なソフトウェアテスト• ウォーターフォール型
• テスト計画・アプローチ・仕様書の作成
• 文書化はテストの目的、リスク評価やテスト実行者の役割を明確化するのに役立つ
• 文書のテンプレートはIEEEで標準化されていする
!
• VモデルとV&V(右図)
実践テスト• assertionとビヘビア駆動開発
• テストコードの例
• 良いテストとは?
• 単体テストの基本
• Googleによるテストの定義
• どうやってテストを育てるか?
一般的なテスト(ツール)• assertion (アサーションチェック)
• プログラムが成立する必要のある条件をチェックするテスト
• JUnit(Java), Google gtest(C++), minitest(Ruby)
• ビヘビア駆動開発(Behavior Driven Development: BDD)
• プログラムが仕様に基づく振る舞いをするかチェックする
• RSpec(Ruby), Jasmine(JavaScript)
gtest サンプル
!
TEST(filesystem, is_writable) { std::string path = "tmp_test_directory"; mkdir(path.c_str(), S_IWUSR); EXPECT_EQ(true, jubatus::server::common::is_writable(path.c_str())); rmdir(path.c_str()); }
EXPECT_EQ がassetion Jubatus, jubatus/server/common/filesystem_test.cpp より
assertion• 特徴
• assertといった専用メソッドを呼び出し、値をチェックする
• 注意事項
• 1つのテストケースに1つのassertion記述が推奨
• assertionを複数書いてしまうと
• 1つのテスト(シナリオ)なのに失敗理由が複数発生するおそれ
• 失敗したときどこのエラーか範囲を狭めにくい
• とはいえ、複数条件や前提条件の確認で複数書く場合もあるし...
RSpec 例
http://rspec.info の例より RSpecではshouldを書く
# bowling_spec.rb!require 'bowling'!!describe Bowling, "#score" do! it "returns 0 for all gutter game" do! bowling = Bowling.new! 20.times { bowling.hit(0) }! bowling.score.should eq(0)! end!end
良い、質の高いテストとは• 「質の高いテストの特徴」とは(『基本から学ぶソフトウェアテスト』 p122より)
• 不具合を検出できる可能性が高いこと
• 重複がないこと
• 最善であること
• 単純すぎず,複雑すぎないこと
• 検出の方法が明示してあること
• 現実問題としてトレードオフである
• 単体テストと統合テストで重複することはある
• 最善とはバグを効率よく見つけやすいテストらしいが、その適切な加減も難しい
• 複雑すぎず・・・複雑な条件のコードはテストも難しくなりがち。元のコードもテストのしやすさを考えるべきだと私は思う
• エラー原因の検出は大事。見つけられないものは修正できない
良いテストって何?• 目的:テストからバグの修正・ソフトウェアの品質向上に結びつけること
• 製品と同等の品質があると嬉しい 具体的には? 網羅性とか?
• 個人的に覚えて欲しいポイントをあげる
再現性 繰り返し実行しても同一の結果が得られる
独立性 他のモジュールに依存していなければ、テストしたコードの範囲を限定できる
保守性 テスト自体誤りを防ぐ コードとテストの修正に無理なく対応できる
テスト実行環境からの独立
実行環境を永続的に変更する実行をしない 実行環境の状態に依存せずテスト実行できる
単体テスト記述の基本• 独立性
• 他のモジュールに依存しない
• テストケース実行で他のテストケースに依存しない
• 利点
• モジュール単体のテストに集中できる
• 失敗原因の特定・再現を容易にさせる
• 独立性・再現性は大事!
Googleのテストサイズの定義一般的な呼び方
実行時間 Goal/Limit 対象範囲 自動化
small unit test 100 ms/ 1 minute
狭い 限定的 almost
medium integration test
1 sec/ 5 minutes
広く モジュールをまたがる
automated or manual
large system testquickly as possible/ 15 minutes
ソフトウェア 全体 -
Small tests lead to code quality. Medium and large tests lead to product quality. (How Google Tests Software, Chapter2 より)
どうやってテストを育てるか• アジャイルプロジェクトの一部として回す
• 機能の増減でテストも修正
• テストコードのリファクタリングもたまに実施する
• ユーザ(お客様)の価値は生まないが、開発における生産性を助ける
• 現実的な運用として
• 異なる抽象度(単体テスト・統合テスト)のテストを同じファイルに書かない・書かせない・混ぜて管理しない
• テストを実行するコマンドも別けるべき
分散システムのテストの困難性• 環境の前提条件が大きい
• テストコードそのもの記述範囲外
• テストに関するデプロイをスクリプト化しづらい
• 今だとPuppet, Chefなどで希望が見える
• 分散システムのテストの特徴
• 別のテストに影響を与えるテストがある
• 例:設定項目の変更・(分散システムに限らず)状態が遷移するテスト
• 複数のプログラムをまたいだ状態に依存するテストの存在(※)
(※)Immutable Infrastructureはアプリケーションのアーキテクチャを変えていく、伊藤直也氏(前編) - Publickey http://www.publickey1.jp/blog/14/immutable_infrastructure_1.html
実践アジャイルテスト• アジャイルテストとは
• メンバー全員がアジャイルテスター
• テスト駆動開発
• アジャイル開発をテスト・テスターへ適用した概念
• ありそうな勘違い
• テストしないことではない
• ドキュメント・テスト計画を作らないわけではない
アジャイルテストの4象限
Agile Test Planning with the Agile Testing Quadrants http://lisacrispin.com/downloads/AdpTestPlanning.pdf p8より
アジャイルテスト+ TDD
• テストファースト
• もしくはテストを書く習慣をつける
• アジャイルチームにとって何が優先度が高いのか、それにあわせてテストを書いていくということ
Real TDD
Google Testing Blog: The *Real* Test Driven Development
http://googletesting.blogspot.jp/2014/04/the-real-test-driven-development.html
(April Fool)
企業に注目
企業に注目• 国内の記事
• はてなやクックパッドの開発現場で、CIやテストはどう行われているのか?(前編)。CROSS 2014 - Publickey
• http://www.publickey1.jp/blog/14/cicross_2014.html
• Microsoft
Microsoft• 特徴
• Windows (OS) や Office など製品多数
• 近年は(ウェブ・クラウド)サービスにもかなり力を入れている
• テストの話題
• キャリアとしてSWET(Software Engineer in Test)のポジションが存在する
• OS・オフィス製品の互換性の維持に関する取り組みが強い
• セキュリティへの早くからの取り組み(Microsoft Security Pushes, 2002年)
• Windowsデバイスドライバへ形式手法・静的解析を適用する研究・ツールの存在
• IDEにテストライブラリを含めたり、テストツールをOSS化する動きもある
Google• 特徴
• 検索サービスにとどまらず、多くのウェブサービスを提供
• 超大規模分散システム・データセンターも含めた運用
• クライアントサイドとして、Android端末・Chromeブラウザ、Chrome OSなどのプログラムも開発
• テストの話題
• SWETなどのキャリアはMicrosoftを参考にしているような面が見られる
• 分散システムのテストに関する情報は少なめ
• テストツール(gtest, gmock)やOSS(Chrome, Android)などを通して業界への貢献
• Google Testing Blog: http://googletesting.blogspot.jp
RRRSpec• Cookpadの分散テスト実行システム(※)
• コードの配信・実行・状態管理が役割
• マスター/スレーブ(ワーカー)型のシステム構成を取る
• スクリプト言語のため、ビルドが不要な点が大きい
• ただし、データベースなど外部環境に依存する場合は、あらかじめ準備しておく必要がある(はず)
• 中断されたテストの再開を自動化できるのがキモ
※: 分散テスト実行システムRRRSpecをリリースしました | クックパッド開発者ブログ http://techlife.cookpad.com/2014/03/24/rrrspec/
RRRSpec考察• PFIとして参考にしたい所
• 分散してのテスト実行は単純に参考になる
• distcc(RRSpec)のgtest版は欲しい
• 現実問題
• ビルド&テスト実行の1フェーズを分散実行したい
• テストに必要なライブラリとテストコードは密結合
• ビルドとテストの依存解決が課題と考えられる
• CMake, waf で何かできないだろうか(考察終了)
Go言語のテストに注目• Goのテストライブラリにはassertion/BDDがない
• ifでエラーを発見したら、自分でエラー文をレポートするというスタイル
※:Go の Test に対する考え方 - Qiita http://qiita.com/Jxck_/items/8717a5982547cfa54ebc Why does Go not have assertions? http://golang.org/doc/faq#assertions
Goライブラリのテスト例• src/pkg/os/os_unix_test.go より抜粋
var expandTests = []struct { in, out string}{ {"", ""},// <<省略/omitted>> {"A$$$#$1$H$home_1*B", "APIDNARGSARGUMENT1(Value of H)/usr/foo*B"},}!func TestExpand(t *testing.T) { for _, test := range expandTests { result := Expand(test.in, testGetenv) if result != test.out { t.Errorf("Expand(%q)=%q; expected %q", test.in, result, test.out) } }}
まとめ• テストの基礎的な用語・良いテストの定義の説明
• Googleのsmall/medium/largeなども参考になる
• テストを書くには
• 良い書籍・ウェブの記事があるので読みましょう
• PFI社内wikiにはテスト入門文書がある
• これを基礎に今後話してみたいこと
• 分散システムのテスト・テストの分散実行
参考資料• 書籍
• 基本から学ぶソフトウェアテスト(Testing Computer Software)
• 体系的ソフトウェアテスト入門(Systematic Software Testing)
• 実践アジャイルテスト(Agile Testing: A Pratical Guide for Testers and Agile Teams)
• テストから見えてくるグーグルのソフトウェア開発(How Google Tests Software)
• How We Test Software at Microsoft
• アカデミック
• Static driver verifier, a formal verification tool for Windows device drivers
• http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1459840
• SLAM - Microsoft Research (Static Driver Verifier)
• http://research.microsoft.com/en-us/projects/slam/
• ブログ
• Google Testing Blog http://googletesting.blogspot.jp
文献 (web)• それっぽい分散テストツールっぽいものをいくつか - kuenishi's blog
• http://kuenishi.hatenadiary.jp/entry/2012/08/02/213030
• PFIインターンへ行ってきた(前編)~結合テストの自動化環境を整えてきた~
• (拙著) http://d.hatena.ne.jp/obfuscation/20110410
• Testing Large-Scale Distributed Software
• http://www.slideshare.net/sunye/testing-largescale-distributed-software
• Distributed software testing - RethinkDB
• http://rethinkdb.com/blog/distributed-software-testing/
• テスト駆動型開発についての議論 - ワザノバ | wazanova
• http://wazanova.jp/items/944