Table of Contents
Open Table of Contents
Koans とは
クイズ形式で Ruby を学ぶ Koans。その手法がなかなか凝っている。
- Learn Ruby with the EdgeCase Ruby Koans
ここでは上記からダウンロードできる 2010/12/23 日版を利用した。- edgecase/ruby_koans - GitHub
GitHub でソースは管理されている。
- edgecase/ruby_koans - GitHub
The goal is to learn the Ruby language, syntax, structure, and some common functions and libraries. We also teach you culture. Testing is not just something we pay lip service to, but something we live. It is essential in your quest to learn and do great things in the language.
Koans は Ruby 言語の文法、構造、そして、幾つかの共通関数やライブラリを学ぶことをゴールとしたもので、TDD の手法を用いてそれを実現している。
path_to_enlightenment.rb
というファイルを起動することで、あるテストケースがカルマにダメージを与えたとのメッセージが表示され、マスターから助言を授かることになる。
表示されるメッセージを頼りにテストケースをパスするように修正していくことで、次の新たな設問(新たなカルマへのダメージ)へと進み、30 ちょっとのカテゴリの計 272 問(2010/12/23 版)の設問をクリアすることで悟りをひらけることになる。
設問をクリアしていく過程は以下のようになる。
例えば 2 番目の設問は以下の通りとなっている。
マスターが「君はまだ悟りをひらいていない」と言っている。“The answers you seek…” ということで “This shoud be true — Please fix this” とある。
「please meditate on the following code:」ということで、about_asserts.rb:16:in
test_assert_with_message’` が指定されているので、該当ファイルの該当行を確認すると、
# Enlightenment may be more easily achieved with appropriate
# messages.
def test_assert_with_message
assert false, "This should be true -- Please fix this" # line: 16
end
assert
が false となっている。当然これではテストは通らないので、true に書き変えて保存する。
再度 path_to_enlightenment.rb
を起動してあげると、
$ ruby path_to_enlightenment.rb
AboutAsserts#test_assert_truth has expanded your awareness.
AboutAsserts#test_assert_with_message has expanded your awareness.
AboutAsserts#test_assert_equality has damaged your karma.
The Master says:
You have not yet reached enlightenment.
You are progressing. Excellent. 2 completed.
The answers you seek...
Failed assertion, no message given.
Please meditate on the following code:
/home/hoge/Dropbox/work/koans/about_asserts.rb:25:in `test_assert_equality'
learn the rules so you know how to break them properly
your path thus far [.X________________________________________________] 2/274
次の設問へと続く。
基本は、テストケースのアサーションの期待値を埋めていくことで設問に答えていくことになる。
メッセージ(“The ansers you seek…“)に既に答えが出てしまってはいるが、そこはじっくり読まずに、テストケースとテストメソッド名の方に集中して何を学ばせようとしているのか頭の片隅に置きながら期待値を考えていると、よく考えられた設問になっているなぁと感心してしまう。
最初の方こそ上記のようなホントに初歩的な設問だが、徐々に内容が濃くなってくるので、なかなか良い復習、勉強になる。
また、一気に 274 問実施するのは流石にキツイので、できる時間に少しづつ実施することが可能な作りになっているのもうれしい。何問目まで回答できているかは .path_progress
というファイルが覚えておいてくれているので、特に意識することなく、path_to_enlightenment.rb
を起動すれば前回の設問から続きを行うことができる。
watchr を使って回答に集中
設問に答えては path_to_enlightenment.rb
を起動するというのはメンドイ。
自動化しておく。
watchr gem を使うとファイルを監視下におき、編集された際に実行させたいことを定義することができる。
回答を記述するファイルを編集するたびに自動的に path_to_enlightenment.rb
が実行されるようにしておく。
watchr をインストールしていない場合はインストールしておく。
$ sudo gem install watchr
path_to_enlightenment.rb
と同じディレクトリに以下のファイルを用意しておく。
koans.watchr
:
def run
system("clear; ruby path_to_enlightenment.rb")
end
watch('.*\.rb$') { run }
run
watchr を起動しておく。
$ watchr koans.watchr
これで回答を行うファイルを編集する度にコンソールがリフレッシュされ path_to_enlightenment.rb
の結果を確認することができる。
triangle.rb
大半は assertion の期待値を埋めていくのだが、テストケースを通す為の関数を書く設問もある。
以下の 2 問。
- 設問その 1:
about_triangle_project.rb
class AboutTriangleProject < EdgeCase::Koan
def test_equilateral_triangles_have_equal_sides
assert_equal :equilateral, triangle(2, 2, 2)
assert_equal :equilateral, triangle(10, 10, 10)
end
def test_isosceles_triangles_have_exactly_two_sides_equal
assert_equal :isosceles, triangle(3, 4, 4)
assert_equal :isosceles, triangle(4, 3, 4)
assert_equal :isosceles, triangle(4, 4, 3)
assert_equal :isosceles, triangle(10, 10, 2)
end
def test_scalene_triangles_have_no_equal_sides
assert_equal :scalene, triangle(3, 4, 5)
assert_equal :scalene, triangle(10, 11, 12)
assert_equal :scalene, triangle(5, 4, 2)
end
end
- 設問その 2:
about_triangle_project_2.rb
class AboutTriangleProject2 < EdgeCase::Koan
# The first assignment did not talk about how to handle errors.
# Let's handle that part now.
def test_illegal_triangles_throw_exceptions
assert_raise(TriangleError) do triangle(0, 0, 0) end
assert_raise(TriangleError) do triangle(3, 4, -5) end
assert_raise(TriangleError) do triangle(1, 1, 3) end
assert_raise(TriangleError) do triangle(2, 4, 2) end
end
end
設問その 1 のテストの要件を満たす関数を用意し、かつ、設問その 2 の制約もパスする必要がある。
答えは提供されていない(見つけられなかった。。)ので、ベストアンサーかどうかはわからないが、以下の関数を書くことでテストをパスしている。
ツッコミありましたらご指摘願いたい。
triangle.rb
:
def triangle(a, b, c)
raise TriangleError.new if [a, b, c].any? { |e| e <= 0 }
raise TriangleError.new if ((a + b) <= c) || ((a + c) <= b) || ((b + c ) <= a)
case [a, b, c].uniq.size
when 1 then :equilateral
when 2 then :isosceles
else :scalene
end
end