Upgrade to Pro — share decks privately, control downloads, hide ads and more …

About TDD at Cookpad Summer Intern 2016 day1

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

About TDD at Cookpad Summer Intern 2016 day1

Avatar for MOROHASHI Kyosuke

MOROHASHI Kyosuke

August 12, 2016

More Decks by MOROHASHI Kyosuke

Other Decks in Programming

Transcript

  1. $ cd # お好きなところ $ mkdir clock # 好きな名前 $

    cd clock $ git init Bootstrap ‣ ৽͘͠ͳʹ͔Λ͢Δͱ͖͸ɺσΟϨΫτϦΛͭͬͯ͘
 ͙͢(JUͰ؅ཧ࢝͠ΊΔश׳Λ͚ͭ·͠ΐ͏ɻ 
  2. $ gem install bundler $ bundle init $ vim Gemfile

    ``` # frozen_string_literal: true # A sample Gemfile source "https://rubygems.org" gem "rspec" ``` $ bundle install $ git add . $ git commit -m 'bundle init' Bootstrap 
  3. $ bundle exec rspec --init $ git add . $

    git commit -m 'rspec --init' Bootstrap 
  4. $ vim spec/clock_spec.rb ``` describe 'Clock' do specify { expect(true).to

    be true } end ``` ``` $ bundle exec rspec spec/clock_spec.rb . Finished in 0.00097 seconds (files took 0.09778 seconds to load) 1 example, 0 failures ``` ࠷ॳͷҰา 
  5. ``` describe Clock do specify { expect(Clock).to be_an_instance_of(Class) } end

    ``` $ bundle exec rspec spec bundler: failed to load command: rspec 
 (/opt/brew/opt/rbenv/versions/2.3.0/bin/rspec) NameError: uninitialized constant Clock ClockΫϥεΛ࡞Γ͍ͨ → ·ͩͳ͍͔ΒΤϥʔʹͳΔ͸ͣ 
  6. $ mkdir lib $ vim lib/clock.rb ``` class Clock end

    ``` $ bundle exec rspec spec bundler: failed to load command: rspec 
 (/opt/brew/opt/rbenv/versions/2.3.0/bin/rspec) NameError: uninitialized constant Clock ClockΫϥεΛ࡞Δ → ಡΈࠐ·ͳ͍ͱࢀরͰ͖ͳ͍ͷ͸มΘΒͳ͍͸ͣ 
  7. ``` require 'clock' describe Clock do specify { expect(Clock).to be_an_instance_of(Class)

    } end ``` $ bundle exec rspec spec . Finished in 0.00462 seconds (files took 0.09435 seconds to load) 1 example, 0 failures require΋ͨ͠ˠ͜ΜͲͦ͜௨Δ͸ͣ 
  8. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -2,4 +2,10 @@ require 'clock'

    describe Clock do specify { expect(Clock).to be } + + context 'new(10, 20, 00)' do + let(:clock) { Clock.new(10, 20, 0) } + + specify { expect(clock.hour).to eq(10) } + end end ࣮श1: 5෼ ΠϯελϯεΛੜ੒͢Δςετ ‣ ࣮ߦલʹ ͜ͷςετΛ࣮ߦ͢ΔͱͲ͏ͳΓͦ͏͔ɺ༧૝͠ͳ͍͞ɻ ‣ ࣮ߦ͠ɺ݁ՌΛ֬ೝ͠ͳ͍͞ 
  9. $ bundle exec rspec .F Failures: 1) Clock new(10, 20,

    00) Failure/Error: let(:clock) { Clock.new(10, 20, 0) } ArgumentError: wrong number of arguments (given 3, expected 0) # ./spec/clock_spec.rb:7:in `initialize' # ./spec/clock_spec.rb:7:in `new' # ./spec/clock_spec.rb:7:in `block (3 levels) in <top (required)>' # ./spec/clock_spec.rb:9:in `block (3 levels) in <top (required)>' Finished in 0.00186 seconds (files took 0.08364 seconds to load) 2 examples, 1 failure Failed examples: rspec ./spec/clock_spec.rb:9 # Clock new(10, 20, 00) ੜ੒͢ΔςετˠίϯετϥΫλҾ਺͕ҧࣦͬͯഊ͢Δ͸ͣ 
  10. ``` --- a/lib/clock.rb +++ b/lib/clock.rb @@ -1,2 +1,8 @@ class

    Clock + def initialize(*args) + end + + def hour + 10 + end end ``` Fake it (Ծ࣮૷) 
  11. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -8,4 +8,10 @@ describe Clock

    do specify { expect(clock.hour).to eq(10) } end + + context 'new(12, 30, 00)' do + let(:clock) { Clock.new(12, 30, 0) } + + specify { expect(clock.hour).to eq(12) } + end end ࡾ֯ଌྔ (Triangulate) ‣ ࣦഊ͢ΔςετΛ௥Ճ͢Δ ‣ ͷςετ͕௨Δ··ɺͷςετΛ௨͢Α͏ͳɺ࠷௿ݶͷ࣮૷Λ ࡞Δ 
  12. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -1,8 +1,9 @@ class Clock

    - def initialize(*args) + def initialize(hour, *) + @hour = hour end def hour - 10 + @hour end end 12:30ͷςετΛ௨͢Α͏ͳɺ࠷௿ݶͷ࣮૷ 
  13. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -1,9 +1,8 @@ class Clock

    + attr_reader :hour + def initialize(hour, *) @hour = hour end - def hour - @hour - end end {ಈ࡞͢Δ && ͖Ε͍ͳ}ίʔυΛ໨ࢦͯ͠ 
  14. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -1,8 +1,6 @@ require 'clock'

    describe Clock do - specify { expect(Clock).to be_an_instance_of(Class) } - context 'new(10, 20, 00)' do let(:clock) { Clock.new(10, 20, 0) } ςετίʔυ΋ϦϑΝΫλϦϯά͢Δ 
  15. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -5,6 +5,8 @@ describe Clock

    do let(:clock) { Clock.new(10, 20, 0) } specify { expect(clock.hour).to eq(10) } + specify { expect(clock.min).to eq(20) } + specify { expect(clock.sec).to eq(0) } end context 'new(12, 30, 00)' do ෼ͱඵʹର͢Δςετˠ#hour, #minϝιου͕ͳ͍ͷͰࣦഊ͢Δ͸ͣ 
  16. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -1,8 +1,10 @@ class Clock

    - attr_reader :hour + attr_reader :hour, :min, :sec - def initialize(hour, *) + def initialize(hour, min, sec) @hour = hour + @min = min + @sec = sec end end ໌നͳ࣮૷ (Obvious Implementation) 
  17. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -14,4 +14,9 @@ describe Clock

    do specify { expect(clock.hour).to eq(12) } end + + context 'new(12, 30, 60)' do + specify { expect { Clock.new(12, 30, 60) }.to raise_error(ArgumentError) } + end + end ࣮श2: 15෼ ҎԼͷςετΛ࡞੒͠ɺࣦഊΛ֬ೝͨ͠͏͑Ͱ࣮૷͠ͳ͍͞ 
  18. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -2,6 +2,10 @@ class Clock

    attr_reader :hour, :min, :sec def initialize(hour, min, sec) + if (hour >= 24) || (min >= 60) || (sec >= 60) + raise ArgumentError + end + @hour = hour @min = min @sec = sec ਖ਼ͷ਺ͷൣғ֎͚ͩͰΤϥʔʹͳΔ 
  19. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -19,4 +19,7 @@ describe Clock

    do specify { expect { Clock.new(12, 30, 60) }.to raise_error(ArgumentError) } end + context 'new(-12, 30, 59)' do + specify do + expect { Clock.new(-12, 30, 59) }. + to raise_error(ArgumentError) + end + end end ࣮श3ͷςετΛ࢖ͬͯࡾ֯ଌྔ͢Δ 
  20. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -2,7 +2,7 @@ class Clock

    attr_reader :hour, :min, :sec def initialize(hour, min, sec) - if (hour >= 24) || (min >= 60) || (sec >= 60) + if (hour < 0 || hour >= 24) || (min < 0 || min >= 60) 
 || (sec < 0 || sec >= 60) raise ArgumentError end ࣮श2͕άϦʔϯͳ··ɺ࣮श3͕௨Δ࠷௿ݶͷίʔυ 
  21. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -2,13 +2,19 @@ class Clock

    attr_reader :hour, :min, :sec def initialize(hour, min, sec) - if (hour < 0 || hour >= 24) || (min < 0 || min >= 60) || (sec < 0 || sec >= 60) + @hour = verify_valid_clock_input(hour, 24) + @min = verify_valid_clock_input(min, 60) + @sec = verify_valid_clock_input(sec, 60) + end + + private + + def verify_valid_clock_input(val, max) + if (0...max).include?(val) + val + else raise ArgumentError end - - @hour = hour - @min = min - @sec = sec end ϦϑΝΫλϦϯάྫ 
  22. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -22,4 +22,11 @@ describe Clock

    do context 'new(-12, 30, 59)' do specify { expect { Clock.new(-12, 30, 59) }.to raise_error(ArgumentError) } end + + describe '#to_time' do + let(:clock) { Clock.new(10, 20, 0) } + let(:time) { clock.to_time(Date.today) } + + specify { + expect(time.iso8601).to eq ‘2016-08-12T10:20:00+09:00' + } + end end APIΛߟ͑Δ #to_time(<#Date>)͕ૉ௚ͦ͏ˠ#to_timeͷ࣮૷ͳ͍ 
  23. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -7,6 +7,10 @@ class Clock

    @sec = varify_valid_clock_input(sec, 60) end + def to_time(date) + Time.local(2016, 6, 22, 10, 20) + end + private def varify_valid_clock_input(val, max) ճ౴ྫ: Ծ࣮૷ 
  24. ‣ ࣍ͷ೔࣌ɺલͷ೔࣌Λಋग़Ͱ͖Δ ‣ ͖ΐ͏ͷ 10:20 ͸ 2016-08-12T10:20:00 JST ‣ 8/1ͷ

    10:20 ͸ 2016-08-01T10:20:00 JST ࡾ֯ଌྔͷexampleΛ۩ମԽ 
  25. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -25,8 +25,16 @@ describe Clock

    do describe '#to_time' do let(:clock) { Clock.new(10, 20, 0) } - let(:time) { clock.to_time(Date.today) } + context '(Date.today)' do + let(:time) { clock.to_time(Date.today) } - specify { expect(time.iso8601).to eq '2016-06-22T10:20:00+09:00' } + specify { expect(time.iso8601).to eq '2016-06-22T10:20:00+09:00' } + end + + context '(2016-08-01)' do + let(:time) { clock.to_time(Date.new(2016, 8, 1)) } + + specify { expect(time.iso8601).to eq '2016-08-01T10:20:00+09:00' } + end end end ࡾ֯ଌྔ 
  26. --- a/lib/clock.rb +++ b/lib/clock.rb @@ -8,7 +8,7 @@ class Clock

    end def to_time(date) - Time.local(2016, 6, 22, 10, 20) + Time.local(date.year, date.month, date.day, @hour, @min, @sec) end private ࡾ֯ଌྔ 
  27. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -26,7 +26,7 @@ describe Clock

    do describe '#to_time' do let(:clock) { Clock.new(10, 20, 0) } context '(Date.today)' do - let(:time) { clock.to_time(Date.today) } + let(:time) { clock.to_time(Date.new(2016, 6, 22)) } specify { expect(time.iso8601).to eq '2016-06-22T10:20:00+09:0 end ςετίʔυͷվળ: ֎෦ґଘ஋Λແ͘͢ 
  28. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -1,12 +1,12 @@ require 'clock'

    describe Clock do - context 'new(10, 20, 00)' do - let(:clock) { Clock.new(10, 20, 0) } + let(:clock_10_20) { Clock.new(10, 20, 0) } - specify { expect(clock.hour).to eq 10 } - specify { expect(clock.min).to eq 20 } - specify { expect(clock.sec).to eq 0 } + context 'new(10, 20, 00)' do + specify { expect(clock_10_20.hour).to eq 10 } + specify { expect(clock_10_20.min).to eq 20 } + specify { expect(clock_10_20.sec).to eq 0 } end context 'new(12, 30, 00)' do @@ -24,17 +24,20 @@ describe Clock do end describe '#to_time' do - let(:clock) { Clock.new(10, 20, 0) } context '(Date.today)' do - let(:time) { clock.to_time(Date.new(2016, 6, 22)) } + let(:time) { clock_10_20.to_time(Date.new(2016, 6, 22)) } specify { expect(time.iso8601).to eq '2016-06-22T10:20:00+09:00' } end context '(2016-08-01)' do - let(:time) { clock.to_time(Date.new(2016, 8, 1)) } + let(:time) { clock_10_20.to_time(Date.new(2016, 8, 1)) } specify { expect(time.iso8601).to eq '2016-08-01T10:20:00+09:00' } end end ͷɺલʹRefactoring: 
  29. describe Clock do - context 'new(10, 20, 00)' do -

    let(:clock) { Clock.new(10, 20, 0) } + let(:clock_10_20) { Clock.new(10, 20, 0) } - specify { expect(clock.hour).to eq 10 } - specify { expect(clock.min).to eq 20 } - specify { expect(clock.sec).to eq 0 } + context 'new(10, 20, 00)' do + specify { expect(clock_10_20.hour).to eq 10 } + specify { expect(clock_10_20.min).to eq 20 } + specify { expect(clock_10_20.sec).to eq 0 } Refactoring: ‣ `Clock.new(10, 20, 0)`͕සग़͢ΔͷͰɺ໊લΛ͚ͭͯɺ·ͱΊΔ ‣ ςετίʔυ಺ͷ৘ใྔ͕૿͑Δ ‣ νϟϯΫԽ͢Δ͜ͱʹΑΓɺϓϩάϥϚ͕֮͑Δ͜ͱ͕ݮΔ 
  30. --- a/spec/clock_spec.rb +++ b/spec/clock_spec.rb @@ -37,7 +37,9 @@ describe Clock

    do end end + describe '#next_time(time)' do + let(:time) { Time.local(2016, 8, 11, 12, 30) } + specify { + expect(clock_10_20.next_time(time).iso8601).to \ + eq ‘2016-08-12T10:20:00+09:00' + } end end ·ͣ͸RED→ #next_time()͕ͳ͍͔ΒNME