狠狠撸

狠狠撸Share a Scribd company logo
RSpec のここがすごい! RSpec で宣言的な UnitTest! RSpec ? Ruby には、 Test::Unit があるし、 普通に UnitTest が書けるよね? なんで??
RSpec のここがすごい! RSpec で宣言的な UnitTest! まずはこれを見てくれ require 'lru_cache' describe LruCache do describe " を初期化する場合 " do it " は、サイズを渡したら、そのサイズのキャッシュができる ." do targ = LruCache.new(10) targ.limit.should == 10 end it " もし、サイズにマイナス値を渡したら、例外が発生する ." do lambda{ LruCache.new(-1) }.should raise_error(ArgumentError) end it " もし、サイズに nil を渡したら、例外が発生する ." do lambda{ LruCache.new(nil) }.should raise_error(ArgumentError) end it " もし、サイズに数値以外を渡したら、例外が発生する ." do lambda{ LruCache.new("a") }.should raise_error(ArgumentError) end end end http://github.com/mitim/tddbc-lrucache/blob/master/lru_cache_spec.rb
RSpec のここがすごい! RSpec で宣言的な UnitTest! 1.  まず  LruCache に関する 記述 (describe) だよ、と宣言して 1.  そのうちの「初期化をする場合」のテストだよ、と宣言して 1.  「サイズを渡したら、そのサイズのキャッシュができる」べきだと、通常できることを説明していて 1.  その内容で targ.limit は 10 であるべき (should) と明示して 2.  「サイズにマイナス値を渡したら、例外が発生する」べきだと、引数がおかしい場合に起こることを説明していて 1.  その内容で  ArgumentError という error が発生するべきと明示して 3.  「サイズに nil を渡したら、例外が発生する」べきだと、引数がおかしい場合に起こることを説明していて 1.  その内容で  ArgumentError という error が発生するべきと明示して 4.  「サイズに数値以外を渡したら、例外が発生する」べきだと、引数がおかしい場合に起こることを説明していて 1.  その内容で  ArgumentError という error が発生するべきと明示して これを見るだけで、 LruCache が 「何をするプログラムなのか」 が見えてくる ! しかも、 Test::Unit ( Java の JUnit4.1 以前相当)よりも、より 記述が簡便 で読みやすい !
UnitTest の次の流れ -より人が 読みやすい テストへ RSpec で宣言的な UnitTest! UnitTest が広まるなかで、認識されていったこと 1. UnitTest は、ホワイトボックス?テスト ( テスト対象の全コードを理解したうえ  でのテスト ) ではない 。 2. UnitTest でテストしているのは、テスト対象のクラスとメソッドの インタ フェース だ。 1.  つまりは、ブラックボックス?テスト、ステートボックス?テストに 他な らない 。 3.  インタフェース の肝とは、インプットとアウトプットが何であるかをしっかり 確立すること。 1.  つまりは、その インタフェース の振る舞いをしっかり確立すること。 そうだ! 振る舞い をテストするんだ!!
UnitTest の次の流れ -より人が 読みやすい テストへ -> Behavior Test  という認識へ。 RSpec で宣言的な UnitTest! だったら、振る舞いをもっとわかりやすく記述できないかな? -> Java  の場合  : JUnit4.5 assertThat()  の登場
-> Ruby  の場合  : RSpec  の登場 いずれでも、根底にある思想は「 コードは徹頭徹尾人が読むためにある存在 」だということ。
ブラックボックス? ステートボックス? RSpec で宣言的な UnitTest! どちらかというと 設計 に該当する考え方。しかし、そのコードに与える影響の強さは、フローチャート以上。 ブラックボックスやステートボックスの考え方自体は、構造化手法とそれに伴うモジュール化の時代から存在している。
ブラックボックス? ステートボックス? RSpec で宣言的な UnitTest! ブラックボックス?テスト? ブラックボックスとは、あるクラスの公開アクセッサに注視して、その インタフェース を明らかにすること。 じっさいの コードやオブジェクトの状態は考慮に入れない で行う。 クラス そのクラスの公開されている部分(メソッドやプロパティ等)が、外部からアクセス可能になっていること。
ブラックボックス? ステートボックス? RSpec で宣言的な UnitTest! メソッド / プロパティ そのメソッドの IN 値 が明らかになっていること。 IN 値に閾値があるときは、それの範囲
IN 値に特値(特別な値)があるときは、その値
IN 値がオブジェクトの場合:そのステートに制限があるときは、ステート IN 値が 対象外 のときの動作が明らかになっていること。 例外の発行
単なる無動作 IN 値を与えたときの OUT 値 が明らかになっていること。 IN 値に閾値があるときは、とくにその境界値の OUT 値
IN 値に特値があるときは、その場合の OUT 値
クラスにステートがあり、それにより OUT 値が左右される場合は、ステート別の OUT 値
ブラックボックス? ステートボックス? ステートボックス?テスト? ステートボックスとは、あるクラスの オブジェクトのステート やそのクラスが 他に及ぼす影響 に注視して、そのステート?影響を明らかにすること。 じっさいの コードは考慮に入れない で行う。 クラス RSpec で宣言的な UnitTest! そのクラス ( オブジェクト ) のステートと遷移が明らかになっていること。
RSpec で宣言的な UnitTest! ブラックボックス? ステートボックス? メソッド / プロパティ そのメソッドによる、クラス ( オブジェクト ) の ステートの変更 が明らかになっていること。 IN 値によるステートの変化値
IN 値と現ステートの組み合わせによるステートの変化値 そのメソッドによる、 外部への影響 が明らかになっていること。 DB やファイル等、記録媒体への影響
システム的なオブジェクトなど、自身に管理権限のない他のオブジェクトへの影響 そのメソッドでおこる、 外部からの影響 が明らかになっていること。 DB やファイル等、記録媒体からの影響
システム的なオブジェクトなど、自身に管理権限のない他のオブジェクトからの影响
RSpec で宣言的な UnitTest! ブラックボックス? ステートボックス? これらのインタフェースを意識していくと しぜんに、次のような設計を心がけるようになっていく。 1.  メソッドの 引数には、なるべく閾値を設けない 。設ける場合も、列挙(enum)を使 うなどして閾値外にならないように工夫する。 2.  クラスの ステートは、必要最低限に構成する ようになる。複数のステートが絡み複 雑になる場合は、クラス分けを考え出す。 3.  外部への 影響は、なるべく排除する ように考え出す。外部からの影響(変更可能 性)も必要最低限へ。 TDD ではどう扱うか? 1.  どうテストを書いたらいいかわからなくなった!そんな時の指針になる。 2.  ただし、あまりガチガチに縛られないように。
RSpec  のやる事、やらない事 RSpec のやる事 RSpec のやらない事 ( もちろん! )UnitTest が書ける。
即座に UnitTest を実行して、その結果をすぐに得られる。
モックやスタブを使える。 モックやスタブを使えば、テスト範囲を絞れる。 Ruby のありとあらゆる機能が利用できる! とくに、リフレクションがそのまま使えたり、文字列生成が楽なのがうれしい。 ホワイトボックス?テストはサポートしない。 もちろんデバッガ機能なんてないし。 コード?カバレッジは計測しない。 rcovなどを利用しよう。 変更点を感知しての自動実行はされない。 別途CI等を利用しよう。 RSpec で宣言的な UnitTest!
RSpec の構文 なにはなくとも require require  'lru_cache' テスト対象のファイル を読み込ませる。 ちなみに、RSpecの何かをrequireする必要なない。 RSpec で宣言的な UnitTest!
RSpec で宣言的な UnitTest! RSpec の構文 まずは基本 describe  do end で、一番外側のブロックを記述する。 通常は、次のようにテスト対象のクラスを宣言しておく。 また、一緒に説明を付けることも可能。 describe   LRUCache  do end describe   LRUCache ,  " を初期化する場合 "  do end もちろん、説明だけにすることも可能。  describe   "LRUCache のケース "  do end
RSpec の構文 RSpec で宣言的な UnitTest! describe の中 describeの中にもdescribeを重ねられる たとえば、同じクラスのテストでも、 初期化のテストをがっつりやって、 次にhogeメソッドのテスト、 そしてfugaメソッドのテストを …とやっていくと、 必然的にテストが長く見づらくなってくる 。 たとえば、 hogeメソッドのテストと fugaメソッドのテストとでは、 前準備で必要なものがぜんぜん違う 。 そんなときには、 describe のなかにさらに describe を書いて 、整理をつけることができる。
RSpec の構文 RSpec で宣言的な UnitTest! describe の中 describeの説明文 ここに何を書くべきか。 自然に仕様書っぽく構成した文書にしたいなら、次のように気をつけて記述してみるといい。 [ クラス名 ] ,  “[ て / に / を / は / の ]○○ する場合 ( ケース )” ※クラス名は、ひとつ上のdescribeでまとめてしまった方が記述がスッキリするのは、 言うまでも無い。
RSpec の構文 RSpec で宣言的な UnitTest! describe の中 テストの前準備 before テスト本文(it)を実行する前に必要な、 テストと直接は関係ない準備のための処理 を記述する。 たとえば、テスト対象のオブジェクトを生成して、インスタンス変数に入れたり。 たとえば、モックやスタブを用意して、本物のオブジェクトと摩り替えたり。 たとえば、ファイルを用意したり。  before  :each do end before  :all do end :each を指定した before は、各テスト (it) のたびに、その前に必ず実行される。 :all を指定した before は、 describe の最初に一度だけ実行される。
RSpec の構文 RSpec で宣言的な UnitTest! describe の中 テストの後処理 after テスト(it)を実行した後に必要な、 テストと直接は関係ない後片付けのための処理 を記述する。  after  :each do end after  :all do end :each を指定した after は、各テスト (it) を実行するたびに、その後に必ず実行される。  :all を指定した after は、 describe の最後に一度だけ実行される。
RSpec の構文 RSpec で宣言的な UnitTest! it の中 テストのコードは、すべて it の中に記述する。 基本的な書き方は、次のとおり。  it  " テストの説明 "  do [ テスト対象オブジェクト ] . [ テスト対象メソッド ] .should ==  [ 結果 ] end
RSpec の構文 RSpec で宣言的な UnitTest! it の中 ここに何を書くべきか。 自然に仕様書っぽく構成した文書にしたい場合、次のように気をつけて記述してみるといい。 "[ どのような操作をする ] と、 [ その結果はどうなる ] 。 " itの説明文 基本的な機能要件を説明する場合 特殊な機能要件や、エラー的な機能要件を説明する場合 “ は、○○すると、 ×× になる。” “ もし、○○すると、 ×× になる。”
RSpec の構文 RSpec で宣言的な UnitTest! it の中 shouldメソッドは、そのオブジェクトの状態を確認し、指定された状態であるか否か( ~であるべき )を検査する。 ==  演算子のほか、 be 系の Matcher が多数用意されている。 全てのオブジェクトに動的に加えられたメソッドなので、基本的には何でも検査可能。 shouldメソッド should_notメソッド shouldと違い、こちらは否定検査( ~であってはいけない )をするときに使用する。
RSpec の構文 RSpec で宣言的な UnitTest! it の中 shouldで検査できるよう、多数のMatcherが用意されている。 Matcher群 == expected ==比較の結果が同じか be_true 真であるか be_false 偽であるか be_nil nilか be_empty Arrayが空か be_an_instance_of Class クラスがClassと一致するか be_a_kind_of Class クラスが指定Class、もしくはそのサブクラスか == expected ==比較の結果が同じか be_true 真であるか be_false 偽であるか be_nil nilか be_empty Arrayが空か be_an_instance_of Class クラスがClassと一致するか be_a_kind_of Class クラスが指定Class、もしくはそのサブクラスか

