Your SlideShare is downloading. ×
ユニットテスト_2日目
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

ユニットテスト_2日目

1,534
views

Published on

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,534
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. ユニットテスト -2 日目 - 渋川よしき ※ 1日目からの流用も多いです。最初に言い訳しておきます。
  • 2. まずは
    • 目的
      • 昨日の宿題 (doctest, ユニットテストのメリット )
      • ビヘイビア駆動開発とは何者かを知る
      • PySpec を使ってみる
      • モックオブジェクトなどの周辺技術も知る
    • やって欲しいこと ※
      • 体験->発見
      • いつもと違ったことをする
      • 質問する
      • 失敗はない、学びがある
      • 楽しむ
    ユニットテスト2日目 Page ※ 六本木ヒルズでやっている   NLP セミナー の手法を参考にしてます
  • 3. チェックイン ※
    • ペアを作ってください
      • 二人一組で開発してもらいます。昨日とは違う人と組んでください。
      • やろうとすること、考えていることを口に出すと学習効果アップ ※
    • 自己紹介 (2 人で 2 分 )
      • 自分の名前 or ハンドルネーム
      • Python との関わり
      • この1時間で何を学びたいか?という決意表明をしてください
    ユニットテスト2日目 Page ※ 僕が勝手に 師匠と呼んでいる方の  スライド を参考にしました ※ 「言語技術」が日本のサッカーを変える
  • 4. ( 参考 ) 昨日作った、一人分のルールエンジンクラス ユニットテスト2日目 Page class Cricket(object): def __init__(self): self.areas = {18:0, 20:0} def throw(self, area, count): if area not in self.areas: return self.areas[area] += count def get_count(self, area): return self.areas[area] def is_closed(self, area): return self.get_count(area) >= 3 def is_finished(self): return self.is_closed(18) and self.is_closed(20)
  • 5. doctest を使ってみよう ユニットテスト1日目  Page
  • 6. 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()
  • 7. doctest を書いてみよう
    • 例題:先ほど作ったクリケットのクラスのテスト
      • ダーツを投げてみて、クリアするまでの過程をインタラクティブモードで実行します
      • それをコピペして、 docstring に書き込みます。
      • もしも unittest のスタートアップを書いていた場合には doctest のスタートアップに切り替えます。
    • 実行の仕方
      • スタートアップコードを書いた場合にはそのままコンソールから実行できます
      • エラーがないと何も画面には出ません
      • -v をつけると、実況中継が出ます
  • 8. doctest に関する渋川の所感
    • メリット
      • 気軽に書ける
      • コメントの中にかけるので、自然言語で補強できる
      • ユーザの目に触れやすい
      • ライブラリ系ならば動作可能なドキュメント / サンプルコードとして使える
    • デメリット
      • 複雑なテストケースが書きにくい
      • 網羅的なテストケースが書きにくい ( 1オブジェクトにつき数パターンが限度? )
      • return で結果がきれい出るものじゃないと書きにくい ( 結果が DOM ツリーになるとか )
  • 9. ユニットテストの利点
  • 10. ユニットテストの利点 渋川の考えていること
    • 脳の右側を使う
      • 子供にパズルをさせる
        • 何か欠けている
        • 完成形が見える
        • 何をすればいいのかが分かる
    • 余計な脳を使わない
      • 脳の処理能力は意識しないところでも使われる
      • 無駄なことを視界からはずすことで効率を上げる-> GTD
    • 品質アップ
      • ポカよけ
      • リファクタリングを円滑にすすめるためのセーフティネット
        • テストのないリファクタリングはスリリングで危ない楽しさがある
    ユニットテスト2日目 Page
  • 11. ディレクティブなテストの歴史 ※ 説明は飛ばすので、暇なときにでもお読みください
  • 12. xUnit の歴史
    • SUnit と JUnit
      • SUnit は eXtreme Programming で有名な Kent Beck が作成
      • フレームワークが持っている特徴はすでに完成していた
        • TestCase を継承、 test で始まるメソッド名、 assert 文
      • JUnit は Kent Beck と Eric Gamma( デザパタの人 ) が作成
    • xUnit へ
      • XP 本 (1999) の広がりとともに、いろんな言語に移植された
      • pyunit も 1999 に開発され、 Python2.1(Apr/2001) にバンドル
    ユニットテスト2日目 Page
  • 13. TDD から BDD
    • BDD が登場
      • 2003 年に jBehave というフレームワークが開発された
        • 2004 年に平鍋さんが日本に紹介
        • 懸田さんの翻訳記事 はかなり重要
      • Test/assert を、 should/verify に改名
      • テストじゃなくて仕様なんだ!というのを強調
        • サピアウォーフの仮説という言葉が一瞬流行った
    • rSpec
      • 2005 年に rSpec の開発が開始
      • 活発に開発されていて、今 BDD 界をリードしているのは rSpec( っぽい )
    ユニットテスト2日目 Page
  • 14. PySpec
    • PyUnitX
      • unittest.py が古くさく感じたので、デコレータでテスト宣言をする フレームワークとして 2006 年に開発開始
      • 2006 年のオブジェクト倶楽部夏イベントのライトニングトークス でデモ
      • BDD っぽいテストの書き方も追加機能で実装
    • PySpec へ
      • BDD 機能のみに絞り、 TDD っぽい名前は削除
      • 一度完全にスクラップにしてリビルドした
      • Python Workshop The Edge 2007 のトークス で発表
      • 2008 年 1 月に CodePlex で公開 ->引っ越し予定
    ユニットテスト2日目 Page
  • 15. PySpec でユニットテストを書いてみよう
  • 16. 例題:ダーツのクリケット
    • 15 ~ 20 、ブル ( 中心 ) だけを使う
    • 交互に投げる
    • 1つの数字に3本入ると占領 ( クローズ )
      • ダブルは2本分、トリプルは3本分
      • 全員が一つの数字をクローズするとキル
      • クローズしてキルされるまではスコアが入る
    • 誰かが全部をクローズすると終了
      • スコアが高い人の勝ち
      • 最大 20 ラウンド
    Here comes your footer  Page 引用元: Wikipedia
  • 17. 例題:ダーツのクリケット ( 今回のワークの範囲 )
    • 15 ~ 20 、ブル ( 中心 ) だけを使う -> 18, 20
    • 交互に投げる -> 2 人プレイ
    • 1つの数字に3本入ると占領 ( クローズ )
      • ダブルは2本分、トリプルは3本分
      • 全員が一つの数字をクローズするとキル
      • クローズしてキルされるまではスコアが入る
    • 誰かが全部をクローズすると終了
      • スコアが高い人の勝ち
      • 最大 20 ラウンド
    Here comes your footer  Page 引用元: Wikipedia
  • 18. まずは準備
    • ファイルの構成はどちらでもいいです。
      • 実際のコードとテストコードでファイル分割
      • テストコードも実際のコードも同じファイルにする
    • 最初のテストをパスするところまではデモします。真似してタイプしてみてください
    • 二つめ以降は画面に出しませんので、 挑戦してみてください
    ユニットテスト2日目 Page # -*- coding: utf-8 -*- from pyspec import * # スタートアップコード if __name__ == “__main__”: run_test()
  • 19. テスト駆動開発の基本ルール ->基本は TDD と一緒
    • テストファースト
      • Python が「コードを書いてくれ~」と言ってからコードを書く
      • 具体的には AttributeError, AssertionError など
    • 仮実装
      • 返値が 3 なら、 return 3 と書いてしまう
    • 三角測量
      • 一つのメソッドにつき2つのテストケースを使う
    • 明白な実装
      • 分かり切っている実装は仮実装を行わないでいきなり実装
    • 仕様が分かるメソッド名前
      • 名前だけで仕様書の記述ができるようにする。コンテキストと仕様は分ける
    ユニットテスト2日目 Page
  • 20. 最初のメソッドを実装するまで 仕様を記述する
    • テストクラスは普通の Python のクラス
    • 準備は @context, 仕様は @spec というデコレータをつける
    • About().should_equal() などを使ってテストを書いていきます。
    • 準備と仕様はなるべく分けます。仕様書として、事前条件、事後条件を分けて書く
    ユニットテスト2日目 Page class Behavior_CricketGame(object): @context def a_new_game(self): self.game = CricketGame() @spec def which_current_player_is_no1(self): About(self.game.current()).should_equal(0)
  • 21. 最初のメソッドを実装するまで Failure を見る->仮実装で OK を見る (TDD と一緒 )
    • 次に、 NameError( クラスが無い ) と言われるので、クラスを実装する。
    • NameError->AttributeError( メソッドがない ) とひとつずつ解決していくと、 Error が Failure( テスト失敗 ) に変化する
    • Failure を見たら、仮実装 ( テストを通るだけの最低限 ) をしてテストを OK にする
    ユニットテスト2日目 Page class CricketGame(object): def current(self): pass
  • 22. 最初のメソッドを実装するまで 三角測量でメソッドを完成させる
    • もう一つテストを書いて、実装を完成させます ( 三角測量 )
      • 第一ステップ:最初のプレイヤーは1 ( 最初の仮実装 )
      • 第二ステップ:一回投げるとプレイヤー2 ( 今回のステップ )
    ユニットテスト2日目 Page @context(group=2) def a_game_that_was_thrown_once(self): self.game = CricketGame() self.game.throw(18, 1) @spec(group=2) def which_current_is_no2(self): About(self.game.current()).should_equal(1)
  • 23. 例題:ダーツのクリケット ( 今回のワークの範囲 )
    • 15 ~ 20 、ブル ( 中心 ) だけを使う -> 18, 20
    • 交互に投げる -> 2 人プレイ
    • 1つの数字に3本入ると占領 ( クローズ )
      • ダブルは2本分、トリプルは3本分
      • 全員が一つの数字をクローズするとキル
      • クローズしてキルされるまではスコアが入る
    • 誰かが全部をクローズすると終了
      • スコアが高い人の勝ち
      • 最大 20 ラウンド
    Here comes your footer  Page 引用元: Wikipedia
  • 24. PySpec 周辺機能のデモ MockObject, レガシーコードテスト ユニットテスト2日目  Page
  • 25. MockObject
    • MockObject( 模造オブジェクト ) とは?
      • まだ無いオブジェクトの振りをして、もうすでにあるかのように動作する
      • 外部からの操作 ( メソッド呼び出し ) が適正か調べる
        • 調べる機能がないものはスタブと呼ばれる
      • 親から呼ばれる子供オブジェクトに使うことが多い
    • なぜ作ったのか?
      • Ruby の dRuby の実装を見て、そのアイディアを持ってきた
        • 好きなメソッドは method_missing
      • PySpec 自身のテストを書くのに必要だった
    ユニットテスト2日目 Page
  • 26. MockObject のサンプル
    • Record&Verify
      • 第一ステップ:最初のプレイヤーは1 ( 最初の仮実装 )
      • 第二ステップ:一回投げるとプレイヤー2 ( 今回のステップ )
    ユニットテスト2日目 Page from pyspec.mockobject import * recorder = MockObjectRecorder() recorder. throw(18, 1) recorder. get_count(18) == 1 mock = recorder. _get_mock_object_() mock.throw(18, 2 ) <= エラー mock. _verify_() <= 呼び残しがあればエラー
  • 27. レガシーコードテスト機能
    • レガシーコードテストの仕組み
      • 既存の振る舞いを正として、コードが壊れてないか調べる
      • プログラマの意図を表現したユニットテストに比べたら補助的機能
        • 徐々に正規のユニットテストに置き換えていくことを想定
      • 一度目の実行結果を記録する
    • レガシーコードテストのための機能
      • About().should_not_be_changed()
        • 値が変更していないことを調査する
      • pyspec.legacycode.test_proxy()
        • オブジェクトに対するプロキシとして動作し呼ばれたメソッドを記録・検証する
    ユニットテスト2日目 Page
  • 28. レガシーコードテスト機能のサンプル
    • should_not_be_changed()
    • test_proxy()
    ユニットテスト2日目 Page cricket = test_proxy(Cricket())      # メソッド呼び出し、返り値を監視して、異なっていればエラー cricket.throw(18, 2) cricket.get_score(18) cricket.finished() a = 10 About(a).should_not_be_changed() # 絶対成功する例 b = random.randint(0, 100) About(b).should_not_be_changed() # 絶対失敗する例
  • 29. クロージング 2日間お疲れ様でした ユニットテスト2日目  Page
  • 30. よりよいテストを書くために
    • 見やすいテスト
      • 準備と結果 ( テスト ) を明確に分離する
      • 文字列と変数重要 ( 人も PC も読んで分かる )
      • 必要に応じて裏口 ( テスト用のインタフェース ) を作る
        • PySpec の中にもたくさん裏口があります
      • テストもリファクタリングして読みやすいように
    • これからの挑戦
      • UI のテストをもっとシンプルに
      • テスト結果を、非開発者が読んで意味のある情報として出力する
      • カバレッジの表示など、もっとテストしたくなる機能の追加
      • 間口を広げる (doctest 統合など )
    ユニットテスト2日目 Page
  • 31. 宿題
    • 周りの人とユニットテストについて議論してみましょう。
    • ダーツのクリケット
      • 残りのルールもすべて実装してみてください
    • ボウリング
      • ユニットテストのサンプルとして人気の、ボウリングのスコア計算を作ってみてください
    • 100 本ユニットテスト ※
      • ユニットテストを 100 本書いてみて下さい
    ※ MindMap のセミナー の宿題を   参考にしました ユニットテスト2日目 Page
  • 32. 参考資料 これからユニットテストを深めていくために
    • Python のライブラリリファレンス unittest , doctest
    • デブサミ 2008 和田卓人氏「デベロッパーテスティング・ライブ」
    • JPUG 北海道支部 /Ruby 札幌合同 角谷信太郎氏「スはスペックのス」
    • Google->TDD, ユニットテスト etc
    • http://www.codeplex.com/pyspec/ - 引っ越し予定
    • まさーる氏 Kent Beck Testing Framework 入門 ( 渋川の原点 ) – 1999 年
    ユニットテスト2日目 Page