Enviar búsqueda
Cargar
TDDワークショップ(第2回)
•
0 recomendaciones
•
3,631 vistas
Yoshihiro Furukawa
Seguir
会社で実施したTDDワークショップ 第2回めの資料です。
Leer menos
Leer más
Denunciar
Compartir
Denunciar
Compartir
1 de 62
Descargar ahora
Descargar para leer sin conexión
Recomendados
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
Norito Agetsuma
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
MITSUNARI Shigeo
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
信之 岩永
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
Takaaki Suzuki
Golangにおける端末制御 リッチなターミナルUIの実現方法
Golangにおける端末制御 リッチなターミナルUIの実現方法
Masashi Shibata
OSC北海道2014_JPUG資料
OSC北海道2014_JPUG資料
Chika SATO
rsyncのちょっとイイ話
rsyncのちょっとイイ話
Kazuhiro Oinuma
俺のTerraform CI/CD ライフサイクル
俺のTerraform CI/CD ライフサイクル
HonMarkHunt
Recomendados
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
Norito Agetsuma
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
MITSUNARI Shigeo
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
信之 岩永
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
Takaaki Suzuki
Golangにおける端末制御 リッチなターミナルUIの実現方法
Golangにおける端末制御 リッチなターミナルUIの実現方法
Masashi Shibata
OSC北海道2014_JPUG資料
OSC北海道2014_JPUG資料
Chika SATO
rsyncのちょっとイイ話
rsyncのちょっとイイ話
Kazuhiro Oinuma
俺のTerraform CI/CD ライフサイクル
俺のTerraform CI/CD ライフサイクル
HonMarkHunt
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
信之 岩永
困らない程度のJDK入門
困らない程度のJDK入門
Yohei Oda
fastTextの実装を見てみた
fastTextの実装を見てみた
Yoshihiko Shiraki
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
NTT DATA Technology & Innovation
マルチコア時代の並列プログラミング
マルチコア時代の並列プログラミング
Akihiko Matuura
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
Takeshi Yamamuro
Native Memory Tracking
Native Memory Tracking
Takahiro YAMADA
Anaconda navigatorのアップデートが終わらないときの対処方法メモ
Anaconda navigatorのアップデートが終わらないときの対処方法メモ
ayohe
DynamoDBの初心者に伝えたい初めて触るときの勘所
DynamoDBの初心者に伝えたい初めて触るときの勘所
Ryo Sasaki
Quine・難解プログラミングについて
Quine・難解プログラミングについて
mametter
CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料
SECCON Beginners
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
yoku0825
PostgreSQLアンチパターン
PostgreSQLアンチパターン
Soudai Sone
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
yoku0825
あなたの知らないPostgreSQL監視の世界
あなたの知らないPostgreSQL監視の世界
Yoshinori Nakanishi
Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析
Takuya Ueda
Djangoフレームワークのユーザーモデルと認証
Djangoフレームワークのユーザーモデルと認証
Shinya Okano
いまさら聞けないパスワードの取り扱い方
いまさら聞けないパスワードの取り扱い方
Hiroshi Tokumaru
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
mametter
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
Takuya Akiba
Androidでテストってどないすんねん!
Androidでテストってどないすんねん!
akimichi Yamada
テストゼロからイチに進むための戦略と戦術
テストゼロからイチに進むための戦略と戦術
Y Watanabe
Más contenido relacionado
La actualidad más candente
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
信之 岩永
困らない程度のJDK入門
困らない程度のJDK入門
Yohei Oda
fastTextの実装を見てみた
fastTextの実装を見てみた
Yoshihiko Shiraki
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
NTT DATA Technology & Innovation
マルチコア時代の並列プログラミング
マルチコア時代の並列プログラミング
Akihiko Matuura
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
Takeshi Yamamuro
Native Memory Tracking
Native Memory Tracking
Takahiro YAMADA
Anaconda navigatorのアップデートが終わらないときの対処方法メモ
Anaconda navigatorのアップデートが終わらないときの対処方法メモ
ayohe
DynamoDBの初心者に伝えたい初めて触るときの勘所
DynamoDBの初心者に伝えたい初めて触るときの勘所
Ryo Sasaki
Quine・難解プログラミングについて
Quine・難解プログラミングについて
mametter
CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料
SECCON Beginners
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
yoku0825
PostgreSQLアンチパターン
PostgreSQLアンチパターン
Soudai Sone
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
yoku0825
あなたの知らないPostgreSQL監視の世界
あなたの知らないPostgreSQL監視の世界
Yoshinori Nakanishi
Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析
Takuya Ueda
Djangoフレームワークのユーザーモデルと認証
Djangoフレームワークのユーザーモデルと認証
Shinya Okano
いまさら聞けないパスワードの取り扱い方
いまさら聞けないパスワードの取り扱い方
Hiroshi Tokumaru
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
mametter
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
Takuya Akiba
La actualidad más candente
(20)
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
困らない程度のJDK入門
困らない程度のJDK入門
fastTextの実装を見てみた
fastTextの実装を見てみた
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
マルチコア時代の並列プログラミング
マルチコア時代の並列プログラミング
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
Native Memory Tracking
Native Memory Tracking
Anaconda navigatorのアップデートが終わらないときの対処方法メモ
Anaconda navigatorのアップデートが終わらないときの対処方法メモ
DynamoDBの初心者に伝えたい初めて触るときの勘所
DynamoDBの初心者に伝えたい初めて触るときの勘所
Quine・難解プログラミングについて
Quine・難解プログラミングについて
CTF for ビギナーズ ネットワーク講習資料
CTF for ビギナーズ ネットワーク講習資料
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
PostgreSQLアンチパターン
PostgreSQLアンチパターン
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
サーバーが完膚なきまでに死んでもMySQLのデータを失わないための表技
あなたの知らないPostgreSQL監視の世界
あなたの知らないPostgreSQL監視の世界
Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析
Djangoフレームワークのユーザーモデルと認証
Djangoフレームワークのユーザーモデルと認証
いまさら聞けないパスワードの取り扱い方
いまさら聞けないパスワードの取り扱い方
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
Cache-Oblivious データ構造入門 @DSIRNLP#5
Cache-Oblivious データ構造入門 @DSIRNLP#5
Similar a TDDワークショップ(第2回)
Androidでテストってどないすんねん!
Androidでテストってどないすんねん!
akimichi Yamada
テストゼロからイチに進むための戦略と戦術
テストゼロからイチに進むための戦略と戦術
Y Watanabe
xUTP Chapter19 (2). Testcase Class
xUTP Chapter19 (2). Testcase Class
Takuto Wada
Junit4
Junit4
ichikaz3
Akka Unit Testing
Akka Unit Testing
Masashi (Jangsa) Kawaguchi
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unit
higaki
テストコードの定型化
テストコードの定型化
Shinichi Hirauchi
タダで始めるテストファースト入門 ~ C# Express + NUnit
タダで始めるテストファースト入門 ~ C# Express + NUnit
Yasuhiko Yamamoto
Spock's world
Spock's world
Takuma Watabiki
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?
Shinichi Hirauchi
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
Takuya Tsuchida
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
Atsushi Tadokoro
Similar a TDDワークショップ(第2回)
(12)
Androidでテストってどないすんねん!
Androidでテストってどないすんねん!
テストゼロからイチに進むための戦略と戦術
テストゼロからイチに進むための戦略と戦術
xUTP Chapter19 (2). Testcase Class
xUTP Chapter19 (2). Testcase Class
Junit4
Junit4
Akka Unit Testing
Akka Unit Testing
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unit
テストコードの定型化
テストコードの定型化
タダで始めるテストファースト入門 ~ C# Express + NUnit
タダで始めるテストファースト入門 ~ C# Express + NUnit
Spock's world
Spock's world
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
Más de Yoshihiro Furukawa
Active learning
Active learning
Yoshihiro Furukawa
自動化ワークショップ
自動化ワークショップ
Yoshihiro Furukawa
Xp祭り2013
Xp祭り2013
Yoshihiro Furukawa
Tddワークショップ
Tddワークショップ
Yoshihiro Furukawa
Agile2013参加報告
Agile2013参加報告
Yoshihiro Furukawa
Umlモデリングの勘所
Umlモデリングの勘所
Yoshihiro Furukawa
Más de Yoshihiro Furukawa
(6)
Active learning
Active learning
自動化ワークショップ
自動化ワークショップ
Xp祭り2013
Xp祭り2013
Tddワークショップ
Tddワークショップ
Agile2013参加報告
Agile2013参加報告
Umlモデリングの勘所
Umlモデリングの勘所
TDDワークショップ(第2回)
1.
TDD Boot Camp 古川
剛啓 http://www.flickr.com/photos/utest/5609991407
2.
アジェンダ 1. TDD概論 2. ワークショップ1(Fizz
Buzz) 3. 振り返り
3.
注意事項 • 今日は学びの場です。納期とかコストとか関係 ありません。気楽に行きましょう。 • 失敗しても問題ありません。失敗から学ぶこと は多々あります。どんどん失敗しましょう。 • 何か1つでも持って帰って貰えたら嬉しいです。
4.
プロジェクト終盤でありがちな状況 ✓単体テストを省略した ✓いつの間にかテストが壊れている ✓ テストが直ぐ壊れるのでテストするのを やめた ✓ テストに時間が掛かるのでテストしてな い ✓そもそもユニットテストなんかしてない http://www.flickr.com/photos/bagger2009/3630270346
5.
http://www.flickr.com/photos/eivindw/2062037429
6.
http://www.flickr.com/photos/edgarallanbro/7197914274 設計にセーフティネットを掛ける
7.
よく見るV字モデル 要件定義 受入試験 基本設計 システム試験 詳細設計 結合試験 ユニットテスト / コーディング ここでやる。 対象はメソッド。
8.
TDDの利点 • テストカバレッジが向上する • テスタビリティが向上する •
メソッドや構造をシンプルに保つことが出来る • 書いたコードに自信が持てる • テストメソッドを読めばメソッドの使い方が分かる • その他 Twitter #TDDやっててよかったのまとめ http://togetter.com/li/258537 等
9.
TDDの欠点 • コードを書くのに時間が掛る • 簡単ではない •
設計しなくなる http://www.flickr.com/photos/ismarbadzic/7250079044/
10.
ユニットテストを難しくする幾つかのこと ✓ コードがハードウェアに依存している ✓ データベースやらネットワークに アクセスして状態が安定しない ✓
クラス間の結合が強くて連鎖的に インスタンス化する必要がある ✓ GUIばっか http://www.flickr.com/photos/tcrazyfish/6864732291
11.
http://www.flickr.com/photos/planetschwa/99535218
12.
SOLIDを意識する S Single Responsibility
Principle 単一責任の原則 O Open-Closed Principle オープン・クローズドの原則 L Liskov Substitution Principle リスコフの置換原則 I Interface Segregation Principle インターフェース分離の原則 D Dependency Inversion Principle 依存関係逆転の原則
13.
ちゃんとレイヤー化する 薄く保つ GUI等 ユーザーインターフェース層 (又はプレゼンテーション層) ドメイン層 (又はモデル層) インフラストラクチャ層 デバイスへのI/F等 DB HDD
14.
TDDをやると本当は何がいいの? http://www.flickr.com/photos/mikedefiant/429402831
15.
今までのプログラミング (Debug Later Programming) Td Tfind Tfix 時間 バグ混入 バグ顕在化 バグ発見 バグFix バグが混入してから顕在化するまでに時間が掛かると、 バグがある場所を探すまでに時間が掛かる
16.
テスト駆動開発 (Test Driven Development) Td Tfind Tfix 時間 バグ混入 バグ顕在化
バグ発見 バグFix バグ混入から顕在化するまでの時間を短くし、 バグがある場所を探すまでの時間を短縮する
17.
18.
19.
20.
ユニットテストフレームワークを使う JUnit, Google Test,
CppUTest・・・ Mockフレームワークを使う jMock, GMock・・・ http://www.flickr.com/photos/kazk/198640938
21.
と言うことで・・・
22.
Google Testをインストールしてみよう • 以下のサイトからGoogle
Mockのソースを ダウンロードする(Google Testのソースも 含まれている) http://code.google.com/p/googlemock/ • zipファイルを適当な場所に解凍する • READMEに従って、ビルド&インストール
23.
24.
で、実際に始める前に・・・
25.
テストメソッドの構造 準備 オブジェクトの生成や状態のセット等を 行う
実行 テスト対象メソッドを実行する 検証 実行結果を検証し、Red/Greenを判定 する 後始末 オブジェクトを破棄する
26.
テストコードのポイント 良いユニットテストはRepeatable (繰り返し可能、再現可能)
テストダブルを使いこなす 外部環境との界面にインターフェイスを作成し、テストダブルで置き換える 良いユニットテストは独立 (Independent) していなければならない 後始末を忘れずに行い、テストを独立させる static を避け、テストメソッド間の依存関係を断つ Assertion Roulette に注意する 目指すのは「テストメソッド毎にアサーションひとつ」(しかし、やりすぎは禁物) カスタムアサーションを使う パラメタライズドテスト(Parameterized Test)を使いこなす Fragile Test (脆いテスト) に注意する テストだけに使う部分の可視性を下げる private メソッドを扱いたくなったら要注意 テストを設計ツールとして使う テストコードのノイズを減らす 日本語テストメソッドを試してみる シンプルなコードとテスト失敗時の情報のバランスを考える これらのポイントを考えながらテストコードを書くことで、テスト容易性を考慮した設計が見えてく るはずです。 出展: CodeIQ MAGAZINE https://codeiq.jp/magazine/2013/11/1475/
27.
準備 (1) 先ずは、テスト対象となるクラス/モジュール を準備する。 (2) テストクラスを準備する。 (3)
ビルドするためのMakefileを書く ツールを準備しました!! ./prepairFiles [--lang=c | -lang=cpp] [--target=targetName] [--without_Makefile] className ・・・
28.
準備 hogeディレクトリ下でコマンドを実行すると以下 のファイルが生成される (classNameは"fuga") hoge/ |- src/ | |-
Makefile | |- productionSources.mk | |- productionObjects.mk | |- testSources.mk | |- testObjects.mk | |- fuga.h | |- fuga.cpp (fuga.c) | | |- test/ |- fugaTest.h |- fugaTest.cpp |- testMain.cpp
29.
準備 fuga.h (c++) fuga.h (c) #ifndef
FUGA_H_ #define FUGA_H_ #ifndef FUGA_H_ #define FUGA_H_ class fuga { public: fuga(); virtual ~fuga(); }; #endif #endif fuga.cpp #include "fuga.h" fuga::fuga() { } fuga::~fuga() { } fuga.c #include "fuga.h"
30.
準備 fugaTest.h (c) #ifndef FUGATEST_H_ #define
FUGATEST_H_ #include <gtest/gtest.h> extern "C" { #include "fuga.h" } class fugaTest : public ::testing::Test { protected: void SetUp(); void TearDown(); public: fugaTest(); virtual ~fugaTest(); }; #endif
31.
準備 fugaTest.h (c++) #ifndef FUGATEST_H_ #define
FUGATEST_H_ #include <gtest/gtest.h> #include "fuga.h" class fugaTest : public ::testing::Test { protected: fuga* sut; void SetUp(); void TearDown(); public: fugaTest(); virtual ~fugaTest(); }; #endif
32.
準備 fugaTest.cpp #include "fugaTest.h" fugaTest::fugaTest() { } fugaTest::~fugaTest()
{ } void fugaTest::SetUp() { sut = new fuga(); // c用には無い } void fugaTest::TearDown() { delete sut; // c用には無い } TEST_F (fugaTest, testNameIsHere_ChangeThis) { /* Write a test code here. */ }
33.
準備 ファイルが生成されたら、srcディレクトリに移動 (cd src)して、 make test --targetに指定した名前+Testの実行ファイルが ビルドされる。(デフォルトは、「a.outTest」) main関数が無いからmakeはできないので注意
34.
よく使うアサーション 2つの値を比較する 致命的なアサーション 致命的ではないアサーション ASSERT_EQ(expected, actual);EXPECT_EQ(expected, actual); ASSERT_NE(val1,
val2); EXPECT_NE(val1, val2); ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); 致命的なアサーション ASSERT_STREQ(expected_str, actual_str); ASSERT_STRNE(str1, str2); 検証内容 expected == actual val1 != val2 val1 < val2 val1 <= val2 val1 > val2 val1 >= val2 致命的ではないアサーション 検証内容 EXPECT_STREQ(expected_str, actual_str); 2つの C 文字列の内容が等しい EXPECT_STRNE(str1, str2); 2つの C 文字列の内容が等しくない ASSERT_STRCASEEQ(expected_str, actual_str);EXPECT_STRCASEEQ(expected_str, actual_str); 大文字小文字を無視した場合,2つの C 文字列の内容が等しい ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); 大文字小文字を無視した場合,2つの C 文字列 の内容が等しくない
35.
Google Testの使い方 戻り値がある関数をテストする テストクラス 関数 f() 関数の戻り値を期待値と比較する 例 EXPECT_EQ(1,
Factorial(0)); EXPECT_EQ(1, sut->Factorial(0)); (c) (c++) 注 • c++のstd::stringは、このアサーションでテストする • cの文字列は、「ASSERT_STREQ」や「EXPECT_STREQ」等を使用する
36.
Google Testの使い方 変数を更新する関数をテストする テストクラス 関数 f() 変数の値を期待値と比較する 例 Factorial(0); EXPECT_EQ(1,
result); (c) sut->Factorial(0); EXPECT_EQ(1, sut->getResult()); (c++) 変数 v
37.
よく使うアサーション 明示的な失敗 FAIL(); 例外アサーション 致命的なアサーション 致命的ではないアサーション 検証内容 ASSERT_THROW(statement, exception_type);EXPECT_THROW(statement, exception_type);
statement が与えられた型の例外を投げる ASSERT_ANY_THROW(statement); EXPECT_ANY_THROW(statement); statement が任意の型の例外を投げる ASSERT_NO_THROW(statement); EXPECT_NO_THROW(statement); statement が例外を投げない
38.
Google Testの使い方 例外がある関数をテストする テストクラス 関数 f() 例外発生の有無や例外の型を期待値と比較する 例 ASSERT_THROW(
sut->parseArguments(argc, argv), std::invalid_argument ); 注 このアサーションは例外をキャッチする 依って、try/catchで囲んでも期待する動作をしない
39.
Tips 関数の呼び出しをテストする (c) テストクラス 関数 f() 関数
g() 関数 g() 関数 f()が、関数 g()を正しく呼び出していることを確認する場合、 • 関数 g()をモックモジュールの関数 g()に置き換える • モックモジュールの関数 g()で引数の値の保存等、必要な処理 を実施 • アサーションにより保存した値等をチェック 注 • 同じ関数を持つオブジェクトファイルをリンクするとエラー(duplicate symbol)が出るので プロダクションコードはライブラリにしてモックモジュールより後にリンクする • テスト対象のモジュールが変わったら、再ビルドが必要かも
40.
Tips privateメソッドをテストする (c++) テストクラス テスト対象クラス + 関数
f() # 関数 g() △ Spyクラス + 関数 g() privateメソッドをどうしてもテストしたい場合、 • privateメソッドをprotectedメソッドに変更する • テスト対象クラスを継承するSpyクラスを定義し、その中で publicに変更した同名のメソッドを定義する • Spyクラスのメソッドは、元のメソッドを呼び出すだけ 注 • privateメソッドをテストする必要性を検討する必要あり • privateメソッドは、publicメソッドから呼び出されているので何らかの形でテスト済みなハズ
41.
Tips 標準出力への出力内容をテストする (c/c++) テストクラス 関数 f() stdout/stderrへの出力をテストしたい場合、 •
Google Testに付属の関数を使用する • stdoutへの出力を変数に保存する • stdoutへの出力をファイルに保存する 標準出力
42.
Tips (Google Testに付属の関数を使用する) (c/c++) テストクラス 関数
f() 標準出力 #include <gtest/internal/gtest-port.h> TEST_F(aaaTest, stdoutTest) { testing::internal::CaptureStdout(); sayHello(); ASSERT_STREQ("Hello", testing::internal::GetCapturedStdout().c_str()); } CaptureStdout()とGetCapturedStdout()の間は、標準出力に出力 されるはずだった文字列は保存され、 GetCapturedStdout()で取 り出すことができる。 標準エラー出力は、 CaptureStderr()とGetCapturedStderr()を使用する。
43.
Tips (stdoutへの出力を変数に保存する) (c++) テストクラス 関数 f() 標準出力 std::string
CWorkerSpy::output() { std::stringbuf buf; // リダイレクト先の変数 std::streambuf* oldbuf = std::cout.rdbuf(&buf); // 標準出力のstreamを保存 CWorker::output(); std::cout.rdbuf(oldbuf); // 標準出力のstreamを復帰 return buf.str(); } • テスト対象クラスのSpyクラスを定義 • アサーションでテストできるようにstringを返すラッパーメソッドを 定義 • 標準出力のstreamを保存 • 元のメソッドを呼び出す • 標準出力のstreamを復帰
44.
Tips (stdoutへの出力をファイルに保存する) (c++) テストクラス 関数 f() 標準出力 void
CWorkerSpy::output() { std::ofstream ofs("output.txt"); // リダイレクト先のファイル std::streambuf* oldrdbuf = std::cout.rdbuf(ofs.rdbuf()); // 標準出力のstreamを保存 CWorker::output(); std::cout.rdbuf(oldrdbuf); } • • • • • テスト対象クラスのSpyクラスを定義 ラッパーメソッドを定義 標準出力のstreamを保存 元のメソッドを呼び出す 標準出力のstreamを復帰
45.
Google Testによるパラメータ化テスト •パラメータ化テストとは、1つのテストメソッド内でテスト条件(引 数や期待値)を変えながらテストするもの。 •限界値分析や同値分割をやる際に有効 •テストクラスを継承すると共にWithParamInterface<T>を実装 •Tには、テスト対象メソッドの引数の型を指定 ::testing::WithParamInterface<T> △ ::testing::Test △ テストクラス △ パラメータ化テストクラス
46.
Google Testによるパラメータ化テスト (引数が1つ) #include <gtest/gtest.h> #include
"../test/hogeTest.h" class IsEvenParametricTest : public hogeTest, public ::testing::WithParamInterface<int> { }; TEST_Pに変更 #include "IsEvenParametricTest.h" パラメータを取得 TEST_P (IsEvenParametricTest, testNameIsHere_ChangeThis) { /* Write a test code here. */ EXPECT_EQ(true, sut->isEven(GetParam())); } INSTANTIATE_TEST_CASE_P(EvenTest, IsEvenParametricTest, testing::Values(2, 4) ); パラメータを準備
47.
Google Testによるパラメータ化テスト (複数の引数だったり、戻り値もだったり) #include <gtest/gtest.h> #include
<boost/tuple/tuple.hpp> #include "../test/hogeTest.h" 複数のパラメータの場合は tupleを使用 class IsEvenParametricTest2 : public hogeTest, public ::testing::WithParamInterface< boost::tuple<bool, int> > { }; #include "IsEvenParametricTest2.h" パラメータを取得 TEST_P (IsEvenParametricTest2, testNameIsHere_ChangeThis) { /* Write a test code here. */ const bool expect = boost::get<0>(GetParam()); const int num = boost::get<1>(GetParam()); EXPECT_EQ(expect, sut->isEven(num)); } INSTANTIATE_TEST_CASE_P(EvenTest, IsEvenParametricTest2, testing::Values( boost::make_tuple(true, 2), boost::make_tuple(false, 3)) ); パラメータを準備
48.
Red ー Green
ー リファクタリング サイクル テストメソッドを書く テストをPassする最低限 のコードを実装する リファクタリング
49.
例:三角形のチェッククラスを考える TriangleクラスのcheckTriangleメソッド • 3辺が等しい三角形、”EqualateralTriangle”を返す • 2辺が等しい三角形、”IsoscelesTriangle”を返す •
三角形にならない時、”NotTriangle”を返す
50.
例:三角形のチェッククラスを考える Step 1 テストメソッド 三辺が同じ長さの時、”EqualateralTriangle”が返される事を確認 する TEST_F(TriangleTest, AllSidesAreSameLength)
{ EXPECT_EQ("EqualateralTriangle", sut->checkTriangle(1,1,1)); } std::string Triangle::checkTriangle(int a, int b, int c) { return "EqualateralTriangle"; }
51.
例:三角形のチェッククラスを考える Step 2 テストメソッド 二辺が同じ長さの時、”IsoscelesTriangle”が返される事を確認す る TEST_F(TriangleTest, TwoSidesAreSameLength_rhs_lhs)
{ EXPECT_EQ("IsoscelesTriangle", sut->checkTriangle(1,1,2)); } std::string Triangle::checkTriangle(int a, int b, int c) { if((a == b) && (b == c) && (c == a)) { return "EqualateralTriangle"; } return "IsoscelesTriangle"; }
52.
例:三角形のチェッククラスを考える Step 3 テストメソッド 三角形にならない時、”NotTriangle”が返される事を確認する TEST_F(TriangleTest, LhsLengthTooShort)
{ EXPECT_EQ("NotTriangle", sut->checkTriangle(1,3,4)); } std::string Triangle::checkTriangle(int a, int b, int c) { if((a == b) && (b == c) && (c == a)) { return "EqualateralTriangle"; } if(a == b) { return "IsoscelesTriangle"; } return "NotTriangle"; }
53.
例:三角形のチェッククラスを考える Step 4 リファクタリング(引数名の変更) std::string Triangle::checkTriangle(int
lhs, int rhs, int bottom) { if((lhs == rhs) && (rhs == bottom) && (bottom == lhs)) { return "EqualateralTriangle"; } if(lhs == rhs) { return "IsoscelesTriangle"; } return "NotTriangle"; }
54.
継続的にTDDをやるための材料 • 単体テストは設計(実装)の一部だと理解する • 単体テストフレームワークを使用する •
テストコードも構成管理する • テストカバレッジを「Doneの定義」に含める • CI (Continuous Integration)サーバを導入する http://www.flickr.com/photos/roboppy/312248677
55.
最後に • TDD は簡単なプラクティスではありません。 •
しかし、コード品質は確実に向上します。 • 一度や二度の失敗で諦めずに取り組みましょう。 継続は、力なり http://www.flickr.com/photos/picsbyperi/7457301384
56.
57.
ワークショップのルール • 先ずは、ペアで自己紹介して下さい。 • ナビゲータとドライバを決めて下さい。 •
ナビゲータがテストコードを、 ドライバがプロダクションコードを書いて下さい。 • ナビゲータとドライバは適当に交代して下さい。 • 時間は30分です。
58.
ワークショップ1 FizzBuzzクラス(又は関数)を作る • 引数が3の倍数の時、”Fizz”を返す • 引数が5の倍数の時、”Buzz”を返す •
引数が3と5の公倍数の時、”FizzBuzz”を返す • それ以外の時、引数の整数を文字列にして返す
59.
ワークショップ2 FizzBuzzを作る さっき作ったクラス(関数)を使ってFizzBuzzを 作ってください • 引数は、1~100で • ディスプレイに表示するように
60.
ワークショップ3 FizzBuzzを作る さっき作ったFizzBuzzを改修してください • 出力先をファイルに変更してください。 • ファイル名は任意でOKです。
61.
ワークショップ4 FizzBuzzを作る さっき改修したFizzBuzzを更に改修してください • 出力先をファイルだけでなく、ディスプレイにも 表示するように変更してください。 • ファイル名は任意でOKです。
62.
ワークショップ5 FizzBuzzを作る さっき改修したFizzBuzzを更に改修してください • 数字はディスプレイに、Fizz、Buzz、及びFizzBuzz はファイルに出力するようにしてください • ファイル名は任意でOKです。
Descargar ahora