ユニットテスト 1日目
DESCRIPTION
Python Developer Camp2008 ユニットテストの紹介スライドTRANSCRIPT
PythonDeveloperCamp 2008
ユニットテスト - 1日目 -
渋川よしき
PythonDeveloperCamp 2008ユニットテスト1日目 Page 2
まずは
目的- ユニットテストは何かを知る
- ユニットテストは何ではないかを知る
- テスト駆動開発の作法を知る
- unittest.py, doctest を使ってみる
やって欲しいこと※
- 体験→発見
- いつもと違ったことをする
- 質問する
- 失敗はない、学びがある
- 楽しむ ※六本木ヒルズでやっている NLPセミナーの手法を参考にしてます
PythonDeveloperCamp 2008ユニットテスト1日目 Page 3
チェックイン※
ペアを作ってください- 二人一組で開発してもらいます
- やろうとすること、考えていることを口に出すと学習効果アップ※
自己紹介 (2 人で 2 分 )
- 自分の名前 or ハンドルネーム
- Python との関わり
- この1時間で何を学びたいか?という決意表明をしてください
※僕が勝手に師匠と呼んでいる方の スライドを参考にしました※「言語技術」が日本のサッカーを変える
PythonDeveloperCamp 2008ユニットテスト1日目 Page 4
アジェンダ
ディレクティブテスト- ユニットテストとは何か?
- ユニットテストとは何ではないのか?
unittest.py を使ったテスト駆動開発体験- まずは開発のデモ
- 続きはみなさんの手で!
doctest を使ってみる
PythonDeveloperCamp 2008
テストの分類
~ディレクティブなテスト~
PythonDeveloperCamp 2008ユニットテスト1日目 Page 6
2種類のテスト
ディレクティブなテスト- 開発をディレクション ( 方向付け ) するためのテスト
- アジャイルソフトウェア開発で言うところのテスト
マネジメントのためのテスト- 品質などを管理するためのテスト
- いわゆる、ソフトウェア工学の教科書に出てくるテスト
PythonDeveloperCamp 2008ユニットテスト1日目 Page 7
この分類の発想の種
フランクリンプランナー- ディレクタ・リーダ ( メンバーをひっぱる )
- 戦略立案、決断、全体設計- マネージャ ( メンバーの尻をたたく )
- 人・モノ・金の管理、細かい設計
ソフトウェアのテスト- アジャイル開発のテスト- ソフトウェア工学の本に載っているテスト
+ほりうち!師匠のスライド
PythonDeveloperCamp 2008Here comes your footer Page 8
テスト駆動開発 (TDD) とユニットテスト
テスト駆動開発- テストを先に書き、実際のコードをその後に書くやり方
- この開発手法の中で書くテストがユニットテスト
- eXtreme Programmingで広まった手法
- 開発の方向付けをするディレクティブなテスト
いろんな呼び方- テストファーストプログラミング
- デベロッパーテスト
- 動く仕様書
PythonDeveloperCamp 2008Here comes your footer Page 9
まとめ~ユニットテストとは?~
ユニットテストとは何か?- 開発を方向付けする
- テスト駆動開発の中で書く
ユニットテストは何ではないか- 品質管理のテスト
- ウォーターフォールのテストフェーズのテスト
PythonDeveloperCamp 2008
ユニットテストをテスト駆動で書く
unittest.py
PythonDeveloperCamp 2008Here comes your footer Page 11
例題:ダーツのクリケット
15 ~ 20 、ブル ( 中心 ) だけを使う 交互に投げる 1つの数字に3本入ると占領 ( クロー
ズ )
- ダブルは2本分、トリプルは3本分
- 全員が一つの数字をクローズするとキル
- クローズしてキルされるまではスコアが入る
誰かが全部をクローズすると終了- スコアが高い人の勝ち
- 最大 20 ラウンド
引用元: Wikipedia
PythonDeveloperCamp 2008ユニットテスト1日目 Page 12
まずは準備
ファイルの構成はどちらでもいいです。- 実際のコードとテストコードでファイル分割
- テストコードも実際のコードも同じファイルにする
PyScripter を使っていればスタートアップコードは不要です
最初のテストをパスするところまではデモします。真似してタイプしてみてください
二つめ以降は画面に出しませんので、挑戦してみてください
# -*- coding: utf-8 -*-
import unittest
# スタートアップコード
if __name__ == “__main__”:
unittest.runTests()
PythonDeveloperCamp 2008ユニットテスト1日目 Page 13
例題:ダーツのクリケット (今回のワークで扱う範囲 )
15 ~ 20 、ブル ( 中心 ) だけを使う→ 18 と 20だけ使う
交互に投げる→一人分だけ実装 1つの数字に3本入ると占領 ( クローズ )
- ダブルは2本分、トリプルは3本分
- 全員が一つの数字をクローズするとキル
- クローズしてキルされるまではスコアが入る
誰かが全部 (18 と 20) をクローズすると終了- スコアが高い人の勝ち
- 最大 20 ラウンド
PythonDeveloperCamp 2008ユニットテスト1日目 Page 14
テスト駆動開発の基本ルール
テストファースト- Python が「コードを書いてくれ~」と言ってからコードを書く
- 具体的には AttributeError, AssertionError など
仮実装- 返値が 3 なら、 return 3 と書いてしまう
三角測量- 一つのメソッドにつき2つのテストケースを使う
明白な実装- 分かり切っている実装は仮実装を行わないでいきなり実装
- 今回は封印してください
PythonDeveloperCamp 2008ユニットテスト1日目 Page 15
最初のメソッドを実装するまでテストケースを書く
テストケースは unittest.TestCase の子クラスとして実装します テストを書くメソッドは test から始めます TestCase クラスのメソッド (assert_, assertFalse, assertEqual など ) を使って
テストを書いていきます。 なるべく小さいステップで上れるように、階段を設定していきます。
class TestCricket(unittest.TestCase):
def test_throw_1(self):
game = Cricket()
game.throw(18, 1)
self.assertEqual(game.get_count(18), 1)
PythonDeveloperCamp 2008
最初のメソッドを実装するまでFailure を見る→仮実装で OK を見る
次に、 NameError( クラスが無い ) と言われるので、クラスを実装する。
NameError→AttributeError( メソッドがない ) とひとつずつ解決していくと、 Error が Failure( テスト失敗 ) に変化する
Failure を見たら、仮実装 ( テストを通るだけの最低限 ) をしてテストをOK にする
ユニットテスト1日目 Page 16
class Cricket(object):
def throw(self, area, count):
pass
def get_count(self, area):
return 1 #仮実装
PythonDeveloperCamp 2008ユニットテスト1日目 Page 17
最初のメソッドを実装するまで三角測量でメソッドを完成させる
もう一つテストを書いて、実装を完成させます (三角測量 )
- 第一ステップ:一つ値を設定してから取得 ( 最初の仮実装 )
- 第二ステップ:もう一つ値を設定して、合計値を取得 (今回のステップ )
def test_throw_2(self):
game = Cricket()
game.throw(18, 1)
game.throw(18, 2)
self.assertEqual(game.get_count(18), 3)
PythonDeveloperCamp 2008
それでは手を動かしてみて下さい残りの仕様を実装してみてください
15 ~ 20 、ブル ( 中心 ) だけを使う→ 18 と 20だけ使う
交互に投げる→一人分だけ実装 1つの数字に3本入ると占領 ( クローズ )
- ダブルは2本分、トリプルは3本分
- 全員が一つの数字をクローズするとキル
- クローズしてキルされるまではスコアが入る
誰かが全部 (18 と 20) をクローズすると終了- スコアが高い人の勝ち
- 最大 20 ラウンド
ユニットテスト1日目 Page 18
PythonDeveloperCamp 2008
ユニットテストのその後今回はここまではできません m(_ _)m
リファクタリング- 機能追加すると徐々にコードが汚くなる
- プログラムを整理してキレイにする
- 修正後のコードの動作はユニットテストが保証する
開発のリズム- レッド:テストが失敗
- グリーン:テストが成功
- リファクタリング:きれいなコードへ
きれい
汚い
( すぐに ) 動かない
※角谷さんのスライドより
GREEN
動く
Ref
acto
ring
RED
ユニットテスト1日目 Page 19
PythonDeveloperCamp 2008
doctest を使ってみよう
ユニットテスト1日目 Page 20
PythonDeveloperCamp 2008
doctest
doctest とは?- docstring の中のテストコードを実行する仕
組み
- コメントの中に自然に書ける
- インタラクティブモードをコピペすればテスト完成
- 文芸的なテスト
- Python が発祥?
import doctest
def pow(x, y):
"""calc power.
>>> pow(1, 2)
1
>>> pow(10, 2)
100
"""
result = 1
for i in xrange(y):
result *= x
return result
if __name__ == '__main__':
doctest.testmod()
ユニットテスト1日目 Page 21
PythonDeveloperCamp 2008
doctest を書いてみよう
例題:先ほど作ったクリケットのクラスのテスト- ゲーム終了までの過程をインタラクティブモードで実行
- それをコピペして、 docstring に書き込みます。
- もしも unittest のスタートアップを書いていた場合には doctest のスタートアップに切り替えます。
実行の仕方- スタートアップコードを書いた場合にはそのままコンソールから実行できま
す
- エラーがないと何も画面には出ません
- -v をつけると、実況中継が出ます
ユニットテスト1日目 Page 22
PythonDeveloperCamp 2008
doctest に関する渋川の所感
メリット- 気軽に書ける
- コメントの中にかけるので、自然言語で補強できる
- ユーザの目に触れやすい
- ライブラリ系ならば動作可能なドキュメント / サンプルコードとして使える
デメリット- 複雑なテストケースが書きにくい
- 網羅的なテストケースが書きにくい ( 1オブジェクトにつき数パターンが限度? )
- return で結果がきれい出るものじゃないと書きにくい (結果が DOM ツリーになるとか )
ユニットテスト1日目 Page 23
PythonDeveloperCamp 2008
宿題
周りの人とユニットテストについて議論してみましょう。
ダーツのクリケット- 残りのルールもすべて実装してみてください
ボウリング- ユニットテストのサンプルとして人気の、ボウリングのスコア計算を作ってみて
ください
100 本ユニットテスト※
- ユニットテストを 100 本書いてみて下さい※MindMapのセミナーの宿題を 参考にしました
ユニットテスト1日目 Page 24
PythonDeveloperCamp 2008
参考資料これからユニットテストを深めていくために
Python のライブラリリファレンス unittest, doctest
デブサミ2008 和田卓人氏「デベロッパーテスティング・ライブ」
JPUG北海道支部/Ruby札幌合同 角谷信太郎氏「スはスペックのス」
Google→TDD, ユニットテスト etc
http://www.codeplex.com/pyspec/ - 引っ越し予定 まさーる 氏 Kent Beck Testing Framework入門 ( 渋川の原点 ) – 1999年
ユニットテスト1日目 Page 25