アーカイブ

2011 年 2 月 のアーカイブ

TDD テスト駆動開発 in 第4回勉強会@minami.rb

2011 年 2 月 3 日 件のコメント

第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 &lt; &lt; d if first_day.month == d.month
      }
      weeks &lt;&lt; week
    }
    return weeks
  end</p>

<p># 当月すべての日を配列にして返す
  def each_day
    days = Array.new()
    @first_day.step(@last_day, 1) {|date|
      days &lt;&lt; date
    }
    return days
  end
end

CalendarTest

require 'test/unit'
require 'date'
require './calendar'</p>

<p>class CalendarTest  &lt; 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 &lt;&lt; Date.new(2011,1,d)
      }
      weeks &lt;&lt; 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 &lt;&lt; Date.new(2011,1,day)
}
assert actual.each_day == array
</code></pre>

<p>end</p>

<p>end

カテゴリー: 未分類 タグ: , ,