テスト駆動開発 TDDという開発手法を使いつつ動的プログラミング言語 Rubyを学ぶ
ローカル環境にダウンロードして実際にファイルを触りつつ動かしたほうが実際の感触やエラーメッセージ等が勉強になります。
(ウェブサイトのオンライン上でも学べますが穴埋め問題だけで終わってしまいます。)
中を見てもらえればわかりますが、 Rubyの問題自体は非常に簡単な初心者レベルから始まっています。
たのしいRuby等の入門書をひと通り読んでからこの問題を解いていくと実際の動きがよくわかると思います。
環境設定 テストファイル&ツール&その他
端末から TDDを自動実行できるように設定して、エディタから Rubyを保存自動実行できるように設定します。
- Rubyのインストール
- Ruby学習用のテストファイル
- エディタ( sublime text3を推奨 )
Ruby
Rubyのインストール
https://www.ruby-lang.org/ja/installation/
Ruby学習用のテストファイル
[Learn Ruby WITH THE NEO RUBY KOANS
http://rubykoans.com/]
(http://rubykoans.com/)
TDDで書かれた Ruby学習用のファイルをダウンロードできます。
(右上のDOWNLOAD THE KOANSボタンでダウンロード後、 Rubyのパスが通っている場所に解凍します。)
エディタ
sublime text3を推奨
http://www.sublimetext.com/3
ソースコードを書くのに特化しているエディタです、 Rubyの実行やハイライト、プロジェクト管理、プラグイン等の便利機能が沢山あります。
エディタは好きな物を使って大丈夫ですが、sublime text3は Rubyの小さな動作確認を簡単にできるのでお勧めです。
(動作確認は人によって端末からirbやPry等を利用する事も。)
sublime text3はビルド(ctrl+b)で Rubyファイルを実行できます。
sublime text3はディレクトリをドラッグアンドドロップするとプロジェクトとして開いてくれます。
Package Control
https://sublime.wbond.net/installation#st3
(sublime text3でプラグインを利用する場合パッケージコントロールをインストールする必要があります。)
SublimeTextの教科書で紹介されてるプラグインまとめ - Qiita
SublimeOnSaveBuild
sublime text3のプラグインSublimeOnSaveBuildを利用すると
ファイルを保存(ctrl+s)するとビルドも同時に実行できます。
sublime text2用とあるがsublime text3でも利用できます。
ユーザー設定(*.rbファイルが保存されたらビルド)
{
"filename_filter": "\\.(rb)$",
"build_on_save": 1
}
ファイルを監視して自動実行するgem:watchr
インストール
gem install watchr
学習時に開けておくウィンドウ
エディタ:ソースコードを触る。
端末:自動化のコマンドによって TDDの実行結果を自動表示してくれる。修正したテストファイルを保存毎に再実行されます。
メソッド検索
メソッド等動作の分からない時に検索します。
るりまサーチ
http://docs.ruby-lang.org/ja/search/
Rubyリファレンス
http://ref.xaio.jp/ruby
3種類の実行方法
端末からrubyコマンドを打ちます。
- テストファイル単位で実行する方法。(1つづつ確かめたい場合)
ruby 指定されたテストファイル名
例:
ruby about_asserts.rb
- 全部の問題を最初からを学習していく方法。
ruby path_to_enlightenment.rb
- 2番めのコマンドを自動実行させる方法
主にこれを使って学習していきます。
watchr koans.watchr
(gem watchrのインストールが必要)
watch( '.*\.rb' ) do
system 'rake'
end
koans.watchrの中を見ると Rubyファイルを監視しているのがわかります。
このコマンドを実行しておく事で、手動でテストファイルを修正してから Rubyコマンドを実行するという繰り返しが自動化されます。
その他
分散バージョン管理 git(参考サイト:サルでもわかる git入門)を利用する方法を **更に学習するためには・・**に追記しました。
( ruby言語だけ学習する場合は必要ありません。)
準備完了
実際の学習方法
- 鉄則 TDDではコードとテストを同時に書き換えてはいけません。
最初のテストファイル (about_asserts.rb)
このテストファイルには TDDの基本が詰まっています。
最初の実行結果画面
AboutAsserts#test_assert_truth has damaged your karma.
(テストはあなたのカルマにダメージを与えました。)
The Master says:
(マスターが言うには)
You have not yet reached enlightenment.
Do not lose hope.
(あなたはまだ悟りを開いていない、しかし希望を失ってはいけない)
The answers you seek...
(あなたが探す答えは・・・)
Failed assertion.
(assertionが失敗している)
Please meditate on the following code:
(次のコードの場所を見てください)
/home/hi/Documents/koans/about_asserts.rb:10:in `test_assert_truth'
(about_asserts.rb 10行目のtest_assert_truth部分)
mountains are merely mountains
your path thus far
[X_________________________________________________] 0/282
(あなたのゴールまでの距離、282問題のうち0問が終わりました。)
最初のテストファイル(about_asserts.rb)では TDDの基本的な動きを学ぶ。
基礎知識:
- def メソッド名 ~ end
Rubyのメソッドを定義する文法
この間にメソッド内容を書きます。
- メソッド名の後ろに?が付く場合
これは真偽値を判断するメソッドになります、答えはtrueかfalseになります。
例) is_a? この部分が真偽値を判断するメソッドになります。
- true 真値
- false 偽値
- nil オブジェクトが存在しない
- #の後ろはコメントになります。
- assert 条件を評価
- expected_value 期待する値
- actual_value 実際の値や数式
8行目~
# We shall contemplate truth by testing reality, via asserts.
def test_assert_truth
assert false # This should be true
end
We shall contemplate truth by testing reality, via asserts.
(assertを通して、我々はテストが通るためのtruthを考えます。)
This should be true
(ここはtrueであるべき)
- test_assert_truth (メソッド名がヒントや問題文になっている。)
10行目の assert falseを assert trueに書き換える。
↓ 回答
# We shall contemplate truth by testing reality, via asserts.
def test_assert_truth
assert true # This should be true
end
テストに成功すると1問終了、1/282になっています。
基本的にテスト文の修正や、”__”、”n”(=数字)部分に答えを書き込みます。
回答例
13行目~
# Enlightenment may be more easily achieved with appropriate
# messages.
def test_assert_with_message
assert false, "This should be true -- Please fix this"
end
↓ 回答
# Enlightenment may be more easily achieved with appropriate
# messages.
def test_assert_with_message
assert true, "This should be true -- Please fix this"
end
19行目~
# To understand reality, we must compare our expectations against
# reality.
def test_assert_equality
expected_value = __
actual_value = 1 + 1
assert expected_value == actual_value
end
↓ 回答
# To understand reality, we must compare our expectations against
# reality.
def test_assert_equality
expected_value = 2
actual_value = 1 + 1
assert expected_value == actual_value
end
28行目~
# Some ways of asserting equality are better than others.
def test_a_better_way_of_asserting_equality
expected_value = __
actual_value = 1 + 1
assert_equal expected_value, actual_value
end
↓ 回答
# Some ways of asserting equality are better than others.
def test_a_better_way_of_asserting_equality
expected_value = 2
actual_value = 1 + 1
assert_equal expected_value, actual_value
end
36行目~
# Sometimes we will ask you to fill in the values
def test_fill_in_values
assert_equal __, 1 + 1
end
↓ 回答
# Sometimes we will ask you to fill in the values
def test_fill_in_values
assert_equal 2, 1 + 1
end
最初のテストファイル(about_asserts.rb)を全問終わらせた結果。
次のテストファイルはabout_nil.rbを見るように指示されています。
2番目のテストファイル(about_nil.rb)
2番目のテストファイルから本格的に Rubyを学習していきます。
about_nil.rb:5:in `test_nil_is_an_object'
about_nil.rbファイルの5行目のメソッドtest_nil_is_an_objectを見るように指示されています。
4行目~
def test_nil_is_an_object
assert_equal __, nil.is_a?(Object), "Unlike NULL in other languages"
end
↓
5行目の一部分を抜き出し
assert_equal __, nil.is_a?(Object)
メソッド検索をしたり、
るりまサーチ is_a?
Rubyリファレンス is_a?
一部を抜き出して、test.rb(新規に作成した空ファイル)
p nil.is_a?(Object)
を実行すると答えがわかる。
それでも答えがわからなかったら、例えば上記の問題の場合、test_nil_is_an_objectメソッドをネット検索すると誰かが答えをアップしたものが見つかるかもしれません。
この繰り返しで全282問(2014年6月3日現在)を終わらせます。
追記:更に高度な学習をするために・・・
追記にしたのは Ruby1問当たり数秒から数分で解けるので、1問毎に gitを使うには手間が掛かり過ぎるので、1テストファイル当たり終わったタイミングで良いかもしれません。
(実際の TDDでは1つのテストごとに gitを使っていきます)
実際の TDDを真似てみる。
本来の TDDは gitを利用しつつ
- テストを書く
- REDを確認
- ソースを書く
- GREENを確認
- ( gitでコミット)
- リファクタリング
- ( gitでコミット)
のように繰り返していきます。
TDDは図のようなサイクルで回しながら開発していく。
(一日の区切りでは REDで終わる、次の日に再開する場所をわかりやすくするため)
この Rubyの勉強も TDDのように繰り返し行なって TDDのリズムを掴むのに良い練習となる。
- 問題を見る(=テストを書く)
- REDを確認
- 問題を解く(=ソースを書く)
- GREENを確認
- ( gitでコミット)
( 実際の TDDと違い、テストを書いたり、ソースを書いたり、 リファクタリングが無い。)
gitで覚える事、やってみる事。
gitでブランチを切る。
gitでテストファイルごとにブランチを作る。
テストファイルが終了する毎にmasterにマージする。
マージした時にコンフリクトが発生した時の対処を覚える。
テストファイルの開始時と終了時のdiffを取る。
解答例
about_triangle_project.rb はtriangleメソッドを書く問題。
152~154問目
自分が書いたtriangleメソッド
def triangle(a, b, c)
if a==b && b==c && a==c
return :equilateral
end
if a==b || b==c || a==c
return :isosceles
end
if (a + b)>c || (b + c)>a || (a + c)>b
return :scalene
end
end
ネット検索で見つけた上手いtriangleメソッド
def triangle(a, b, c)
sides = [a, b, c].sort
return :false if sides[0] <= 0 or sides[0] + sides[1] <= sides[2]
case sides.uniq.size
when 1
:equilateral
when 2
:isosceles
else
:scalene
end
end
追記(2014年6月6日):koansの解答をアップしました。
完走したので、自力とネット検索を使いつつ解いた答えをgithubにあげてみました。
github: masakinihirota/answer_koans
https://github.com/masakinihirota/answer_koans
(test.rbは sublime text3で動作確認をしたもので、それ以外特に意味はありません。)