ソフトウェアテスト
入門
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 test
quickly 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
• Google
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

ソフトウェアテスト入門