More Related Content

Viewers also liked (20)

Orientations Inventory
Orientations InventoryOrientations Inventory
Orientations Inventory
resurrectionsession
?
Infomil als informatiepunt over het Activiteitenbesluit
Infomil als informatiepunt over het ActiviteitenbesluitInfomil als informatiepunt over het Activiteitenbesluit
Infomil als informatiepunt over het Activiteitenbesluit
Netherlands Enterprise Agency (RVO.nl)
?
UCV  IEEE fam ssUCV  IEEE fam ss
UCV IEEE fam ss
Francisco Apablaza
?
MacRuby Jogo Rapido
MacRuby Jogo RapidoMacRuby Jogo Rapido
MacRuby Jogo Rapido
Diogo Santos
?
S Spw Ppt Edit
S Spw Ppt EditS Spw Ppt Edit
S Spw Ppt Edit
Konevo311
?
Acqueon - RAP CMS Data Bridge - Presentation
Acqueon - RAP CMS Data Bridge - PresentationAcqueon - RAP CMS Data Bridge - Presentation
Acqueon - RAP CMS Data Bridge - Presentation
Acqueon Technologies Inc.
?
Inverted Nipple Correction
Inverted Nipple CorrectionInverted Nipple Correction
Inverted Nipple Correction
SHAILESH NISAL
?
Keylingo Translations Summary
Keylingo Translations SummaryKeylingo Translations Summary
Keylingo Translations Summary
themarxhouse
?
Интернет для индустрии красоты
Интернет для индустрии красотыИнтернет для индустрии красоты
Интернет для индустрии красоты
Fert
?
Russia
RussiaRussia
Russia
mazavr
?
Portfolio
PortfolioPortfolio
Portfolio
thatguy88
?
Migration To The United States Of America
Migration  To  The  United  States Of  AmericaMigration  To  The  United  States Of  America
Migration To The United States Of America
13aadx
?
Installing the oracle bi mobile app designer
Installing the oracle bi mobile app designerInstalling the oracle bi mobile app designer
Installing the oracle bi mobile app designer
Ravi Kumar Lanke
?
Creating new service name for oracle database
Creating new service name for oracle databaseCreating new service name for oracle database
Creating new service name for oracle database
Ravi Kumar Lanke
?
Earn More, Save More Or Invest Wisely V2
Earn More, Save More Or Invest Wisely V2Earn More, Save More Or Invest Wisely V2
Earn More, Save More Or Invest Wisely V2
Sudhir Agarwal
?
Ca eed 2014 milan wg5 4 nl split incentive
Ca eed 2014 milan wg5 4   nl split incentiveCa eed 2014 milan wg5 4   nl split incentive
Ca eed 2014 milan wg5 4 nl split incentive
Netherlands Enterprise Agency (RVO.nl)
?
 [HQ NACIONAL] STREET FIGHTER II - ANO I: N?MERO 1 - Parte 4 ( Completo 10/ 0... [HQ NACIONAL] STREET FIGHTER II - ANO I: N?MERO 1 - Parte 4 ( Completo 10/ 0...
[HQ NACIONAL] STREET FIGHTER II - ANO I: N?MERO 1 - Parte 4 ( Completo 10/ 0...
Santuário do Mestre Ryu
?
Strategie nutrizionali nella corsa gjav integratori ferrara
Strategie nutrizionali nella corsa gjav integratori ferraraStrategie nutrizionali nella corsa gjav integratori ferrara
Strategie nutrizionali nella corsa gjav integratori ferrara
GJAV
?
Chicago (Group schoolwork project)
Chicago (Group schoolwork project)Chicago (Group schoolwork project)
Chicago (Group schoolwork project)
Sonny Brabez
?
UCV  IEEE fam ssUCV  IEEE fam ss
UCV IEEE fam ss
Francisco Apablaza
?
Inverted Nipple Correction
Inverted Nipple CorrectionInverted Nipple Correction
Inverted Nipple Correction
SHAILESH NISAL
?
Keylingo Translations Summary
Keylingo Translations SummaryKeylingo Translations Summary
Keylingo Translations Summary
themarxhouse
?
Интернет для индустрии красоты
Интернет для индустрии красотыИнтернет для индустрии красоты
Интернет для индустрии красоты
Fert
?
Migration To The United States Of America
Migration  To  The  United  States Of  AmericaMigration  To  The  United  States Of  America
Migration To The United States Of America
13aadx
?
Installing the oracle bi mobile app designer
Installing the oracle bi mobile app designerInstalling the oracle bi mobile app designer
Installing the oracle bi mobile app designer
Ravi Kumar Lanke
?
Creating new service name for oracle database
Creating new service name for oracle databaseCreating new service name for oracle database
Creating new service name for oracle database
Ravi Kumar Lanke
?
Earn More, Save More Or Invest Wisely V2
Earn More, Save More Or Invest Wisely V2Earn More, Save More Or Invest Wisely V2
Earn More, Save More Or Invest Wisely V2
Sudhir Agarwal
?
 [HQ NACIONAL] STREET FIGHTER II - ANO I: N?MERO 1 - Parte 4 ( Completo 10/ 0... [HQ NACIONAL] STREET FIGHTER II - ANO I: N?MERO 1 - Parte 4 ( Completo 10/ 0...
[HQ NACIONAL] STREET FIGHTER II - ANO I: N?MERO 1 - Parte 4 ( Completo 10/ 0...
Santuário do Mestre Ryu
?
Strategie nutrizionali nella corsa gjav integratori ferrara
Strategie nutrizionali nella corsa gjav integratori ferraraStrategie nutrizionali nella corsa gjav integratori ferrara
Strategie nutrizionali nella corsa gjav integratori ferrara
GJAV
?
Chicago (Group schoolwork project)
Chicago (Group schoolwork project)Chicago (Group schoolwork project)
Chicago (Group schoolwork project)
Sonny Brabez
?

Similar to 搁厂辫别肠のここがすごい! (20)

初心者讲习会资料(翱蝉补办补.谤#6)
初心者讲习会资料(翱蝉补办补.谤#6)初心者讲习会资料(翱蝉补办补.谤#6)
初心者讲习会资料(翱蝉补办补.谤#6)
Masahiro Hayashi
?
闯补惫补厂肠谤颈辫迟クイックスタート
闯补惫补厂肠谤颈辫迟クイックスタート闯补惫补厂肠谤颈辫迟クイックスタート
闯补惫补厂肠谤颈辫迟クイックスタート
Shumpei Shiraishi
?
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
Ransui Iso
?
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
Ransui Iso
?
最近の単体テスト
最近の単体テスト最近の単体テスト
最近の単体テスト
Ken Morishita
?
初心者讲习会资料(翱蝉补办补.搁#7)
初心者讲习会资料(翱蝉补办补.搁#7)初心者讲习会资料(翱蝉补办补.搁#7)
初心者讲习会资料(翱蝉补办补.搁#7)
Masahiro Hayashi
?
svelte-ja.pdf
svelte-ja.pdfsvelte-ja.pdf
svelte-ja.pdf
ssuser65180a
?
R spec勉強会
R spec勉強会R spec勉強会
R spec勉強会
Tatsunori Nishikori
?
搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数
搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数
搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数
Altech Takeno
?
Essential Scala 第3章 オブジェクトとクラス
Essential Scala 第3章 オブジェクトとクラス Essential Scala 第3章 オブジェクトとクラス
Essential Scala 第3章 オブジェクトとクラス
Takuya Tsuchida
?
Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R について
tnoda
?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
Hiromi Ishii
?
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
mitim
?
Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)
Eugene Yokota
?
JavaScript超入門 基礎
JavaScript超入門 基礎JavaScript超入門 基礎
JavaScript超入門 基礎
tetsu6
?
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
Shogo Sensui
?
Spock's world
Spock's worldSpock's world
Spock's world
Takuma Watabiki
?
Rpscala2011 0601
Rpscala2011 0601Rpscala2011 0601
Rpscala2011 0601
Hajime Yanagawa
?
闯补惫补蝉肠谤颈辫でオブジェクト指向
闯补惫补蝉肠谤颈辫でオブジェクト指向闯补惫补蝉肠谤颈辫でオブジェクト指向
闯补惫补蝉肠谤颈辫でオブジェクト指向
1000 VICKY
?
初心者讲习会资料(翱蝉补办补.谤#6)
初心者讲习会资料(翱蝉补办补.谤#6)初心者讲习会资料(翱蝉补办补.谤#6)
初心者讲习会资料(翱蝉补办补.谤#6)
Masahiro Hayashi
?
闯补惫补厂肠谤颈辫迟クイックスタート
闯补惫补厂肠谤颈辫迟クイックスタート闯补惫补厂肠谤颈辫迟クイックスタート
闯补惫补厂肠谤颈辫迟クイックスタート
Shumpei Shiraishi
?
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
Ransui Iso
?
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
Ransui Iso
?
最近の単体テスト
最近の単体テスト最近の単体テスト
最近の単体テスト
Ken Morishita
?
初心者讲习会资料(翱蝉补办补.搁#7)
初心者讲习会资料(翱蝉补办补.搁#7)初心者讲习会资料(翱蝉补办补.搁#7)
初心者讲习会资料(翱蝉补办补.搁#7)
Masahiro Hayashi
?
搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数
搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数
搁耻产测と闯补惫补厂肠谤颈辫迟に见る第一级関数
Altech Takeno
?
Essential Scala 第3章 オブジェクトとクラス
Essential Scala 第3章 オブジェクトとクラス Essential Scala 第3章 オブジェクトとクラス
Essential Scala 第3章 オブジェクトとクラス
Takuya Tsuchida
?
Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R について
tnoda
?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
Hiromi Ishii
?
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
mitim
?
Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)
Eugene Yokota
?
JavaScript超入門 基礎
JavaScript超入門 基礎JavaScript超入門 基礎
JavaScript超入門 基礎
tetsu6
?
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
Shogo Sensui
?
闯补惫补蝉肠谤颈辫でオブジェクト指向
闯补惫补蝉肠谤颈辫でオブジェクト指向闯补惫补蝉肠谤颈辫でオブジェクト指向
闯补惫补蝉肠谤颈辫でオブジェクト指向
1000 VICKY
?

Recently uploaded (8)

滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿
滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿
滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿
Matsushita Laboratory
?
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
NTT DATA Technology & Innovation
?
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
NTT DATA Technology & Innovation
?
Matching_Program_for_Quantum_Challenge_Overview.pdf
Matching_Program_for_Quantum_Challenge_Overview.pdfMatching_Program_for_Quantum_Challenge_Overview.pdf
Matching_Program_for_Quantum_Challenge_Overview.pdf
hirokiokuda2
?
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
CRI Japan, Inc.
?
ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]
ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]
ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]
kota usuha
?
IoT Devices Compliant with JC-STAR Using Linux as a Container OS
IoT Devices Compliant with JC-STAR Using Linux as a Container OSIoT Devices Compliant with JC-STAR Using Linux as a Container OS
IoT Devices Compliant with JC-STAR Using Linux as a Container OS
Tomohiro Saneyoshi
?
ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫
ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫
ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫
ssuserfcafd1
?
滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿
滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿
滨肠丑颈颈搁颈办颈蝉耻办别冲理学疗法士间の知识共有に向けた临床推论テキストの构造化に関する研究.辫诲蹿
Matsushita Laboratory
?
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
PostgreSQL最新動向 ~カラムナストアから生成AI連携まで~ (Open Source Conference 2025 Tokyo/Spring ...
NTT DATA Technology & Innovation
?
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
Apache Sparkに対するKubernetesのNUMAノードを意識したリソース割り当ての性能効果 (Open Source Conference ...
NTT DATA Technology & Innovation
?
Matching_Program_for_Quantum_Challenge_Overview.pdf
Matching_Program_for_Quantum_Challenge_Overview.pdfMatching_Program_for_Quantum_Challenge_Overview.pdf
Matching_Program_for_Quantum_Challenge_Overview.pdf
hirokiokuda2
?
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
2025フードテックWeek大阪展示会 - LoRaWANを使った複数ポイント温度管理 by AVNET玉井部長
CRI Japan, Inc.
?
ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]
ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]
ElasticsearchでSPLADEする [Search Engineering Tech Talk 2025 Winter]
kota usuha
?
IoT Devices Compliant with JC-STAR Using Linux as a Container OS
IoT Devices Compliant with JC-STAR Using Linux as a Container OSIoT Devices Compliant with JC-STAR Using Linux as a Container OS
IoT Devices Compliant with JC-STAR Using Linux as a Container OS
Tomohiro Saneyoshi
?
ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫
ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫
ドメインモデリング基本编①词全体の流れ2025冲02冲27社内向け开催.辫辫迟虫
ssuserfcafd1
?

搁厂辫别肠のここがすごい!

  • 1. RSpec のここがすごい! RSpec で宣言的な UnitTest! RSpec ? Ruby には、 Test::Unit があるし、 普通に UnitTest が書けるよね? なんで??
  • 2. RSpec のここがすごい! RSpec で宣言的な UnitTest! まずはこれを見てくれ require 'lru_cache' describe LruCache do describe " を初期化する場合 " do it " は、サイズを渡したら、そのサイズのキャッシュができる ." do targ = LruCache.new(10) targ.limit.should == 10 end it " もし、サイズにマイナス値を渡したら、例外が発生する ." do lambda{ LruCache.new(-1) }.should raise_error(ArgumentError) end it " もし、サイズに nil を渡したら、例外が発生する ." do lambda{ LruCache.new(nil) }.should raise_error(ArgumentError) end it " もし、サイズに数値以外を渡したら、例外が発生する ." do lambda{ LruCache.new("a") }.should raise_error(ArgumentError) end end end http://github.com/mitim/tddbc-lrucache/blob/master/lru_cache_spec.rb
  • 3. RSpec のここがすごい! RSpec で宣言的な UnitTest! 1. まず LruCache に関する 記述 (describe) だよ、と宣言して 1. そのうちの「初期化をする場合」のテストだよ、と宣言して 1. 「サイズを渡したら、そのサイズのキャッシュができる」べきだと、通常できることを説明していて 1. その内容で targ.limit は 10 であるべき (should) と明示して 2. 「サイズにマイナス値を渡したら、例外が発生する」べきだと、引数がおかしい場合に起こることを説明していて 1. その内容で ArgumentError という error が発生するべきと明示して 3. 「サイズに nil を渡したら、例外が発生する」べきだと、引数がおかしい場合に起こることを説明していて 1. その内容で ArgumentError という error が発生するべきと明示して 4. 「サイズに数値以外を渡したら、例外が発生する」べきだと、引数がおかしい場合に起こることを説明していて 1. その内容で ArgumentError という error が発生するべきと明示して これを見るだけで、 LruCache が 「何をするプログラムなのか」 が見えてくる ! しかも、 Test::Unit ( Java の JUnit4.1 以前相当)よりも、より 記述が簡便 で読みやすい !
  • 4. UnitTest の次の流れ -より人が 読みやすい テストへ RSpec で宣言的な UnitTest! UnitTest が広まるなかで、認識されていったこと 1. UnitTest は、ホワイトボックス?テスト ( テスト対象の全コードを理解したうえ でのテスト ) ではない 。 2. UnitTest でテストしているのは、テスト対象のクラスとメソッドの インタ フェース だ。 1. つまりは、ブラックボックス?テスト、ステートボックス?テストに 他な らない 。 3. インタフェース の肝とは、インプットとアウトプットが何であるかをしっかり 確立すること。 1. つまりは、その インタフェース の振る舞いをしっかり確立すること。 そうだ! 振る舞い をテストするんだ!!
  • 5. UnitTest の次の流れ -より人が 読みやすい テストへ -> Behavior Test という認識へ。 RSpec で宣言的な UnitTest! だったら、振る舞いをもっとわかりやすく記述できないかな? -> Java の場合 : JUnit4.5 assertThat() の登場
  • 6. -> Ruby の場合 : RSpec の登場 いずれでも、根底にある思想は「 コードは徹頭徹尾人が読むためにある存在 」だということ。
  • 7. ブラックボックス? ステートボックス? RSpec で宣言的な UnitTest! どちらかというと 設計 に該当する考え方。しかし、そのコードに与える影響の強さは、フローチャート以上。 ブラックボックスやステートボックスの考え方自体は、構造化手法とそれに伴うモジュール化の時代から存在している。
  • 8. ブラックボックス? ステートボックス? RSpec で宣言的な UnitTest! ブラックボックス?テスト? ブラックボックスとは、あるクラスの公開アクセッサに注視して、その インタフェース を明らかにすること。 じっさいの コードやオブジェクトの状態は考慮に入れない で行う。 クラス そのクラスの公開されている部分(メソッドやプロパティ等)が、外部からアクセス可能になっていること。
  • 9. ブラックボックス? ステートボックス? RSpec で宣言的な UnitTest! メソッド / プロパティ そのメソッドの IN 値 が明らかになっていること。 IN 値に閾値があるときは、それの範囲
  • 11. IN 値がオブジェクトの場合:そのステートに制限があるときは、ステート IN 値が 対象外 のときの動作が明らかになっていること。 例外の発行
  • 12. 単なる無動作 IN 値を与えたときの OUT 値 が明らかになっていること。 IN 値に閾値があるときは、とくにその境界値の OUT 値
  • 15. ブラックボックス? ステートボックス? ステートボックス?テスト? ステートボックスとは、あるクラスの オブジェクトのステート やそのクラスが 他に及ぼす影響 に注視して、そのステート?影響を明らかにすること。 じっさいの コードは考慮に入れない で行う。 クラス RSpec で宣言的な UnitTest! そのクラス ( オブジェクト ) のステートと遷移が明らかになっていること。
  • 16. RSpec で宣言的な UnitTest! ブラックボックス? ステートボックス? メソッド / プロパティ そのメソッドによる、クラス ( オブジェクト ) の ステートの変更 が明らかになっていること。 IN 値によるステートの変化値
  • 17. IN 値と現ステートの組み合わせによるステートの変化値 そのメソッドによる、 外部への影響 が明らかになっていること。 DB やファイル等、記録媒体への影響
  • 20. RSpec で宣言的な UnitTest! ブラックボックス? ステートボックス? これらのインタフェースを意識していくと しぜんに、次のような設計を心がけるようになっていく。 1. メソッドの 引数には、なるべく閾値を設けない 。設ける場合も、列挙(enum)を使 うなどして閾値外にならないように工夫する。 2. クラスの ステートは、必要最低限に構成する ようになる。複数のステートが絡み複 雑になる場合は、クラス分けを考え出す。 3. 外部への 影響は、なるべく排除する ように考え出す。外部からの影響(変更可能 性)も必要最低限へ。 TDD ではどう扱うか? 1. どうテストを書いたらいいかわからなくなった!そんな時の指針になる。 2. ただし、あまりガチガチに縛られないように。
  • 21. RSpec のやる事、やらない事 RSpec のやる事 RSpec のやらない事 ( もちろん! )UnitTest が書ける。
  • 23. モックやスタブを使える。 モックやスタブを使えば、テスト範囲を絞れる。 Ruby のありとあらゆる機能が利用できる! とくに、リフレクションがそのまま使えたり、文字列生成が楽なのがうれしい。 ホワイトボックス?テストはサポートしない。 もちろんデバッガ機能なんてないし。 コード?カバレッジは計測しない。 rcovなどを利用しよう。 変更点を感知しての自動実行はされない。 別途CI等を利用しよう。 RSpec で宣言的な UnitTest!
  • 24. RSpec の構文 なにはなくとも require require 'lru_cache' テスト対象のファイル を読み込ませる。 ちなみに、RSpecの何かをrequireする必要なない。 RSpec で宣言的な UnitTest!
  • 25. RSpec で宣言的な UnitTest! RSpec の構文 まずは基本 describe do end で、一番外側のブロックを記述する。 通常は、次のようにテスト対象のクラスを宣言しておく。 また、一緒に説明を付けることも可能。 describe LRUCache do end describe LRUCache , " を初期化する場合 " do end もちろん、説明だけにすることも可能。 describe "LRUCache のケース " do end
  • 26. RSpec の構文 RSpec で宣言的な UnitTest! describe の中 describeの中にもdescribeを重ねられる たとえば、同じクラスのテストでも、 初期化のテストをがっつりやって、 次にhogeメソッドのテスト、 そしてfugaメソッドのテストを …とやっていくと、 必然的にテストが長く見づらくなってくる 。 たとえば、 hogeメソッドのテストと fugaメソッドのテストとでは、 前準備で必要なものがぜんぜん違う 。 そんなときには、 describe のなかにさらに describe を書いて 、整理をつけることができる。
  • 27. RSpec の構文 RSpec で宣言的な UnitTest! describe の中 describeの説明文 ここに何を書くべきか。 自然に仕様書っぽく構成した文書にしたいなら、次のように気をつけて記述してみるといい。 [ クラス名 ] , “[ て / に / を / は / の ]○○ する場合 ( ケース )” ※クラス名は、ひとつ上のdescribeでまとめてしまった方が記述がスッキリするのは、 言うまでも無い。
  • 28. RSpec の構文 RSpec で宣言的な UnitTest! describe の中 テストの前準備 before テスト本文(it)を実行する前に必要な、 テストと直接は関係ない準備のための処理 を記述する。 たとえば、テスト対象のオブジェクトを生成して、インスタンス変数に入れたり。 たとえば、モックやスタブを用意して、本物のオブジェクトと摩り替えたり。 たとえば、ファイルを用意したり。 before :each do end before :all do end :each を指定した before は、各テスト (it) のたびに、その前に必ず実行される。 :all を指定した before は、 describe の最初に一度だけ実行される。
  • 29. RSpec の構文 RSpec で宣言的な UnitTest! describe の中 テストの後処理 after テスト(it)を実行した後に必要な、 テストと直接は関係ない後片付けのための処理 を記述する。 after :each do end after :all do end :each を指定した after は、各テスト (it) を実行するたびに、その後に必ず実行される。 :all を指定した after は、 describe の最後に一度だけ実行される。
  • 30. RSpec の構文 RSpec で宣言的な UnitTest! it の中 テストのコードは、すべて it の中に記述する。 基本的な書き方は、次のとおり。 it " テストの説明 " do [ テスト対象オブジェクト ] . [ テスト対象メソッド ] .should == [ 結果 ] end
  • 31. RSpec の構文 RSpec で宣言的な UnitTest! it の中 ここに何を書くべきか。 自然に仕様書っぽく構成した文書にしたい場合、次のように気をつけて記述してみるといい。 "[ どのような操作をする ] と、 [ その結果はどうなる ] 。 " itの説明文 基本的な機能要件を説明する場合 特殊な機能要件や、エラー的な機能要件を説明する場合 “ は、○○すると、 ×× になる。” “ もし、○○すると、 ×× になる。”
  • 32. RSpec の構文 RSpec で宣言的な UnitTest! it の中 shouldメソッドは、そのオブジェクトの状態を確認し、指定された状態であるか否か( ~であるべき )を検査する。 == 演算子のほか、 be 系の Matcher が多数用意されている。 全てのオブジェクトに動的に加えられたメソッドなので、基本的には何でも検査可能。 shouldメソッド should_notメソッド shouldと違い、こちらは否定検査( ~であってはいけない )をするときに使用する。
  • 33. RSpec の構文 RSpec で宣言的な UnitTest! it の中 shouldで検査できるよう、多数のMatcherが用意されている。 Matcher群 == expected ==比較の結果が同じか be_true 真であるか be_false 偽であるか be_nil nilか be_empty Arrayが空か be_an_instance_of Class クラスがClassと一致するか be_a_kind_of Class クラスが指定Class、もしくはそのサブクラスか == expected ==比較の結果が同じか be_true 真であるか be_false 偽であるか be_nil nilか be_empty Arrayが空か be_an_instance_of Class クラスがClassと一致するか be_a_kind_of Class クラスが指定Class、もしくはそのサブクラスか
  • 34. RSpec の構文 RSpec で宣言的な UnitTest! it の中 Matcher群 have_key key keyがあるか be_close E,D 数値が、E~Dの範囲に収まっているか change receiver,message,&block Procオブジェクトが変化するか change(receiver,message,&block).by value Procオブジェクトが指定された値で変化するか(should_notは使用できない) change(receiver,message,&block).from(before).to(after) Procオブジェクトがbeforeからafterに変化するか(should_notは使用できない) eql expected ==とほぼ同義((eql?で比較) equal expected 同じオブジェクトか have(n).items 配列などのコレクションオブジェクトが、n個の要素を持っているか。 have_exactly(n).items 配列などのコレクションオブジェクトが、ちょうどn個の要素を持っているか。(should_notは使用できない) have_at_least(n).items 配列などのコレクションオブジェクトが、n個以上の要素を持っているか。(should_notは使用できない) have_at_most(n).items 配列などのコレクションオブジェクトが、n個以下の要素を持っているか。(should_notは使用できない)
  • 35. RSpec の構文 RSpec で宣言的な UnitTest! it の中 Matcher群 include expected 配列などのコレクションオブジェクトに、expectedが入っているか。 match regexp 正規表現regexpにマッチするか。 raise_error 例外が発生するか。 raise_error Expected Expectedな例外が発生するか。 raise_error Expected,message Expectedな例外が、messageを伴って発生するか。 raise_error Expected,regexp Expectedな例外が、正規表現にマッチするメッセージを伴って発生するか。 respond_to method,method,method... オブジェクトが、指定メソッドを全て持つか。 satisfy {|e| ...} ブロックの実行結果(eにテストオブジェクトが渡される)が真になるか。 thorw_symbol(symbol=nil) symbolがthrowされるか。 書いてる本人が、使ったことがないMatcherが多数。
  • 36. RSpec の構文 RSpec で宣言的な UnitTest! it の中 例外が発行されたかどうかはどうチェックする? 次のようにすると、例外の捕捉ができ、例外発行チェックができる。 proc{ [ターゲットオブジェクト].[ターゲットメソッド] }.should raise_error
  • 37. RSpec の構文 RSpec で宣言的な UnitTest! スタブ / モック機能 RSpecには、簡単なスタブとモックを組み込む機構が用意されている。 ここでは、RSpecのスタブ/モック機能に焦点を当てる。 簡単な機構なので、もっとダイナミックな仕組みが欲しい場合は、mochaやflex_mockなどのモック専用ライブラリ/フレームワークを利用した方が効率がいい。
  • 38. RSpec の構文 RSpec で宣言的な UnitTest! スタブ / モック機能 スタブとモックの違い スタブもモックも、UnitTestで必要になる、内部使用している部品をエミュレートすることで、 本物の部品の代用となる空箱 のようなもののことを指す。 なぜこんなものが必要なのか?それは、こんな理由によっている。 全てを「本物」でテストしようとすると、「全てが揃わないとテストできない」という本末転倒な事が起こりかねない。
  • 40. UnitTest が大きな問題に移ると段々と結合テスト化してしまう、という問題がある。 ある程度のスタブ/モックを使用することで、これらの問題が有機的にクリアされていく。 ※ ただし、スタブ/モックを多用し過ぎると、今度はインタフェース不一致の発見を先送りにする、という状況にもなりかねない。このあたりはさじ加減が必要。
  • 41. RSpec の構文 RSpec で宣言的な UnitTest! スタブ / モック機能 スタブとモックの違い では、スタブとモックの違いはなにか? 最近、 Martin Fowler らが、このスタブとモックの違いに関して面白い考察をしていた。この定義は今や一般化しており、RSpecでもこの意味でスタブとモックとを使い分けている。 スタブ 「 インタフェースの定義だけ一致 していれば、中身はどのように動いてもいいので、とりあえず用意しておく空箱」のことを言う。 モック 「インタフェースの定義だけではなく、 それがどの様に呼ばれるか、またそれに対して何を返すべきかまでを模倣 した空箱」のことを言う。
  • 42. RSpec の構文 RSpec で宣言的な UnitTest! スタブ / モック機能 スタブ 何かのクラスのアクセッサをスタブ化するときは、次の構文でアクセッサをスタブに摩り替える。 たとえば次のように書くと、Stringクラスのsizeメソッドが、必ず10を返却するようになる。 [クラス] .stub! (:[アクセッサ]) .and_return ([戻り値]) # [クラス]は[アクセッサ]をスタブ化し、[戻り値]を返す。 String .stub! (:size) .and_return (10)
  • 43. RSpec の構文 RSpec で宣言的な UnitTest! スタブ / モック機能 モック 何かのクラスのアクセッサをモック化するときは、次の構文でアクセッサをモックに摩り替える。 [クラス] .should_recieve (:[アクセッサ]) # [クラス]は[アクセッサ]が呼ばれることを期待する。 [クラス] .should_recieve (:[アクセッサ]) .and_return ([戻り値]) # [クラス]は[アクセッサ]が呼ばれることを期待し、その結果として[戻り値]を返す。 [クラス] .should_recieve (:[アクセッサ]) .with ([引数]) .and_return ([戻り値]) # [クラス]は[アクセッサ]が[引数]で呼ばれることを期待し、その結果として[戻り値]を返す。
  • 44. RSpec の構文 RSpec で宣言的な UnitTest! スタブ / モック機能 たとえば次のように書くと、Arrayクラスのsliceメソッドが引数(5,5)で呼ばれることを期待し、その結果として[5,6,7,8,9]を返却するようになる。 Array .should_recieve (:slice) .with (5,5) .and_return ([5,6,7,8,9]) モック
  • 45. RSpec を実行しよう! RSpec で宣言的な UnitTest! 通常のプログラミング時にテストを行う場合 RSpecは、コンソールからコマンドラインで実行する。(NetBeansを使うと、なんと!IDE内でグラフ付で実行できる!) $ spec -c -fs [specコードファイル.rb] コンソールを出す。 Windowsの場合、Ruby Consoleを出して! specコードのあるディレクトリに移動する。
  • 47. RSpec を実行しよう! RSpec で宣言的な UnitTest! CI のなかでテストを通して行う場合 $ spec -c -fh [specコードファイル.rb] > result.html 次のようにすると、 HTML 形式で結果を出力してくれる。 出力したHTMLを特定HTTPサーバに配置するなり、メールに添付するなどまでを自動化すると、かなり使えるツールになる。