お題:assert_equal
チャート式Rubyの4回目,テスト駆動開発の根本となるassert_equalです.assert equalとはequalかどうかを確かめる(assert)関数です.どんなのでもいいんですが,自分で作ると好きにできますんで,その様子を見てもらいましょう.
解法:red,green
まずは1==1です.
> ruby assert_equal.rb
ruby: No such file or directory -- assert_equal.rb (LoadError)
もちろんないんで,それをemacsします.
p 1==1
として見ましょう.
> ruby assert_equal.rb
true
と返ってきてますか?
これをmethodにします.英語の感覚だと,
assert equal expected and result
とでもなるでしょうか.なんで,
assert_equal(expected, result)
という感じです.まずはred
p assert_equal(1, 1)
として見ましょう.
> ruby assert_equal.rb
assert_equal.rb:1:in `<main>': undefined method `assert_equal' for main:Object (NoMethodError)
関数がないと怒られますよね.それなら,
def assert_equal(expected, result)
return expected == result
end
p assert_equal(1, 1)
なら動くし,ちゃんとtrueが返ってますよね.
解説:colorize-出色の継承-
これだけだと,殺風景なんで,red, green, refactoringという標語にしたがって動作するように変えます.肝は,colorizeです.
require 'colorize'
def assert_equal(expected, result)
if expected == result
puts 'true'.green
else
puts 'false'.red
end
end
assert_equal(1, 1)
どうです.greenでしょ?
ならtestにredも付け加えて置きましょう.
assert_equal(1, 2)
redでしょ?
colorizeというgem libraryがないと怒られたなら
> gem install colorize
でinstallしてください.関学のproxyで引っかかっている人は,
> gem install colorize -r -p http://proxy.ksc.kwansei.ac.jp:8080
してください.
gemというのはrubyのlibraryを管理するシステムです.色々出せますんで,試してみてください.
> irb
irb(main):001:0> require 'colorize'
=> true
irb(main):002:0> String.colors
=> [:black, :light_black, :red, :light_red, :green, :light_green, :yellow, :light_yellow, :blue, :light_blue, :magenta, :light_magenta, :cyan, :light_cyan, :white, :light_white, :default]
colorizeは,ruby標準のString classに色を表示するmethodを上載せ(override)します.こんなのがすぐに使えて色々あるのがrubyです.いや,object思考です.
改良:richer output
もう少し出力をrichにしましょう.
- 引数でとってきた,expected, resultの値をそのまま出力
- どうなったかを記述
- true: print "succeeded in assert_equal.\n".green
- false: print "failed in assert_equal.\n".red
どうです.できました?
require 'colorize'
def assert_equal(expected, result)
if expected == result
puts 'true'.green
else
puts 'false'.red
end
end
assert_equal(1, 1)
assert_equal(1, 2)
拡張:assert_not_equal
assert_not_equal(1, 2)
を考えましょう.まずはtestです.上のんを入れて実行して見ましょう.
> ruby assert_equal.rb
expected :: 1
result :: 1
succeeded in assert_equal.
expected :: 1
result :: 2
failed in assert_equal.
assert_equal.rb:15:in `<main>': undefined method `assert_not_equal' for main:Object (NoMethodError)
Did you mean? assert_equal
なんかが返ってくるでしょうか.関数がないと怒られます.まずはcopy & pasteします.関数名だけassert_equalからassert_not_equalに直しましょう.
expected :: 1
result :: 2
failed in assert_equal.
となります.このままだと,振る舞いがおかしいですよね.修正します.
expected :: 1
result :: 2
succeeded in assert_not_equal.
となればOKです.
require 'colorize'
def assert_equal(expected, result)
if expected == result
puts 'true'.green
else
puts 'false'.red
end
end
assert_equal(1, 1)
assert_equal(1, 2)
整理:重複箇所の整理
重複している箇所は整理して,別立ての関数にしてください.
require 'colorize'
def assert_equal(expected, result)
if expected == result
puts 'true'.green
else
puts 'false'.red
end
end
assert_equal(1, 1)
assert_equal(1, 2)
補足:重複実行の予防
このcodeは今後繰り返し使っています.そのためには,requireで呼び出す必要があります.同じdirectoryに写(copy)して使うようにします.
例えば,
require './assert_equal'
assert_equal(2, 1*2)
assert_not_equal('bob', 'bob2')
というように使います.
しかし,今のままだとassert_equal.rbに書いたテストがそのまま実行されてしまいます.そこで,そういうのを回避してくれるidiom(熟語)があります.
if $PROGRAM_NAME == __FILE__
assert_equal(1, 1)
assert_equal(1, 2)
assert_not_equal(1, 2)
assert_not_equal(1, 1)
end
です.意味は,codeが書いてあるファイル名(FILE)が,動いているファイル名($PROGRAM_NAME)と一致したら中身を実行です.これはidiomなんで…覚えてください.あ,ここに書いてあるということをね.
require 'colorize'
def puts_vals(expected, result)
puts "expected :: #{expected}"
puts "result :: #{result}"
end
def assert_not_equal(expected, result)
puts_vals(expected, result)
print expected != result ?
"succeeded in #{__method__}.\n".green :
"failed in #{__method__}.\n".red
end
def assert_equal(expected, result)
puts_vals(expected, result)
print case expected == result
when true ; "succeeded in #{__method__}.\n".green
when false ; "failed in #{__method__}.\n".red
end
end
if $PROGRAM_NAME == __FILE__
assert_equal(1, 1)
assert_equal(1, 2)
assert_not_equal(1, 2)
assert_not_equal(1, 1)
end
- source ~/git_hub/ruby_docs/chart_style_ruby/c4_assert_equal.org