2013年6月15日Ruby初級者向けレッスン 46回— Test::Unit —ひがき @ Ruby関西
お品書き• テスト フレームワーク• テスト駆動開発– Red–Green–Refactor• Test::Unit の小技• Test Double
テスト フレームワーク いろいろ• Test::Unit• RSpec• Cucumber• Capybara• etc.
Test::Unit• プログラムの単体テストを行う• Ruby用の xUnit– MiniTest::Unit — 標準添付– Test::Unit — 標準添付∗ 内部で MiniTest::Unit を使用– Test::Unit Gem
RSpec• プログラムの振舞いを記述する (BDD)• ドメイン特化言語 (DSL)• 参考– http://jp.rubyist.net/magazine/?0021-Rspec
Cucumber (::)• 自然言語に近い形式で書ける• 受け入れテスト向け• これからは Turnip なの?http://magazine.rubyist.net/?0042-FromCucumberToTurnip
Capybara• Webアプリケーション向け– ブラウザ上のユーザ操作– JavaScript
自動テストのメリット• 機能的な保証– バグの検出– バグ混入を監視• 開発支援– 不安を解消– リファクタリング
テスト駆動開発1. まずテストを書き、失敗することを確認する2. テストが成功するように、製品コードを書く3. テストはそのまま、コードをきれいに
Red–Green–Refactorテスト プロダクトRed GreenRefactor-?
テスト駆動開発をやってみよう• プロダクトコード — myarray.rb• テストコード — test myarray.rb• MyArray が空のときMyArray#empty? は真であるべき
Step 0 プロダクトclass MyArraydef initialize@array = []endend
Step 0 テストrequire ’test/unit’require ’./myarray’class TestMyArray  Test::Unit::TestCasedef setup@array = MyArray.newenddef...
テストのながれテストごとに、以下を実行する。1. setup — 準備2. test ∼ — テスト本体3. teardown — 後始末• テストの実行順序は無保証• 各テストは他のテストに依存してはいけない
Step 0 ERROR 実行$ ruby test_myarray.rb...E===================================================Error: test_empty_by_empty_mya...
Step 1 プロダクトclass MyArraydef initialize@array = []enddef empty? # = 追加end # = 追加end
Step 1 Red 実行$ ruby test_myarray.rb...F===================================================Failure: nil is not true.test_em...
Step 2 プロダクトclass MyArraydef initialize@array = []enddef empty?true # = 追加endend
Step 2 Fake it! 実行$ ruby test_myarray.rbLoaded suite test_myarrayStarted.Finished in 0.000942 seconds.1 tests, 1 assertion...
assert式が真なら、テストが通る。assert(.empty?, 空であること)assert(obj.nil?, nil であること)
assert equal第1引数 == 第2引数 なら、テストが通る。assert_equal(0, array.size)assert_equal(’matz’, author)assert_equal(0.3, 0.2 + 0.1, Fai...
assert in epsilon第1引数と第2引数の誤差が第3引数の許容範囲内なら、テストが通る。assert_in_epsilon(0.3, 0.2 + 0.1, 1e-15)
assert raiseブロック内で、第1引数の例外が発生したら、テストが通る。ex = assert_raise(IndexError) do[].fetch(0)end
Step 3 プロダクトclass MyArray...def empty?true # = Fake it!enddef  o # = 追加@array  o # = 追加self # = 追加end # = 追加end
Step 3 テスト...class TestMyArray  Test::Unit::TestCase...def test_empty_by_empty_myarrayassert(@array.empty?)enddef test_emp...
Step 3 Triangulate 実行$ ruby test_myarray.rb....F===================================================Failure: false is not t...
Step 4 プロダクトclass MyArray...def empty?@array.empty? # = 修正enddef  o@array  oselfendend
Step 4 Green 実行$ ruby test_myarray.rbLoaded suite test_myarrayStarted..Finished in 0.00123 seconds.2 tests, 2 assertions, ...
小技 --help$ ruby test_myarray.rb --helpTest::Unit automatic runner.Usage: test_myarray.rb [options] [-- untouched argum-r, ...
小技 --verbose$ ruby test_myarray.rb --verboseLoaded suite test_myarrayStartedTestMyArray:test_empty_by_empty_myarray: .: (0...
小技 テストの指定$ ruby test_myarray.rb -v -n /_non/Loaded suite test_myarrayStartedTestMyArray:test_empty_by_nonempty_myarray: .:...
こんなときどうするrequire ’person’class TestPerson  Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(1965, 4, 1...
Test Double• テスト対象 (プロダクト) が依存しているコンポーネントを置き換える– ダミーオブジェクト– テストスタブ– テストスパイ– モックオブジェクト– フェイクオブジェクトhttp://goyoki.hatenablog....
例えば影武者を使うrequire ’kagemusha/time’class TestPerson  Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(19...
もしくは Mocha を使うrequire ’mocha/setup’class TestPerson  Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(...
あるいは RR を使うrequire ’rr’class TestPerson  Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(1965, 4, 14)...
まとめ• テスト フレームワーク• テスト駆動開発– Red–Green–Refactor• Test::Unit の小技• Test Double
演習問題 0今日のレッスンで分からなかったこと、疑問に思ったことをグループで話し合ってみよう。
演習問題 1• スタッククラスを作ろう!– テスト駆動開発で「スタック」クラスを作ってみよう。– push で順に要素を追加できること。– pop で最後から順に要素を取り出せること。– このような動作を LIFO (Last In, Firs...
実装するメソッド• empty?– スタックが空なら真、空でなければ偽を返す。• size– スタックの要素数を返す。• push(val)– 引数の値をスタックの最後に積む• pop– スタックの最後の値を取り除いて返す。– スタックが空なら...
Step 1 empty?• 新しいスタックの empty? は真であること。• テストが失敗することを確認しよう。Red• Stack#empty? で真を返そう。Fake it!
Step 2 push pop• 新しいスタックに 3 を push して、pop すると 3が返ること。• テストが失敗することを確認しよう。Red• pop で 3 を返そう。Fake it!
Step 3 size• 新しいスタックに 3 を push するとsize が 1 になること。• テストが失敗することを確認しよう。Red• Stack#size で 1 を返そう。Fake it!
Step 4 size• 新しいスタックに 3 を push した後、5 を push すると size が 2 になること。• Fake it! が通らなくなることを確認しよう。Triangulate• テストが通るように修正しよう。
Step 5 empty?• 新しいスタックに 3 を push するとempty? は偽であること。• Fake it! が通らなくなることを確認しよう。Triangulate• テストが通るように修正しよう。
Step 6 pop• 新しいスタックから pop するとStack::EmptyStackErrorが発生すること。
Step 7 pop• 新しいスタックに 3 を push した後、5 をpush し、pop すると size が 1 であること。
Step 8 pop• 新しいスタックに 3 を push した後、5 を push し、pop すると 5 が返ること。
自己紹介• 名前 (ニックネーム)• 普段の仕事・研究内容・代表作• Ruby歴・コンピュータ歴• 勉強会に来た目的• などなど
参考• るりまhttp://doc.ruby-lang.org/ja/• サンプルコードhttps://github.com/higaki/learn ruby kansai 58• XP祭り関西にてユニットテストの保守に関する発表http:/...
Upcoming SlideShare
Loading in …5
×

Ruby初級者向けレッスン 第46回 ─── Test::Unit

3,542 views

Published on

Published in: Technology, Education
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,542
On SlideShare
0
From Embeds
0
Number of Embeds
191
Actions
Shares
0
Downloads
21
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide

Ruby初級者向けレッスン 第46回 ─── Test::Unit

  1. 1. 2013年6月15日Ruby初級者向けレッスン 46回— Test::Unit —ひがき @ Ruby関西
  2. 2. お品書き• テスト フレームワーク• テスト駆動開発– Red–Green–Refactor• Test::Unit の小技• Test Double
  3. 3. テスト フレームワーク いろいろ• Test::Unit• RSpec• Cucumber• Capybara• etc.
  4. 4. Test::Unit• プログラムの単体テストを行う• Ruby用の xUnit– MiniTest::Unit — 標準添付– Test::Unit — 標準添付∗ 内部で MiniTest::Unit を使用– Test::Unit Gem
  5. 5. RSpec• プログラムの振舞いを記述する (BDD)• ドメイン特化言語 (DSL)• 参考– http://jp.rubyist.net/magazine/?0021-Rspec
  6. 6. Cucumber (::)• 自然言語に近い形式で書ける• 受け入れテスト向け• これからは Turnip なの?http://magazine.rubyist.net/?0042-FromCucumberToTurnip
  7. 7. Capybara• Webアプリケーション向け– ブラウザ上のユーザ操作– JavaScript
  8. 8. 自動テストのメリット• 機能的な保証– バグの検出– バグ混入を監視• 開発支援– 不安を解消– リファクタリング
  9. 9. テスト駆動開発1. まずテストを書き、失敗することを確認する2. テストが成功するように、製品コードを書く3. テストはそのまま、コードをきれいに
  10. 10. Red–Green–Refactorテスト プロダクトRed GreenRefactor-?
  11. 11. テスト駆動開発をやってみよう• プロダクトコード — myarray.rb• テストコード — test myarray.rb• MyArray が空のときMyArray#empty? は真であるべき
  12. 12. Step 0 プロダクトclass MyArraydef initialize@array = []endend
  13. 13. Step 0 テストrequire ’test/unit’require ’./myarray’class TestMyArray Test::Unit::TestCasedef setup@array = MyArray.newenddef test_empty_by_empty_myarrayassert(@array.empty?)endend
  14. 14. テストのながれテストごとに、以下を実行する。1. setup — 準備2. test ∼ — テスト本体3. teardown — 後始末• テストの実行順序は無保証• 各テストは他のテストに依存してはいけない
  15. 15. Step 0 ERROR 実行$ ruby test_myarray.rb...E===================================================Error: test_empty_by_empty_myarray(TestMyArray)NoMethodError: undefined method ‘empty?’ for#MyArray:0x802ea72c @array=[]test_myarray.rb:12:in ‘test_empty_by_empty_myarray’...1 tests, 0 assertions, 0 failures, 1 errors,0 pendings, 0 omissions, 0 notifications
  16. 16. Step 1 プロダクトclass MyArraydef initialize@array = []enddef empty? # = 追加end # = 追加end
  17. 17. Step 1 Red 実行$ ruby test_myarray.rb...F===================================================Failure: nil is not true.test_empty_by_empty_myarray(TestMyArray)test_myarray.rb:12:in ‘test_empty_by_empty_myarray’...1 tests, 1 assertions, 1 failures, 0 errors,0 pendings, 0 omissions, 0 notifications
  18. 18. Step 2 プロダクトclass MyArraydef initialize@array = []enddef empty?true # = 追加endend
  19. 19. Step 2 Fake it! 実行$ ruby test_myarray.rbLoaded suite test_myarrayStarted.Finished in 0.000942 seconds.1 tests, 1 assertions, 0 failures, 0 errors,0 pendings, 0 omissions, 0 notifications100% passed
  20. 20. assert式が真なら、テストが通る。assert(.empty?, 空であること)assert(obj.nil?, nil であること)
  21. 21. assert equal第1引数 == 第2引数 なら、テストが通る。assert_equal(0, array.size)assert_equal(’matz’, author)assert_equal(0.3, 0.2 + 0.1, Fail!!)Fail!!0.3 expected but was0.30000000000000004
  22. 22. assert in epsilon第1引数と第2引数の誤差が第3引数の許容範囲内なら、テストが通る。assert_in_epsilon(0.3, 0.2 + 0.1, 1e-15)
  23. 23. assert raiseブロック内で、第1引数の例外が発生したら、テストが通る。ex = assert_raise(IndexError) do[].fetch(0)end
  24. 24. Step 3 プロダクトclass MyArray...def empty?true # = Fake it!enddef o # = 追加@array o # = 追加self # = 追加end # = 追加end
  25. 25. Step 3 テスト...class TestMyArray Test::Unit::TestCase...def test_empty_by_empty_myarrayassert(@array.empty?)enddef test_empty_by_nonempty_myarray # = 追加@array 1st # = 追加assert(!@array.empty?) # = 追加end # = 追加end
  26. 26. Step 3 Triangulate 実行$ ruby test_myarray.rb....F===================================================Failure: false is not true.test_empty_by_nonempty_myarray(TestMyArray)test_myarray.rb:17:in ‘test_empty_by_nonempty_myarra...2 tests, 2 assertions, 1 failures, 0 errors,0 pendings, 0 omissions, 0 notifications
  27. 27. Step 4 プロダクトclass MyArray...def empty?@array.empty? # = 修正enddef o@array oselfendend
  28. 28. Step 4 Green 実行$ ruby test_myarray.rbLoaded suite test_myarrayStarted..Finished in 0.00123 seconds.2 tests, 2 assertions, 0 failures, 0 errors,0 pendings, 0 omissions, 0 notifications100% passed
  29. 29. 小技 --help$ ruby test_myarray.rb --helpTest::Unit automatic runner.Usage: test_myarray.rb [options] [-- untouched argum-r, --runner=RUNNER Use the given RUNNE--collector=COLLECTOR Use the given COLLE--ignore-name=NAME Ignores tests match-t, --testcase=TESTCASE Runs tests in TestC...-h, --help Display this help.Deprecated options:--console Console runner (use
  30. 30. 小技 --verbose$ ruby test_myarray.rb --verboseLoaded suite test_myarrayStartedTestMyArray:test_empty_by_empty_myarray: .: (0.000630)test_empty_by_nonempty_myarray: .: (0.000499)Finished in 0.001676 seconds.2 tests, 2 assertions, 0 failures, 0 errors,0 pendings, 0 omissions, 0 notifications100% passed
  31. 31. 小技 テストの指定$ ruby test_myarray.rb -v -n /_non/Loaded suite test_myarrayStartedTestMyArray:test_empty_by_nonempty_myarray: .: (0.000499)Finished in 0.000892 seconds.1 tests, 1 assertions, 0 failures, 0 errors,0 pendings, 0 omissions, 0 notifications100% passed
  32. 32. こんなときどうするrequire ’person’class TestPerson Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(1965, 4, 14))assert_equal(48, matz.age)# 来年はテストに失敗する!?endend
  33. 33. Test Double• テスト対象 (プロダクト) が依存しているコンポーネントを置き換える– ダミーオブジェクト– テストスタブ– テストスパイ– モックオブジェクト– フェイクオブジェクトhttp://goyoki.hatenablog.com/entry/20120301/1330608789
  34. 34. 例えば影武者を使うrequire ’kagemusha/time’class TestPerson Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(1965, 4, 14))Kagemusha::Time.at(2013, 6, 15) doassert_equal(48, matz.age)endendend
  35. 35. もしくは Mocha を使うrequire ’mocha/setup’class TestPerson Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(1965, 4, 14))Time.stubs(:now).returns(Time.local(2013, 6, 15))assert_equal(48, matz.age)endend
  36. 36. あるいは RR を使うrequire ’rr’class TestPerson Test::Unit::TestCasedef test_agematz = Person.new(’matz’, Time.local(1965, 4, 14))mock(Time).now{Time.local(2013, 6, 15)}assert_equal(48, matz.age)endend
  37. 37. まとめ• テスト フレームワーク• テスト駆動開発– Red–Green–Refactor• Test::Unit の小技• Test Double
  38. 38. 演習問題 0今日のレッスンで分からなかったこと、疑問に思ったことをグループで話し合ってみよう。
  39. 39. 演習問題 1• スタッククラスを作ろう!– テスト駆動開発で「スタック」クラスを作ってみよう。– push で順に要素を追加できること。– pop で最後から順に要素を取り出せること。– このような動作を LIFO (Last In, FirstOut) という。
  40. 40. 実装するメソッド• empty?– スタックが空なら真、空でなければ偽を返す。• size– スタックの要素数を返す。• push(val)– 引数の値をスタックの最後に積む• pop– スタックの最後の値を取り除いて返す。– スタックが空ならStack::EmptyStackErrorを発生させる。
  41. 41. Step 1 empty?• 新しいスタックの empty? は真であること。• テストが失敗することを確認しよう。Red• Stack#empty? で真を返そう。Fake it!
  42. 42. Step 2 push pop• 新しいスタックに 3 を push して、pop すると 3が返ること。• テストが失敗することを確認しよう。Red• pop で 3 を返そう。Fake it!
  43. 43. Step 3 size• 新しいスタックに 3 を push するとsize が 1 になること。• テストが失敗することを確認しよう。Red• Stack#size で 1 を返そう。Fake it!
  44. 44. Step 4 size• 新しいスタックに 3 を push した後、5 を push すると size が 2 になること。• Fake it! が通らなくなることを確認しよう。Triangulate• テストが通るように修正しよう。
  45. 45. Step 5 empty?• 新しいスタックに 3 を push するとempty? は偽であること。• Fake it! が通らなくなることを確認しよう。Triangulate• テストが通るように修正しよう。
  46. 46. Step 6 pop• 新しいスタックから pop するとStack::EmptyStackErrorが発生すること。
  47. 47. Step 7 pop• 新しいスタックに 3 を push した後、5 をpush し、pop すると size が 1 であること。
  48. 48. Step 8 pop• 新しいスタックに 3 を push した後、5 を push し、pop すると 5 が返ること。
  49. 49. 自己紹介• 名前 (ニックネーム)• 普段の仕事・研究内容・代表作• Ruby歴・コンピュータ歴• 勉強会に来た目的• などなど
  50. 50. 参考• るりまhttp://doc.ruby-lang.org/ja/• サンプルコードhttps://github.com/higaki/learn ruby kansai 58• XP祭り関西にてユニットテストの保守に関する発表http://goyoki.hatenablog.com/entry/20110202/1296663870

×