狠狠撸

狠狠撸Share a Scribd company logo
颁++でテスト駆动开発
自己紹介

? HN: 秋猫

? Twitter: @akineko

? Blog: http://d.hatena.ne.jp/Akineko/ 絶賛更新停滞中!

? 職歴: ホテル→Webデザイン→ゲームプログラマ

? Aimingという会社でオンラインゲームの
  サーバープログラマやってます

? C++とかアジャイル開発が好きです
アジェンダ

? C++のテストライブラリの紹介

? テスト駆动开発とは

? 実践!テスト駆动开発

? テスト駆动开発の恩恵

? テスト駆动开発に必要な知识
テストライブラリの
紹介
Boost.Test




@hotwatermorningさんにパス!
Google Test

? 公式: http://code.google.com/p/googletest/

? ドキュメントの翻訳: http://opencv.jp/googletestdocs/

? 名前の通りGoogle製のC++テストライブラリ

? 豊富なアサーション
  ? http://lovejava.blog85.fc2.com/blog-entry-3.html

? 豊富な機能

? 比較的癖がなく使いやすい
Google Testのテストコード例
#include <gtest/gtest.h>


TEST(CalcTest, AddTest) {
    // 致命的なアサーション
    ASSERT_EQ(5, add(2, 3));


    // 致命的でないアサーション
    EXPECT_EQ(5, add(2, 3));
}
Google Testのフィクスチャ機能
class FooTest : public ::testing::Test {
public:
  FooTest() { /* テストスイート単位での初期化処理 */ }
  ~FooTest() { /* テストスイート単位での終了処理 */ }
protected:
  virtual void SetUp() { /* テスト毎の初期化処理 */ }
  virtual void TearDown() { /* テスト毎の終了処理 */ }
  Foo foo;
}

TEST_F(FooTest, hogeTest) { /* fooを使ったテスト */ }
Cutter

? http://cutter.sourceforge.net/index.html.ja

? CのテストライブラリにC++の機能を追加

? 他ライブラリとは異なった独自の機能を持つ

? テストは共有ライブラリ化して実行する
  ? cutter テストディレクトリ
  ? 上記のコマンドで指定ディレクトリ内の
     共有ライブラリよりテストコードを抽出して実行します

? ドキュメントが超親切!…過ぎてわかりづらいorz
Cutterのテストコード例
#include <cppcutter.h>


namespace calc_test
{
    void test_add()
    {
        cppcut_assert_equal(5, add(2, 3));
    }
}
Cutterのフィクスチャ機能

? cut_startup()
  ? テストスイート単位での初期化処理

? cut_shutdown()
  ? テストスイート単位での終了処理

? cut_setup()
  ? テストケース単位での初期化処理

? cut_teardown()
  ? テストケース単位での終了処理

? これらをnamespace内に含めればOK
その他

? CppUnit
  ? http://sourceforge.net/apps/mediawiki/cppunit/index.php

? CxxTest
  ? http://cxxtest.com/

? QTestLib
  ? http://developer.qt.nokia.com/doc/qt-4.8/qtestlib-manual.html

? UnitTest++
  ? http://unittest-cpp.sourceforge.net/
モックライブラリ

? GoogleMock
  ? http://code.google.com/p/googlemock/
  ? http://opencv.jp/googlemockdocs/index.html



? Mockitopp
  ? http://code.google.com/p/mockitopp/
テスト駆动开発とは
テスト駆动开発とは?

? 通常の開発手法
 ? 実装を行い、それに対するテストを書く
 ? 時にはテストがないものも…




? テスト駆動開発
 ? 先にテストコードを書き、
   そのテストが通る実装を行なっていく開発手法
 ? あくまで開発手法でありテスト手法ではない
テスト駆動開発のサイクル

1.   テストコードを書く

2.   実行して失敗することを確認する

3.   そのテストに成功する最低限の実装コードを書く

4.   実行して成功することを確認する

5.   テストが通る状態のままリファクタリングを行う

6.   1?5をリズムよく繰り返す
実践!テスト駆动开発
ダメージ計算

? プレイヤーがモンスターから受けるダメージを計算せよ

? 受けるダメージは 攻撃力 ー 防御力 とする

? プレイヤーが防御をしていた場合、
        受けるダメージは1/2となる

? 20%の確率でクリティカルとなりダメージは2倍となる
仕様変更!!!

? 20%の確率で攻撃がミスするようにして!

? ダメージは0.8?1.2ぐらいの変動にして!

? クリティカルの時は防御していても無視して!

? ダメージの上限は9999ね!

? ダメージはーになっても回復じゃなくて0にしてね!

? やっぱり避ける確率はすばやさの差で!
テスト駆动开発の恩恵
テスト可能な設計?実装になる

? テストしたいけど複雑に絡み合ってできないを避けれる
 ? 他クラスの状態に依存しまくったクラスとか…
 ? 膨大な引数の関数とか…
 ? 条件分岐しまくりな関数とか…

? 特定の箇所のパフォーマンス測定も容易
 ? テスト出来る=単独実行可能
 ? 計測できるので必要な箇所にのみ最適化ができる
 ? なんとなくここが遅いはずは不要な最適化が…
