TDD テスト駆動開発 in 第4回勉強会@minami.rb
第4回勉強会@minami.rb に参加してきた。 http://qwik.jp/minamirb/57.html
その中での1セッション 『TDD テスト駆動開発入門』(by yalabさん)での課題が時間内に終わらなかったので復習をかねて最後までやり遂げる事に。ruby はそんなに書きなれていない事もあり、なかなか手間取ったがやっと課題の要件はみたす事ができたので、ここに晒しておく。 ruby ではそうじゃないよとか、普通はこうだよね。的なツッコミを入れていただけると有難いです。
時間がかかったポイントとしては ruby の実装不足。慣れてないのが大きいのかなと。 ただコーディングするだけならすぐかもしれないが、いかにrubyっぽく綺麗に書けるのだろうかと考えながらだったからのような気がします。実際このコードが rubyの暗黙の美的センスに乗っ取っているかどうかはわからないのですが、極力そうしたつもり。 for とか while とかでぐるぐるまわして if で条件分岐してどうたらとかいうのは、なるべくしたくないですし。
こういう積み重ねが大切ですね。 まぁ、とりあえずこんな感じで一旦アップしておきます。 ちょっと思うところがあるので、これに手を入れてすぐに第2版をアップしたいと思います。
課題 http://www.slideshare.net/yalab/ss-6749458 ・月末を返す last_day メソッドを作ってください。 ・第一週の日曜日 (先月の最後の日曜日かもしれない)を返すメソッドを作ってください。 ・最終週の土曜日(次月の最初の土曜日かもしれない)を返すメソッドを作ってください。 ・各週と各日を操作するeach_weekとeach_dayを作ってください。 ・月曜始まりと日曜始まりの両方を使えるようにしてください。
calendar.rb カレンダー
calendarTest.rb カレンダーのテストクラス これが重要。これのおかげで一旦完成した後も躊躇なくリファクタリングを進める事ができる。 常々思っている事なのだが、テストコードは人の為と云うよりも自分の安心の為に書くものだと思う。
実行結果
$ ruby calendarTest.rb
Loaded suite calendarTest
Started
................
Finished in 0.02391 seconds.
16 tests, 16 assertions, 0 failures, 0 errors
Calendar.rb
class Calendar attr_reader :first_day attr_reader :last_day attr_reader :base_cwday</p> <p>def initialize(year, month, base_cwday = "Sun") @first_day = Date.new(year, month, 1)</p> <h1>@last_day = (Date.new(year, month, 1) >> 1) - 1</h1> <pre><code>@last_day = (Date.new(year, month, -1)) @base_cwday = Date::ABBR_DAYNAMES.index(base_cwday) </code></pre> <p>end</p> <p># カレンダー表示上の最初の日を返す def display_first_day return @first_day - @first_day.cwday + @base_cwday end</p> <p># カレンダー表示上の最後の日を返す def display_last_day return @last_day + (6 - @last_day.cwday + @base_cwday) end</p> <p># 当月すべての日を週ごとに配列にして返す def each_week weeks = Array.new() display_first_day.step(display_last_day, 7) {|wd| week = Array.new() wd.step(wd + 6, 1) {|d| week < < d if first_day.month == d.month } weeks << week } return weeks end</p> <p># 当月すべての日を配列にして返す def each_day days = Array.new() @first_day.step(@last_day, 1) {|date| days << date } return days end end
CalendarTest
require 'test/unit' require 'date' require './calendar'</p> <p>class CalendarTest < Test::Unit::TestCase</p> <p># 基本パターン def test_first_day_201101 actual = Calendar.new(2011, 1) assert_equal Date.new(2011, 1, 1), actual.first_day end</p> <p># 固定値で返してないか別の月で確認 def test_first_day_201102 actual = Calendar.new(2011, 2) assert_equal Date.new(2011, 2, 1), actual.first_day end</p> <p># 日数 31日 def test_last_day_201101 actual = Calendar.new(2011, 1) assert_equal Date.new(2011, 1, 31), actual.last_day<br /> end</p> <p># 日数 28日 def test_last_day_201102 actual = Calendar.new(2011, 2) assert_equal Date.new(2011, 2, 28), actual.last_day<br /> end</p> <p># 日数 29日 def test_last_day_201002 actual = Calendar.new(2012, 2) assert_equal Date.new(2012, 2, 29), actual.last_day<br /> end</p> <p># 日数 30日 def test_last_day_201004 actual = Calendar.new(2010, 4) assert_equal Date.new(2010, 4, 30), actual.last_day end</p> <p>## display_first_sunday # カレンダー上の最初日曜が前月にあるパターン def test_display_first_day_feb feb = Calendar.new(2011, 2) assert_equal Date.new(2011, 1, 30), feb.display_first_day end</p> <p># カレンダー上の最初日曜が前月にあるパターン(月曜始まり) def test_display_first_day_feb_Mon feb = Calendar.new(2011, 2, "Mon") assert_equal Date.new(2011, 1, 31), feb.display_first_day puts feb.base_cwday end</p> <p># カレンダー上の最初日曜が前年前月にあるパターン def test_display_first_day_jan feb = Calendar.new(2011, 1) assert_equal Date.new(2010, 12, 26), feb.display_first_day end</p> <p>## display_last_saturday # カレンダー上の最終土曜が翌月にあるパターン2 def test_display_last_day_201101 actual = Calendar.new(2011, 1) assert_equal Date.new(2011, 2, 5), actual.display_last_day end</p> <p># カレンダー上の最終土曜が翌年翌月にあるパターン def test_display_last_day_201012 actual = Calendar.new(2010, 12) assert_equal Date.new(2011, 1, 1), actual.display_last_day end</p> <p># カレンダー上の最終土曜が翌年翌月にあるパターン(月曜始まり) def test_display_last_day_201012_mon actual = Calendar.new(2010, 12, "Mon") assert_equal Date.new(2011, 1, 2), actual.display_last_day end</p> <p># カレンダー上の最終日が当月にあるパターン def test_display_last_day_201104 actual = Calendar.new(2011, 4) assert_equal Date.new(2011, 4, 30), actual.display_last_day end</p> <p># カレンダー上の最終日が当月にあるパターン(月曜始まり) def test_display_last_day_201107_mon actual = Calendar.new(2011, 7, "Mon") assert_equal Date.new(2011, 7, 31), actual.display_last_day end</p> <p>def test_each_week actual = Calendar.new(2011, 1) expect = [ Array.new(1) { |i| i+1 }, Array.new(7) { |i| i+2 }, Array.new(7) { |i| i+9 }, Array.new(7) { |i| i+16 }, Array.new(7) { |i| i+23 }, Array.new(2) { |i| i+30 }, ] weeks = Array.new() expect.each { |e| week = Array.new() e.each { |d| week << Date.new(2011,1,d) } weeks << week } assert actual.each_week == weeks end</p> <p>def test_each_day actual = Calendar.new(2011, 1)</p> <pre><code>array = Array.new([]) (1..31).each { |day| array << Date.new(2011,1,day) } assert actual.each_day == array </code></pre> <p>end</p> <p>end