直ぐに実行可能なテストがある

? 変更によるバグの混入を防げる
 ? 変更の多いゲームこそテストによって守りましょう
 ? 仕様変更といっても一から作り直しはしませんよね?



? めんどくさいからで変更の影響の確認をしないを防げる
 ? 確認しないことが問題ではなくめんどくさいことが問題
 ? 簡単にできれば大事な事なのでみんなしますよね
使いやすいインターフェイス

? テストを書く = 使い方を考える

? 先に使い方を考えるので
  使いにくいインターフェイスに気づける

? 凝集度の高い関数

? 使い方を考えることは設計をする事にもつながる

? 設計について考える機会が増える
テスト駆动开発に
     必要な知识
テスト駆动开発に必要な知识

? テストに関する知識
 ? どういうテストを書けばいいのか

? 設計に関する知識
 ? 大きい問題を小さい問題の集合へ分割する

? リファクタリングに関する知識
 ? コードを良い設計へ改善する
テストのレベル

? 単体テスト
  ? 1つのクラスや1つの関数など
    プログラムの最も小さい部品に対するテスト
  ? 単体の定義は言語により様々
  ? Cだと関数1つ、C++だとクラス1つなど
  ? テスト駆動開発で書くテストのレベルは主にこれ

? 統合テスト
  ? 単体を組み合わせた1つのサブシステムに対するテスト

? Etc…
テストの種別

? ブラックボックステスト
 ? 要件や仕様に基づいてどのように振る舞うべきかのテスト
 ? 内部の実装や構造の知識を必要としない




? ホワイトボックステスト
 ? 内部の実装や構造に基づいたテスト
 ? if文やcase文などの全ての経路を通っているかなど
  プログラミングの知識もある程度必要なもの
ピンポイントテスト
? 仕様書を見て嫌な予感がするところをテストする

? コードを書いていて嫌な予感がするところをテストする

? 間、対称、類推、外側を考える
  ? 具体的な値を並べる
   ? その値の間に値はないか、対称となる値はないか、
    類似した値はないか、外側になる値はないか

? 意地悪条件を考える
  ? めちゃくちゃでかい値、0、nullとか…

? マインドマップを使って考えると効果的
同値クラステスト

? 無数にあるテストケースの数を減らす技法

? 意味のある範囲で分割しその中の代表値をテストする

? この分割された範囲のことを同値クラスと呼ぶ

? ほとんどの人が無意識に実践しています
同値クラステスト

? 仕様: HPの表示の色を%によって変えよ
 ?    通常は白色
 ? 30%以下は黄色
 ?  5%以下は赤色

? この場合の値としては
 ?  0~  5%
    6~ 30%
   31~100%
 ? という範囲に分割でき、この各範囲が同値クラスです
境界値テスト

? 同値クラステストと併用される技法

? 境界となる値はバグが発生しやすい

? この境界に着目してテストする値を選ぶ

? 同値クラスの例だと
 ? 0?5、6?30、31?100なので
 ? -1、0、5、6、30、31、100、101
 ? 各同値クラスの境界となる値と
  その直前?直後の値をテストする
その他いろいろ

? ドメイン分析テスト

? デシジョンテーブル

? CFD法

? HAYST法

? 状態遷移テスト

? 制御フローテスト

? データフローテスト
テストに対する悬念点
分割され過ぎちゃって
パフォーマンスが悪いんじゃないの?
パフォーマンス問題

? 前述の通り根拠なき予想による無駄な最適化が防げます

? 分割が原因でも最適化は関数を展開するだけ

? パフォーマンスの問題が起きるのは全体ではなく
 特定の箇所が問題となる事が多い

? 最適化しか考えてないごちゃごちゃしたコードは
 変更コストの増大や変更によるバグを発生させます
テストできない場所ってあるでしょ?
  できない場所あるんだから
  やっても意味ないじゃん!
テスト問題

? テストしにくい場所、できない場所は確かにあります

? それでもそこ以外のテストができていれば
 問題発生時の特定は比較的容易になります

? プリントデバッグ?デバッガでどこが原因か
 わからないものを闇雲に探したくないですよね?
最后に
まずは…

? 完璧なものなんて気にせずやってみましょう!

? ?の知識がついてからは来ません!

? 書くテストも自分が必要と思う分だけでOK

? テストが不足していた失敗体験で自然と増えます

? やればやるだけ身につきます!
参考書籍

? テスト駆動開発入門
 ? http://amzn.to/wsqgW3

? ?はじめて学ぶソフトウェアのテスト技法
 ? http://amzn.to/zXZz8D

? ?ソフトウェアテスト技法ドリル
 ? http://amzn.to/zVkXLI

? マインドマップから始めるソフトウェアテスト
 ? http://amzn.to/w3BSN7
参考文献

? ?TDD Advent Calendar jp: 2011
  ? http://atnd.org/events/22027

? 和田さんの資料
  ? http://www.slideshare.net/t_wada

? Twitter?Blog?Google検索いろいろ…
ご清聴ありがとうございました!

More Related Content

颁++でテスト駆动开発