diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 000000000..2fbf0ffd7 --- /dev/null +++ b/.bundle/config @@ -0,0 +1 @@ +--- {} diff --git a/.replit b/.replit new file mode 100644 index 000000000..311bf648c --- /dev/null +++ b/.replit @@ -0,0 +1,6 @@ + + +run="git status \n git checkout -b adding-unit-tests \n git add . \n git commit -m 'adding some unit tests' \n git push origin adding-unit-tests" + + + diff --git a/.rspec b/.rspec new file mode 100644 index 000000000..83e16f804 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--require spec_helper diff --git a/00_hello/hello.rb b/00_hello/hello.rb new file mode 100644 index 000000000..9f422fdcb --- /dev/null +++ b/00_hello/hello.rb @@ -0,0 +1,9 @@ +#write your code here +def hello + return "Hello!" +end + + +def greet(who) + return "Hello, #{who}!" +end diff --git a/00_hello/hello_spec.rb b/00_hello/hello_spec.rb index 26075944a..9053a012d 100644 --- a/00_hello/hello_spec.rb +++ b/00_hello/hello_spec.rb @@ -6,7 +6,7 @@ # # cd 00_hello # -# This directory is the starting point for this exercise. It contains a spec file and you'll be adding a ruby file to (eventually) make the specs pass. +# This directory is the starting point for this exercise. It contains a spec file and a ruby file to (eventually) make the specs pass. # # ## Run the test # @@ -14,21 +14,7 @@ # # ## Watch it fail # -# You should see an error. **Don't get scared!** Try to read it and figure out what the computer wants to tell you. Somewhere on the first line it should say something like -# -# cannot load such file -- test-first-teaching/hello/hello (LoadError) -# -# That means that it is looking for a file called `hello.rb` and can't find it. -# -# ## Create hello.rb -# -# Open up `hello.rb` in a text editor. Save it. Run the test again. -# -# rake -# -# ## Watch it fail -# -# Now you should see an error like this: +# you should see an error like this: # # the hello function # says hello (FAILED - 1) diff --git a/00_hello/index.html b/00_hello/index.html index e4eb3d6b8..2261bffcf 100644 --- a/00_hello/index.html +++ b/00_hello/index.html @@ -17,17 +17,8 @@

learn_ruby

  • 02 Calculator
  • 03 Simon Says
  • 04 Pig Latin
  • -
  • 05 Silly Blocks
  • -
  • 06 Performance Monitor
  • -
  • 07 Hello Friend
  • -
  • 08 Book Titles
  • -
  • 09 Timer
  • -
  • 10 Temperature Object
  • -
  • 11 Dictionary
  • -
  • 12 Rpn Calculator
  • -
  • 13 Xml Document
  • -
  • 14 Array Extensions
  • -
  • 15 In Words
  • +
  • 05 Book Titles
  • +
  • 06 Timer
  • hello

    @@ -40,7 +31,7 @@

    Open a terminal in this directory

    cd 00_hello
     
    -

    This directory is the starting point for this exercise. It contains a spec file and you'll be adding a ruby file to (eventually) make the specs pass.

    +

    This directory is the starting point for this exercise. It contains a spec file and a ruby file to (eventually) make the specs pass.

    Run the test

    @@ -49,23 +40,7 @@

    Run the test

    Watch it fail

    -

    You should see an error. Don't get scared! Try to read it and figure out what the computer wants to tell you. Somewhere on the first line it should say something like

    - -
    cannot load such file -- test-first-teaching/hello/hello (LoadError)
    -
    - -

    That means that it is looking for a file called hello.rb and can't find it.

    - -

    Create hello.rb

    - -

    Open up hello.rb in a text editor. Save it. Run the test again.

    - -
    rake
    -
    - -

    Watch it fail

    - -

    Now you should see an error like this:

    +

    you should see an error like this:

    the hello function
       says hello (FAILED - 1)
    diff --git a/01_temperature/index.html b/01_temperature/index.html
    index fc87b405d..19f126a96 100644
    --- a/01_temperature/index.html
    +++ b/01_temperature/index.html
    @@ -17,17 +17,8 @@ 

    learn_ruby

  • 02 Calculator
  • 03 Simon Says
  • 04 Pig Latin
  • -
  • 05 Silly Blocks
  • -
  • 06 Performance Monitor
  • -
  • 07 Hello Friend
  • -
  • 08 Book Titles
  • -
  • 09 Timer
  • -
  • 10 Temperature Object
  • -
  • 11 Dictionary
  • -
  • 12 Rpn Calculator
  • -
  • 13 Xml Document
  • -
  • 14 Array Extensions
  • -
  • 15 In Words
  • +
  • 05 Book Titles
  • +
  • 06 Timer
  • temperature

    diff --git a/01_temperature/temperature.rb b/01_temperature/temperature.rb new file mode 100644 index 000000000..184dbb27e --- /dev/null +++ b/01_temperature/temperature.rb @@ -0,0 +1,8 @@ +def ftoc (temp) + + return ((temp - 32) * 5/9).to_f +end + +def ctof (temp) + return (temp.to_f * 9/5 + 32.0) +end \ No newline at end of file diff --git a/01_temperature/temperature_spec.rb b/01_temperature/temperature_spec.rb index 7e92a54dc..f206c4c03 100644 --- a/01_temperature/temperature_spec.rb +++ b/01_temperature/temperature_spec.rb @@ -18,9 +18,7 @@ require "temperature" describe "temperature conversion functions" do - describe "#ftoc" do - it "converts freezing temperature" do expect(ftoc(32)).to eq(0) end @@ -36,11 +34,9 @@ it "converts arbitrary temperature" do expect(ftoc(68)).to eq(20) end - end describe "#ctof" do - it "converts freezing temperature" do expect(ctof(0)).to eq(32) end @@ -61,7 +57,5 @@ # and http://en.wikipedia.org/wiki/Double_precision_floating-point_format # Also, try "puts 0.5 - 0.4 - 0.1" -- pretty crazy, right? end - end - end diff --git a/02_calculator/calculator.rb b/02_calculator/calculator.rb new file mode 100644 index 000000000..8f52a07c7 --- /dev/null +++ b/02_calculator/calculator.rb @@ -0,0 +1,39 @@ +def add (num1, num2) + return num1 + num2 +end + +def subtract (num1, num2) + return num1 - num2 +end + +def sum (arr) + total = 0 + arr.each do | item | + total += item + end + return total +end + +def multiply(arr) + product = 1 + arr.each do |item| + product *= item + end + return product +end + +def power(num1, num2) + return num1 ** num2 +end + +def factorial (num) + fact = 1 + + +while num > 0 + fact *= num + num -= 1 + end + + return fact +end \ No newline at end of file diff --git a/02_calculator/calculator_spec.rb b/02_calculator/calculator_spec.rb index fef7e9d00..acd83657e 100644 --- a/02_calculator/calculator_spec.rb +++ b/02_calculator/calculator_spec.rb @@ -9,7 +9,7 @@ # # you will build a simple calculator script with the following methods: # -# `add` takes two parameters and adds them +# `add` takes two parameters and adds them I # # `subtract` takes two parameters and subtracts the second from the first # @@ -37,21 +37,21 @@ describe "add" do it "adds 0 and 0" do - expect(add(0,0)).to eq(0) + expect(add(0, 0)).to eq(0) end it "adds 2 and 2" do - expect(add(2,2)).to eq(4) + expect(add(2, 2)).to eq(4) end it "adds positive numbers" do - expect(add(2,6)).to eq(8) + expect(add(2, 6)).to eq(8) end end describe "subtract" do it "subtracts numbers" do - expect(subtract(10,4)).to eq(6) + expect(subtract(10, 4)).to eq(6) end end @@ -65,11 +65,11 @@ end it "computes the sum of an array of two numbers" do - expect(sum([7,11])).to eq(18) + expect(sum([7, 11])).to eq(18) end it "computes the sum of an array of many numbers" do - expect(sum([1,3,5,7,9])).to eq(25) + expect(sum([1, 3, 5, 7, 9])).to eq(25) end end @@ -78,22 +78,37 @@ # write tests and code for the following: describe "#multiply" do + it "multiplies two numbers" do + expect(multiply([2, 3])).to eq(6) + end - it "multiplies two numbers" - - it "multiplies several numbers" - + it "multiplies several numbers" do expect(multiply([5, 3, 4, 2, 1])).to eq(120) end end describe "#power" do - it "raises one number to the power of another number" + it "raises one number to the power of another number" do + expect(power(3, 2)).to eq(9) + end end # http://en.wikipedia.org/wiki/Factorial describe "#factorial" do - it "computes the factorial of 0" - it "computes the factorial of 1" - it "computes the factorial of 2" - it "computes the factorial of 5" - it "computes the factorial of 10" + it "computes the factorial of 0" do + expect(factorial(0)).to eq(1) + end + + it "computes the factorial of 1" do + expect(factorial(1)) .to eq(1) + end + + it "computes the factorial of 2" do + expect(factorial(2)) .to eq(2) + end + it "computes the factorial of 5" do + expect(factorial(5)) + .to eq(120) + end + it "computes the factorial of 10" do + expect(factorial(10)) .to eq(3628800) + end end diff --git a/02_calculator/index.html b/02_calculator/index.html index b8c612f4e..2da3ed49e 100644 --- a/02_calculator/index.html +++ b/02_calculator/index.html @@ -17,17 +17,8 @@

    learn_ruby

  • 02 Calculator
  • 03 Simon Says
  • 04 Pig Latin
  • -
  • 05 Silly Blocks
  • -
  • 06 Performance Monitor
  • -
  • 07 Hello Friend
  • -
  • 08 Book Titles
  • -
  • 09 Timer
  • -
  • 10 Temperature Object
  • -
  • 11 Dictionary
  • -
  • 12 Rpn Calculator
  • -
  • 13 Xml Document
  • -
  • 14 Array Extensions
  • -
  • 15 In Words
  • +
  • 05 Book Titles
  • +
  • 06 Timer
  • calculator

    diff --git a/03_simon_says/index.html b/03_simon_says/index.html index 74de726a0..9defe81ea 100644 --- a/03_simon_says/index.html +++ b/03_simon_says/index.html @@ -17,17 +17,8 @@

    learn_ruby

  • 02 Calculator
  • 03 Simon Says
  • 04 Pig Latin
  • -
  • 05 Silly Blocks
  • -
  • 06 Performance Monitor
  • -
  • 07 Hello Friend
  • -
  • 08 Book Titles
  • -
  • 09 Timer
  • -
  • 10 Temperature Object
  • -
  • 11 Dictionary
  • -
  • 12 Rpn Calculator
  • -
  • 13 Xml Document
  • -
  • 14 Array Extensions
  • -
  • 15 In Words
  • +
  • 05 Book Titles
  • +
  • 06 Timer
  • simon_says

    diff --git a/03_simon_says/simon_says.rb b/03_simon_says/simon_says.rb new file mode 100644 index 000000000..251797306 --- /dev/null +++ b/03_simon_says/simon_says.rb @@ -0,0 +1 @@ +#write your code here diff --git a/04_pig_latin/index.html b/04_pig_latin/index.html index b40830700..05e6c91bf 100644 --- a/04_pig_latin/index.html +++ b/04_pig_latin/index.html @@ -17,17 +17,8 @@

    learn_ruby

  • 02 Calculator
  • 03 Simon Says
  • 04 Pig Latin
  • -
  • 05 Silly Blocks
  • -
  • 06 Performance Monitor
  • -
  • 07 Hello Friend
  • -
  • 08 Book Titles
  • -
  • 09 Timer
  • -
  • 10 Temperature Object
  • -
  • 11 Dictionary
  • -
  • 12 Rpn Calculator
  • -
  • 13 Xml Document
  • -
  • 14 Array Extensions
  • -
  • 15 In Words
  • +
  • 05 Book Titles
  • +
  • 06 Timer
  • pig_latin

    diff --git a/04_pig_latin/pig_latin.rb b/04_pig_latin/pig_latin.rb new file mode 100644 index 000000000..251797306 --- /dev/null +++ b/04_pig_latin/pig_latin.rb @@ -0,0 +1 @@ +#write your code here diff --git a/05_book_titles/book.rb b/05_book_titles/book.rb new file mode 100644 index 000000000..009f2643e --- /dev/null +++ b/05_book_titles/book.rb @@ -0,0 +1,3 @@ +class Book +# write your code here +end diff --git a/08_book_titles/book_titles_spec.rb b/05_book_titles/book_titles_spec.rb similarity index 100% rename from 08_book_titles/book_titles_spec.rb rename to 05_book_titles/book_titles_spec.rb diff --git a/08_book_titles/index.html b/05_book_titles/index.html similarity index 80% rename from 08_book_titles/index.html rename to 05_book_titles/index.html index b5da4af8e..3412f8363 100644 --- a/08_book_titles/index.html +++ b/05_book_titles/index.html @@ -17,17 +17,8 @@

    learn_ruby

  • 02 Calculator
  • 03 Simon Says
  • 04 Pig Latin
  • -
  • 05 Silly Blocks
  • -
  • 06 Performance Monitor
  • -
  • 07 Hello Friend
  • -
  • 08 Book Titles
  • -
  • 09 Timer
  • -
  • 10 Temperature Object
  • -
  • 11 Dictionary
  • -
  • 12 Rpn Calculator
  • -
  • 13 Xml Document
  • -
  • 14 Array Extensions
  • -
  • 15 In Words
  • +
  • 05 Book Titles
  • +
  • 06 Timer
  • book_titles

    diff --git a/05_silly_blocks/index.html b/05_silly_blocks/index.html deleted file mode 100644 index ada51229b..000000000 --- a/05_silly_blocks/index.html +++ /dev/null @@ -1,115 +0,0 @@ - - - Test-First Teaching: learn_ruby: silly_blocks - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    silly_blocks

    -

    Topics

    - -
      -
    • blocks
    • -
    • closures
    • -
    • yield
    • -
    • loops
    • -
    - -
    -
    -

    Tests

    -silly_blocks_spec.rb -
    -require "silly_blocks"
    -
    -describe "some silly block functions" do
    -
    -  describe "reverser" do
    -    it "reverses the string returned by the default block" do
    -      result = reverser do
    -        "hello"
    -      end
    -      expect(result).to eq("olleh")
    -    end
    -
    -    it "reverses each word in the string returned by the default block" do
    -      result = reverser do
    -        "hello dolly"
    -      end
    -      expect(result).to eq("olleh yllod")
    -    end
    -  end
    -
    -  describe "adder" do
    -    it "adds one to the value returned by the default block" do
    -      expect(adder do
    -        5
    -      end).to eq(6)
    -    end
    -
    -    it "adds 3 to the value returned by the default block" do
    -      expect(adder(3) do
    -        5
    -      end).to eq(8)
    -    end
    -  end
    -
    -  describe "repeater" do
    -    it "executes the default block" do
    -      block_was_executed = false
    -      repeater do
    -        block_was_executed = true
    -      end
    -      expect(block_was_executed).to eq(true)
    -    end
    -
    -    it "executes the default block 3 times" do
    -      n = 0
    -      repeater(3) do
    -        n += 1
    -      end
    -      expect(n).to eq(3)
    -    end
    -
    -    it "executes the default block 10 times" do
    -      n = 0
    -      repeater(10) do
    -        n += 1
    -      end
    -      expect(n).to eq(10)
    -    end
    -
    -  end
    -
    -end
    -
    -
    -
    - - - diff --git a/05_silly_blocks/silly_blocks_spec.rb b/05_silly_blocks/silly_blocks_spec.rb deleted file mode 100644 index c64e3ef70..000000000 --- a/05_silly_blocks/silly_blocks_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -# # Topics -# -# * blocks -# * closures -# * yield -# * loops -# - -require "silly_blocks" - -describe "some silly block functions" do - - describe "reverser" do - it "reverses the string returned by the default block" do - result = reverser do - "hello" - end - expect(result).to eq("olleh") - end - - it "reverses each word in the string returned by the default block" do - result = reverser do - "hello dolly" - end - expect(result).to eq("olleh yllod") - end - end - - describe "adder" do - it "adds one to the value returned by the default block" do - expect(adder do - 5 - end).to eq(6) - end - - it "adds 3 to the value returned by the default block" do - expect(adder(3) do - 5 - end).to eq(8) - end - end - - describe "repeater" do - it "executes the default block" do - block_was_executed = false - repeater do - block_was_executed = true - end - expect(block_was_executed).to eq(true) - end - - it "executes the default block 3 times" do - n = 0 - repeater(3) do - n += 1 - end - expect(n).to eq(3) - end - - it "executes the default block 10 times" do - n = 0 - repeater(10) do - n += 1 - end - expect(n).to eq(10) - end - - end - -end diff --git a/06_performance_monitor/index.html b/06_performance_monitor/index.html deleted file mode 100644 index 7e2dc0560..000000000 --- a/06_performance_monitor/index.html +++ /dev/null @@ -1,124 +0,0 @@ - - - Test-First Teaching: learn_ruby: performance_monitor - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    performance_monitor

    -

    Topics

    - -
      -
    • stubs
    • -
    • blocks
    • -
    • yield
    • -
    - - -

    Performance Monitor

    - -

    This is (a stripped down version of) an actual useful concept: a function that runs a block of code and then tells you how long it took to run.

    -
    -
    -

    Tests

    -performance_monitor_spec.rb -
    -require "performance_monitor"
    -
    -require "time"  # loads up the Time.parse method -- do NOT create time.rb!
    -
    -describe "Performance Monitor" do
    -  before do
    -    @eleven_am = Time.parse("2011-1-2 11:00:00")
    -  end
    -
    -  it "takes about 0 seconds to run an empty block" do
    -    elapsed_time = measure do
    -    end
    -    expect(elapsed_time).to be_within(0.1).of(0)
    -  end
    -
    -  it "takes exactly 0 seconds to run an empty block (with stubs)" do
    -    allow(Time).to receive(:now) { @eleven_am }
    -    elapsed_time = measure do
    -    end
    -    expect(elapsed_time).to eq(0)
    -  end
    -
    -  it "takes about 1 second to run a block that sleeps for 1 second" do
    -    elapsed_time = measure do
    -      sleep 1
    -    end
    -    expect(elapsed_time).to be_within(0.1).of(1)
    -  end
    -
    -  it "takes exactly 1 second to run a block that sleeps for 1 second (with stubs)" do
    -    fake_time = @eleven_am
    -    allow(Time).to receive(:now) { fake_time }
    -    elapsed_time = measure do
    -      fake_time += 60  # adds one minute to fake_time
    -    end
    -    expect(elapsed_time).to eq(60)
    -  end
    -
    -  it "runs a block N times" do
    -    n = 0
    -    measure(4) do
    -      n += 1
    -    end
    -    expect(n).to eq(4)
    -  end
    -
    -  it "returns the average time, not the total time, when running multiple times" do
    -    run_times = [8,6,5,7]
    -    fake_time = @eleven_am
    -    allow(Time).to receive(:now) { fake_time }
    -    average_time = measure(4) do
    -      fake_time += run_times.pop
    -    end
    -    expect(average_time).to eq(6.5)
    -  end
    -
    -  it "returns the average time when running a random number of times for random lengths of time" do
    -    fake_time = @eleven_am
    -    allow(Time).to receive(:now) { fake_time }
    -    number_of_times = rand(10) + 2
    -    average_time = measure(number_of_times) do
    -      delay = rand(10)
    -      fake_time += delay
    -    end
    -    expect(average_time).to eq((fake_time - @eleven_am).to_f/number_of_times)
    -  end
    -
    -end
    -
    -
    -
    - - - diff --git a/06_performance_monitor/performance_monitor_spec.rb b/06_performance_monitor/performance_monitor_spec.rb deleted file mode 100644 index fa19f3e4b..000000000 --- a/06_performance_monitor/performance_monitor_spec.rb +++ /dev/null @@ -1,78 +0,0 @@ -# # Topics -# -# * stubs -# * blocks -# * yield -# -# # Performance Monitor -# -# This is (a stripped down version of) an actual useful concept: a function that runs a block of code and then tells you how long it took to run. - -require "performance_monitor" - -require "time" # loads up the Time.parse method -- do NOT create time.rb! - -describe "Performance Monitor" do - before do - @eleven_am = Time.parse("2011-1-2 11:00:00") - end - - it "takes about 0 seconds to run an empty block" do - elapsed_time = measure do - end - expect(elapsed_time).to be_within(0.1).of(0) - end - - it "takes exactly 0 seconds to run an empty block (with stubs)" do - allow(Time).to receive(:now) { @eleven_am } - elapsed_time = measure do - end - expect(elapsed_time).to eq(0) - end - - it "takes about 1 second to run a block that sleeps for 1 second" do - elapsed_time = measure do - sleep 1 - end - expect(elapsed_time).to be_within(0.1).of(1) - end - - it "takes exactly 1 second to run a block that sleeps for 1 second (with stubs)" do - fake_time = @eleven_am - allow(Time).to receive(:now) { fake_time } - elapsed_time = measure do - fake_time += 60 # adds one minute to fake_time - end - expect(elapsed_time).to eq(60) - end - - it "runs a block N times" do - n = 0 - measure(4) do - n += 1 - end - expect(n).to eq(4) - end - - it "returns the average time, not the total time, when running multiple times" do - run_times = [8,6,5,7] - fake_time = @eleven_am - allow(Time).to receive(:now) { fake_time } - average_time = measure(4) do - fake_time += run_times.pop - end - expect(average_time).to eq(6.5) - end - - it "returns the average time when running a random number of times for random lengths of time" do - fake_time = @eleven_am - allow(Time).to receive(:now) { fake_time } - number_of_times = rand(10) + 2 - average_time = measure(number_of_times) do - delay = rand(10) - fake_time += delay - end - expect(average_time).to eq((fake_time - @eleven_am).to_f/number_of_times) - end - -end diff --git a/09_timer/index.html b/06_timer/index.html similarity index 76% rename from 09_timer/index.html rename to 06_timer/index.html index fcf7a2c66..a16721555 100644 --- a/09_timer/index.html +++ b/06_timer/index.html @@ -17,17 +17,8 @@

    learn_ruby

  • 02 Calculator
  • 03 Simon Says
  • 04 Pig Latin
  • -
  • 05 Silly Blocks
  • -
  • 06 Performance Monitor
  • -
  • 07 Hello Friend
  • -
  • 08 Book Titles
  • -
  • 09 Timer
  • -
  • 10 Temperature Object
  • -
  • 11 Dictionary
  • -
  • 12 Rpn Calculator
  • -
  • 13 Xml Document
  • -
  • 14 Array Extensions
  • -
  • 15 In Words
  • +
  • 05 Book Titles
  • +
  • 06 Timer
  • timer

    diff --git a/06_timer/timer.rb b/06_timer/timer.rb new file mode 100644 index 000000000..987ae7603 --- /dev/null +++ b/06_timer/timer.rb @@ -0,0 +1,3 @@ +class Timer + #write your code here +end diff --git a/09_timer/timer_spec.rb b/06_timer/timer_spec.rb similarity index 100% rename from 09_timer/timer_spec.rb rename to 06_timer/timer_spec.rb diff --git a/07_hello_friend/hello_friend_spec.rb b/07_hello_friend/hello_friend_spec.rb deleted file mode 100644 index f6c07d376..000000000 --- a/07_hello_friend/hello_friend_spec.rb +++ /dev/null @@ -1,101 +0,0 @@ -# # Hello, friend! -# -# This lab teaches basic Ruby Object syntax. -# -# ## Watch it fail -# -# Your first real failure should be something like this: -# -# ./friend_spec.rb:3: uninitialized constant Friend (NameError) -# -# Fix this by opening `friend.rb` and creating an empty class: -# -# class Friend -# end -# -# Save it. Run the test again. -# -# ## Watch it fail again -# -# Now you should see an error like this: -# -# NoMethodError in 'Friend says hello' -# undefined method `greeting' for # -# ./friend_spec.rb:5: -# -# This means that while it found the file, and it found the class, it couldn't find the method named "greeting". -# -# ## Define the "greeting" method -# -# In `friend.rb`, add the following inside the class (before the "end"). -# -# def greeting -# end -# -# Save it. Run the test again. -# -# ## Watch it fail some more -# -# Now you should see an error like this: -# -# 'Friend says hello' FAILED -# expected: "Hello!", -# got: nil (compared using ==) -# ./friend_spec.rb:5: -# -# This means that there is a method, but it's not returning anything! ("nil" is the Ruby way of saying "not anything".) -# -# ## Make it return something -# -# Inside the "greeting" method, put a single line containing a string that is *not* "Hello!". (Here we are simulating you making an honest mistake, so we can see what the error message looks like.) -# -# def greeting -# "whuh?" -# end -# -# Save it. Run the test again. -# -# ## Watch it fail yet again -# -# Now you should see an error like this: -# -# 'Friend says hello' FAILED -# expected: "Hello!", -# got: "whuh?" (compared using ==) -# ./friend_spec.rb:5: -# -# Correct this by changing "whuh?" to "Hello!". Save it. Run the test again. -# -# ## Watch it pass! -# -# Hooray! Finally! It works! -# -# ## Give yourself a high five -# -# Also, sing a song and do a little dance. -# -# ## And then... -# -# Fix the next failure! :-) -# -# Hint 1: in order to get the next test to pass, you will need to pass a *parameter*: -# -# def greeting(who) -# -# Hint 2: once you do that, the **first** test might start failing again. To fix both at the same time, you need to provide a **default value** for that parameter: -# -# def greeting(who = nil) -# -# - -require "friend" - -describe Friend do - it "says hello" do - expect(Friend.new.greeting).to eq("Hello!") - end - - it "says hello to someone" do - expect(Friend.new.greeting("Bob")).to eq("Hello, Bob!") - end -end diff --git a/07_hello_friend/index.html b/07_hello_friend/index.html deleted file mode 100644 index 55f4e035c..000000000 --- a/07_hello_friend/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - Test-First Teaching: learn_ruby: hello_friend - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    hello_friend

    -

    Hello, friend!

    - -

    This lab teaches basic Ruby Object syntax.

    - -

    Watch it fail

    - -

    Your first real failure should be something like this:

    - -
    ./friend_spec.rb:3: uninitialized constant Friend (NameError)
    -
    - -

    Fix this by opening friend.rb and creating an empty class:

    - -
    class Friend
    -end
    -
    - -

    Save it. Run the test again.

    - -

    Watch it fail again

    - -

    Now you should see an error like this:

    - -
    NoMethodError in 'Friend says hello'
    -undefined method `greeting' for #<Friend:0x1180f3c>
    -./friend_spec.rb:5:
    -
    - -

    This means that while it found the file, and it found the class, it couldn't find the method named "greeting".

    - -

    Define the "greeting" method

    - -

    In friend.rb, add the following inside the class (before the "end").

    - -
    def greeting
    -end
    -
    - -

    Save it. Run the test again.

    - -

    Watch it fail some more

    - -

    Now you should see an error like this:

    - -
    'Friend says hello' FAILED
    -expected: "Hello!",
    -     got: nil (compared using ==)
    -./friend_spec.rb:5:
    -
    - -

    This means that there is a method, but it's not returning anything! ("nil" is the Ruby way of saying "not anything".)

    - -

    Make it return something

    - -

    Inside the "greeting" method, put a single line containing a string that is not "Hello!". (Here we are simulating you making an honest mistake, so we can see what the error message looks like.)

    - -
    def greeting
    -  "whuh?"
    -end
    -
    - -

    Save it. Run the test again.

    - -

    Watch it fail yet again

    - -

    Now you should see an error like this:

    - -
    'Friend says hello' FAILED
    -expected: "Hello!",
    -     got: "whuh?" (compared using ==)
    -./friend_spec.rb:5:
    -
    - -

    Correct this by changing "whuh?" to "Hello!". Save it. Run the test again.

    - -

    Watch it pass!

    - -

    Hooray! Finally! It works!

    - -

    Give yourself a high five

    - -

    Also, sing a song and do a little dance.

    - -

    And then...

    - -

    Fix the next failure! :-)

    - -

    Hint 1: in order to get the next test to pass, you will need to pass a parameter:

    - -
    def greeting(who)
    -
    - -

    Hint 2: once you do that, the first test might start failing again. To fix both at the same time, you need to provide a default value for that parameter:

    - -
    def greeting(who = nil)
    -
    -
    -
    -

    Tests

    -hello_friend_spec.rb -
    -require "friend"
    -
    -describe Friend do
    -  it "says hello" do
    -    expect(Friend.new.greeting).to eq("Hello!")
    -  end
    -
    -  it "says hello to someone" do
    -    expect(Friend.new.greeting("Bob")).to eq("Hello, Bob!")
    -  end
    -end
    -
    -
    -
    - - - diff --git a/10_temperature_object/index.html b/10_temperature_object/index.html deleted file mode 100644 index 6c88c6e7f..000000000 --- a/10_temperature_object/index.html +++ /dev/null @@ -1,172 +0,0 @@ - - - Test-First Teaching: learn_ruby: temperature_object - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    temperature_object

    -

    Topics:

    - -
      -
    • floating-point math
    • -
    • objects
    • -
    • constructors
    • -
    • class methods
    • -
    • factory methods
    • -
    • options hashes
    • -
    - - -

    Hints

    - -

    Remember that one degree fahrenheit is 5/9 of one degree celsius, and that the freezing point of water is 0 degrees celsius but 32 degrees fahrenheit.

    - -

    Remember to define the from_celsius factory method as a class method, not an instance method.

    - -

    The temperature object's constructor should accept an options hash which contains either a :celcius entry or a :fahrenheit entry.

    -
    -
    -

    Tests

    -temperature_object_spec.rb -
    -require "temperature"
    -
    -describe Temperature do
    -
    -  describe "can be constructed with an options hash" do
    -    describe "in degrees fahrenheit" do
    -      it "at 50 degrees" do
    -        expect(Temperature.new(:f => 50).in_fahrenheit).to eq(50)
    -      end
    -
    -      describe "and correctly convert to celsius" do
    -        it "at freezing" do
    -          expect(Temperature.new(:f => 32).in_celsius).to eq(0)
    -        end
    -
    -        it "at boiling" do
    -          expect(Temperature.new(:f => 212).in_celsius).to eq(100)
    -        end
    -
    -        it "at body temperature" do
    -          expect(Temperature.new(:f => 98.6).in_celsius).to eq(37)
    -        end
    -
    -        it "at an arbitrary temperature" do
    -          expect(Temperature.new(:f => 68).in_celsius).to eq(20)
    -        end
    -      end
    -    end
    -
    -    describe "in degrees celsius" do
    -      it "at 50 degrees" do
    -        expect(Temperature.new(:c => 50).in_celsius).to eq(50)
    -      end
    -
    -      describe "and correctly convert to fahrenheit" do
    -        it "at freezing" do
    -          expect(Temperature.new(:c => 0).in_fahrenheit).to eq(32)
    -        end
    -
    -        it "at boiling" do
    -          expect(Temperature.new(:c => 100).in_fahrenheit).to eq(212)
    -        end
    -
    -        it "at body temperature" do
    -          expect(Temperature.new(:c => 37).in_fahrenheit).to be_within(0.1).of(98.6)
    -          # Why do we need to use be_within here?
    -          # See http://www.ruby-forum.com/topic/169330
    -          # and http://groups.google.com/group/rspec/browse_thread/thread/f3ebbe3c313202bb
    -          # Also, try "puts 0.5 - 0.4 - 0.1" -- pretty crazy, right?
    -        end
    -      end
    -    end
    -  end
    -
    -  # Factory Method is a design pattern, not a Ruby language feature.
    -  # One way to implement this pattern in Ruby is via class methods --
    -  # that is, methods defined on the class (Temperature) rather than
    -  # on individual instances of the class.
    -  describe "can be constructed via factory methods" do
    -
    -    it "in degrees celsius" do
    -      expect(Temperature.from_celsius(50).in_celsius).to eq(50)
    -      expect(Temperature.from_celsius(50).in_fahrenheit).to eq(122)
    -    end
    -
    -    it "in degrees fahrenheit" do
    -      expect(Temperature.from_fahrenheit(50).in_fahrenheit).to eq(50)
    -      expect(Temperature.from_fahrenheit(50).in_celsius).to eq(10)
    -    end
    -
    -  end
    -
    -  # test-driving bonus:
    -  #
    -  # 1. make two class methods -- ftoc and ctof
    -  # 2. refactor to call those methods from the rest of the object
    -  #
    -  # run *all* the tests during your refactoring, to make sure you did it right
    -  #
    -  describe "utility class methods" do
    -
    -  end
    -
    -  # Here's another way to solve the problem!
    -  describe "Temperature subclasses" do
    -    describe "Celsius subclass" do
    -      it "is constructed in degrees celsius" do
    -        expect(Celsius.new(50).in_celsius).to eq(50)
    -        expect(Celsius.new(50).in_fahrenheit).to eq(122)
    -      end
    -
    -      it "is a Temperature subclass" do
    -        expect(Celsius.new(0)).to be_a(Temperature)
    -      end
    -    end
    -
    -    describe "Fahrenheit subclass" do
    -      it "is constructed in degrees fahrenheit" do
    -        expect(Fahrenheit.new(50).in_fahrenheit).to eq(50)
    -        expect(Fahrenheit.new(50).in_celsius).to eq(10)
    -      end
    -
    -      it "is a Temperature subclass" do
    -        expect(Fahrenheit.new(0)).to be_a(Temperature)
    -      end
    -    end
    -  end
    -
    -end
    -
    -
    -
    - - - diff --git a/10_temperature_object/temperature_object_spec.rb b/10_temperature_object/temperature_object_spec.rb deleted file mode 100644 index 5c0af8685..000000000 --- a/10_temperature_object/temperature_object_spec.rb +++ /dev/null @@ -1,128 +0,0 @@ -# # Topics: -# * floating-point math -# * objects -# * constructors -# * class methods -# * factory methods -# * options hashes -# -# # Hints -# -# Remember that one degree fahrenheit is 5/9 of one degree celsius, and that the freezing point of water is 0 degrees celsius but 32 degrees fahrenheit. -# -# Remember to define the `from_celsius` factory method as a *class* method, not an *instance* method. -# -# The temperature object's constructor should accept an *options hash* which contains either a `:celcius` entry or a `:fahrenheit` entry. -# -# -# - -require "temperature" - -describe Temperature do - - describe "can be constructed with an options hash" do - describe "in degrees fahrenheit" do - it "at 50 degrees" do - expect(Temperature.new(:f => 50).in_fahrenheit).to eq(50) - end - - describe "and correctly convert to celsius" do - it "at freezing" do - expect(Temperature.new(:f => 32).in_celsius).to eq(0) - end - - it "at boiling" do - expect(Temperature.new(:f => 212).in_celsius).to eq(100) - end - - it "at body temperature" do - expect(Temperature.new(:f => 98.6).in_celsius).to eq(37) - end - - it "at an arbitrary temperature" do - expect(Temperature.new(:f => 68).in_celsius).to eq(20) - end - end - end - - describe "in degrees celsius" do - it "at 50 degrees" do - expect(Temperature.new(:c => 50).in_celsius).to eq(50) - end - - describe "and correctly convert to fahrenheit" do - it "at freezing" do - expect(Temperature.new(:c => 0).in_fahrenheit).to eq(32) - end - - it "at boiling" do - expect(Temperature.new(:c => 100).in_fahrenheit).to eq(212) - end - - it "at body temperature" do - expect(Temperature.new(:c => 37).in_fahrenheit).to be_within(0.1).of(98.6) - # Why do we need to use be_within here? - # See http://www.ruby-forum.com/topic/169330 - # and http://groups.google.com/group/rspec/browse_thread/thread/f3ebbe3c313202bb - # Also, try "puts 0.5 - 0.4 - 0.1" -- pretty crazy, right? - end - end - end - end - - # Factory Method is a design pattern, not a Ruby language feature. - # One way to implement this pattern in Ruby is via class methods -- - # that is, methods defined on the class (Temperature) rather than - # on individual instances of the class. - describe "can be constructed via factory methods" do - - it "in degrees celsius" do - expect(Temperature.from_celsius(50).in_celsius).to eq(50) - expect(Temperature.from_celsius(50).in_fahrenheit).to eq(122) - end - - it "in degrees fahrenheit" do - expect(Temperature.from_fahrenheit(50).in_fahrenheit).to eq(50) - expect(Temperature.from_fahrenheit(50).in_celsius).to eq(10) - end - - end - - # test-driving bonus: - # - # 1. make two class methods -- ftoc and ctof - # 2. refactor to call those methods from the rest of the object - # - # run *all* the tests during your refactoring, to make sure you did it right - # - describe "utility class methods" do - - end - - # Here's another way to solve the problem! - describe "Temperature subclasses" do - describe "Celsius subclass" do - it "is constructed in degrees celsius" do - expect(Celsius.new(50).in_celsius).to eq(50) - expect(Celsius.new(50).in_fahrenheit).to eq(122) - end - - it "is a Temperature subclass" do - expect(Celsius.new(0)).to be_a(Temperature) - end - end - - describe "Fahrenheit subclass" do - it "is constructed in degrees fahrenheit" do - expect(Fahrenheit.new(50).in_fahrenheit).to eq(50) - expect(Fahrenheit.new(50).in_celsius).to eq(10) - end - - it "is a Temperature subclass" do - expect(Fahrenheit.new(0)).to be_a(Temperature) - end - end - end - -end diff --git a/11_dictionary/dictionary_spec.rb b/11_dictionary/dictionary_spec.rb deleted file mode 100644 index f57bb3e9d..000000000 --- a/11_dictionary/dictionary_spec.rb +++ /dev/null @@ -1,83 +0,0 @@ -# # Topics -# -# * Hash -# * Array -# * instance variables -# * regular expressions -# - -require 'dictionary' - -describe Dictionary do - before do - @d = Dictionary.new - end - - it 'is empty when created' do - expect(@d.entries).to eq({}) - end - - it 'can add whole entries with keyword and definition' do - @d.add('fish' => 'aquatic animal') - expect(@d.entries).to eq({'fish' => 'aquatic animal'}) - expect(@d.keywords).to eq(['fish']) - end - - it 'add keywords (without definition)' do - @d.add('fish') - expect(@d.entries).to eq({'fish' => nil}) - expect(@d.keywords).to eq(['fish']) - end - - it 'can check whether a given keyword exists' do - expect(@d.include?('fish')).to be false - end - - it "doesn't cheat when checking whether a given keyword exists" do - expect(@d.include?('fish')).to be false # if the method is empty, this test passes with nil returned - @d.add('fish') - expect(@d.include?('fish')).to be true # confirms that it actually checks - expect(@d.include?('bird')).to be false # confirms not always returning true after add - end - - it "doesn't include a prefix that wasn't added as a word in and of itself" do - @d.add('fish') - expect(@d.include?('fi')).to be false - end - - it "doesn't find a word in empty dictionary" do - expect(@d.find('fi')).to be_empty # {} - end - - it 'finds nothing if the prefix matches nothing' do - @d.add('fiend') - @d.add('great') - expect(@d.find('nothing')).to be_empty - end - - it "finds an entry" do - @d.add('fish' => 'aquatic animal') - expect(@d.find('fish')).to eq({'fish' => 'aquatic animal'}) - end - - it 'finds multiple matches from a prefix and returns the entire entry (keyword + definition)' do - @d.add('fish' => 'aquatic animal') - @d.add('fiend' => 'wicked person') - @d.add('great' => 'remarkable') - expect(@d.find('fi')).to eq({'fish' => 'aquatic animal', 'fiend' => 'wicked person'}) - end - - it 'lists keywords alphabetically' do - @d.add('zebra' => 'African land animal with stripes') - @d.add('fish' => 'aquatic animal') - @d.add('apple' => 'fruit') - expect(@d.keywords).to eq(%w(apple fish zebra)) - end - - it 'can produce printable output like so: [keyword] "definition"' do - @d.add('zebra' => 'African land animal with stripes') - @d.add('fish' => 'aquatic animal') - @d.add('apple' => 'fruit') - expect(@d.printable).to eq(%Q{[apple] "fruit"\n[fish] "aquatic animal"\n[zebra] "African land animal with stripes"}) - end -end diff --git a/11_dictionary/index.html b/11_dictionary/index.html deleted file mode 100644 index 4b4d4463f..000000000 --- a/11_dictionary/index.html +++ /dev/null @@ -1,128 +0,0 @@ - - - Test-First Teaching: learn_ruby: dictionary - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    dictionary

    -

    Topics

    - -
      -
    • Hash
    • -
    • Array
    • -
    • instance variables
    • -
    • regular expressions
    • -
    - -
    -
    -

    Tests

    -dictionary_spec.rb -
    -require 'dictionary'
    -
    -describe Dictionary do
    -  before do
    -    @d = Dictionary.new
    -  end
    -
    -  it 'is empty when created' do
    -    expect(@d.entries).to eq({})
    -  end
    -
    -  it 'can add whole entries with keyword and definition' do
    -    @d.add('fish' => 'aquatic animal')
    -    expect(@d.entries).to eq({'fish' => 'aquatic animal'})
    -    expect(@d.keywords).to eq(['fish'])
    -  end
    -
    -  it 'add keywords (without definition)' do
    -    @d.add('fish')
    -    expect(@d.entries).to eq({'fish' => nil})
    -    expect(@d.keywords).to eq(['fish'])
    -  end
    -
    -  it 'can check whether a given keyword exists' do
    -    expect(@d.include?('fish').to be_false
    -  end
    -
    -  it "doesn't cheat when checking whether a given keyword exists" do
    -    expect(@d.include?('fish')).to be_false # if the method is empty, this test passes with nil returned
    -    @d.add('fish')
    -    expect(@d.include?('fish')).to be_true # confirms that it actually checks
    -    expect(@d.include?('bird')).to be_false # confirms not always returning true after add
    -  end
    -
    -  it "doesn't include a prefix that wasn't added as a word in and of itself" do
    -    @d.add('fish')
    -    expect(@d.include?('fi')).to be_false
    -  end
    -
    -  it "doesn't find a word in empty dictionary" do
    -    expect(@d.find('fi')).to be_empty # {}
    -  end
    -
    -  it 'finds nothing if the prefix matches nothing' do
    -    @d.add('fiend')
    -    @d.add('great')
    -    expect(@d.find('nothing')).to be_empty
    -  end
    -
    -  it "finds an entry" do
    -    @d.add('fish' => 'aquatic animal')
    -    expect(@d.find('fish')).to eq({'fish' => 'aquatic animal'})
    -  end
    -
    -  it 'finds multiple matches from a prefix and returns the entire entry (keyword + definition)' do
    -    @d.add('fish' => 'aquatic animal')
    -    @d.add('fiend' => 'wicked person')
    -    @d.add('great' => 'remarkable')
    -    expect(@d.find('fi')).to eq({'fish' => 'aquatic animal', 'fiend' => 'wicked person'})
    -  end
    -
    -  it 'lists keywords alphabetically' do
    -    @d.add('zebra' => 'African land animal with stripes')
    -    @d.add('fish' => 'aquatic animal')
    -    @d.add('apple' => 'fruit')
    -    expect(@d.keywords).to eq(%w(apple fish zebra))
    -  end
    -
    -  it 'can produce printable output like so: [keyword] "definition"' do
    -    @d.add('zebra' => 'African land animal with stripes')
    -    @d.add('fish' => 'aquatic animal')
    -    @d.add('apple' => 'fruit')
    -    expect(@d.printable).to eq(%Q{[apple] "fruit"\n[fish] "aquatic animal"\n[zebra] "African land animal with stripes"})
    -  end
    -end
    -
    -
    -
    - - - diff --git a/12_rpn_calculator/index.html b/12_rpn_calculator/index.html deleted file mode 100644 index 5237a7d4e..000000000 --- a/12_rpn_calculator/index.html +++ /dev/null @@ -1,191 +0,0 @@ - - - Test-First Teaching: learn_ruby: rpn_calculator - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    rpn_calculator

    -

    Topics

    - -
      -
    • arrays
    • -
    • arithmetic
    • -
    • strings
    • -
    - - -

    RPN Calculator

    - -

    "RPN" stands for "Reverse Polish Notation". (See the wikipedia entry for more information on this colorful term.) Briefly, in an RPN world, instead of using normal "infix" notation, e.g.

    - -
    2 + 2
    -
    - -

    you use "postfix" notation, e.g.

    - -
    2 2 +
    -
    - -

    While this may seem bizarre, there are some advantages to doing things this way. For one, you never need to use parentheses, since there is never any ambiguity as to what order to perform operations in. The rule is, you always go from the back, or the left side.

    - -
    1 + 2 * 3 =>
    -(1 + 2) * 3 or
    -1 + (2 * 3)
    -
    -1 2 + 3 * => (1 + 2) * 3
    -1 2 3 * + => 1 + (2 * 3)
    -
    - -

    Another advantage is that you can represent any mathematical formula using a simple and elegant data structure, called a stack).

    - -

    Hints

    - -

    Ruby doesn't have a built-in stack, but the standard Array has all the methods you need to emulate one (namely, push and pop, and optionally size).

    -
    -
    -

    Tests

    -rpn_calculator_spec.rb -
    -# See
    -# * <http://en.wikipedia.org/wiki/Reverse_Polish_notation>
    -# * <http://www.calculator.org/rpn.aspx>
    -#
    -require "rpn_calculator"
    -
    -describe RPNCalculator do
    -
    -  attr_accessor :calculator
    -
    -  before do
    -    @calculator = RPNCalculator.new
    -  end
    -
    -  it "adds two numbers" do
    -    calculator.push(2)
    -    calculator.push(3)
    -    calculator.plus
    -    expect(calculator.value).to eq(5)
    -  end
    -
    -  it "adds three numbers" do
    -    calculator.push(2)
    -    calculator.push(3)
    -    calculator.push(4)
    -    calculator.plus
    -    expect(calculator.value).to eq(7)
    -    calculator.plus
    -    expect(calculator.value).to eq(9)
    -  end
    -
    -  it "subtracts the second number from the first number" do
    -    calculator.push(2)
    -    calculator.push(3)
    -    calculator.minus
    -    expect(calculator.value).to eq(-1)
    -  end
    -
    -  it "adds and subtracts" do
    -    calculator.push(2)
    -    calculator.push(3)
    -    calculator.push(4)
    -    calculator.minus
    -    expect(calculator.value).to eq(-1)
    -    calculator.plus
    -    expect(calculator.value).to eq(1)
    -  end
    -
    -  it "multiplies and divides" do
    -    calculator.push(2)
    -    calculator.push(3)
    -    calculator.push(4)
    -    calculator.divide
    -    expect(calculator.value).to eq(3.0 / 4.0)
    -    calculator.times
    -    expect(calculator.value).to eq(2.0 * (3.0 / 4.0))
    -  end
    -
    -  it "resolves operator precedence unambiguously" do
    -    # 1 2 + 3 * => (1 + 2) * 3
    -    calculator.push(1)
    -    calculator.push(2)
    -    calculator.plus
    -    calculator.push(3)
    -    calculator.times
    -    expect(calculator.value).to eq((1+2)*3)
    -
    -    # 1 2 3 * + => 1 + (2 * 3)
    -    calculator.push(1)
    -    calculator.push(2)
    -    calculator.push(3)
    -    calculator.times
    -    calculator.plus
    -    expect(calculator.value).to eq(1+(2*3))
    -  end
    -
    -  it "fails informatively when there's not enough values stacked away" do
    -    expect {
    -      calculator.plus
    -    }.to raise_error("calculator is empty")
    -
    -    expect {
    -      calculator.minus
    -    }.to raise_error("calculator is empty")
    -
    -    expect {
    -      calculator.times
    -    }.to raise_error("calculator is empty")
    -
    -    expect {
    -      calculator.divide
    -    }.to raise_error("calculator is empty")
    -  end
    -
    -  # extra credit
    -  it "tokenizes a string" do
    -    expect(calculator.tokens("1 2 3 * + 4 5 - /")).to eq([1, 2, 3, :*, :+, 4, 5, :-, :/])
    -  end
    -
    -  # extra credit
    -  it "evaluates a string" do
    -    expect(calculator.evaluate("1 2 3 * +")).to eq((2 * 3) + 1)
    -
    -    expect(calculator.evaluate("4 5 -")).to eq(4 - 5)
    -
    -    expect(calculator.evaluate("2 3 /")).to eq(2.0 / 3.0)
    -
    -    expect(calculator.evaluate("1 2 3 * + 4 5 - /")).to eq((1.0 + (2 * 3)) / (4 - 5))
    -  end
    -
    -end
    -
    -
    -
    - - - diff --git a/12_rpn_calculator/rpn_calculator_spec.rb b/12_rpn_calculator/rpn_calculator_spec.rb deleted file mode 100644 index a79d0a369..000000000 --- a/12_rpn_calculator/rpn_calculator_spec.rb +++ /dev/null @@ -1,142 +0,0 @@ -# # Topics -# * arrays -# * arithmetic -# * strings -# -# # RPN Calculator -# -# "RPN" stands for "Reverse Polish Notation". (See [the wikipedia entry](http://en.wikipedia.org/wiki/Reverse_Polish_notation) for more information on this colorful term.) Briefly, in an RPN world, instead of using normal "infix" notation, e.g. -# -# 2 + 2 -# -# you use "postfix" notation, e.g. -# -# 2 2 + -# -# While this may seem bizarre, there are some advantages to doing things this way. For one, you never need to use parentheses, since there is never any ambiguity as to what order to perform operations in. The rule is, you always go from the back, or the left side. -# -# 1 + 2 * 3 => -# (1 + 2) * 3 or -# 1 + (2 * 3) -# -# 1 2 + 3 * => (1 + 2) * 3 -# 1 2 3 * + => 1 + (2 * 3) -# -# Another advantage is that you can represent any mathematical formula using a simple and elegant data structure, called a [stack](http://en.wikipedia.org/wiki/Stack_(data_structure)). -# -# # Hints -# -# Ruby doesn't have a built-in stack, but the standard Array has all the methods you need to emulate one (namely, `push` and `pop`, and optionally `size`). -# - -# See -# * -# * -# -require "rpn_calculator" - -describe RPNCalculator do - - attr_accessor :calculator - - before do - @calculator = RPNCalculator.new - end - - it "adds two numbers" do - calculator.push(2) - calculator.push(3) - calculator.plus - expect(calculator.value).to eq(5) - end - - it "adds three numbers" do - calculator.push(2) - calculator.push(3) - calculator.push(4) - calculator.plus - expect(calculator.value).to eq(7) - calculator.plus - expect(calculator.value).to eq(9) - end - - it "subtracts the second number from the first number" do - calculator.push(2) - calculator.push(3) - calculator.minus - expect(calculator.value).to eq(-1) - end - - it "adds and subtracts" do - calculator.push(2) - calculator.push(3) - calculator.push(4) - calculator.minus - expect(calculator.value).to eq(-1) - calculator.plus - expect(calculator.value).to eq(1) - end - - it "multiplies and divides" do - calculator.push(2) - calculator.push(3) - calculator.push(4) - calculator.divide - expect(calculator.value).to eq(3.0 / 4.0) - calculator.times - expect(calculator.value).to eq(2.0 * (3.0 / 4.0)) - end - - it "resolves operator precedence unambiguously" do - # 1 2 + 3 * => (1 + 2) * 3 - calculator.push(1) - calculator.push(2) - calculator.plus - calculator.push(3) - calculator.times - expect(calculator.value).to eq((1+2)*3) - - # 1 2 3 * + => 1 + (2 * 3) - calculator.push(1) - calculator.push(2) - calculator.push(3) - calculator.times - calculator.plus - expect(calculator.value).to eq(1+(2*3)) - end - - it "fails informatively when there's not enough values stacked away" do - expect { - calculator.plus - }.to raise_error("calculator is empty") - - expect { - calculator.minus - }.to raise_error("calculator is empty") - - expect { - calculator.times - }.to raise_error("calculator is empty") - - expect { - calculator.divide - }.to raise_error("calculator is empty") - end - - # extra credit - it "tokenizes a string" do - expect(calculator.tokens("1 2 3 * + 4 5 - /")).to eq([1, 2, 3, :*, :+, 4, 5, :-, :/]) - end - - # extra credit - it "evaluates a string" do - expect(calculator.evaluate("1 2 3 * +")).to eq((2 * 3) + 1) - - expect(calculator.evaluate("4 5 -")).to eq(4 - 5) - - expect(calculator.evaluate("2 3 /")).to eq(2.0 / 3.0) - - expect(calculator.evaluate("1 2 3 * + 4 5 - /")).to eq( (1.0 + (2 * 3)) / (4 - 5) ) - end - -end diff --git a/13_xml_document/index.html b/13_xml_document/index.html deleted file mode 100644 index 900ff72d5..000000000 --- a/13_xml_document/index.html +++ /dev/null @@ -1,123 +0,0 @@ - - - Test-First Teaching: learn_ruby: xml_document - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    xml_document

    -

    Topics

    - -
      -
    • method_missing
    • -
    • blocks
    • -
    • strings
    • -
    • hashes
    • -
    - - -

    Builder

    - -

    Here we will implement the so-called Builder Pattern: we will make an object, XmlDocument, that builds an XML file, which can contain arbitrary tags.

    -
    -
    -

    Tests

    -xml_document_spec.rb -
    -# Stuff you'll learn:
    -# method_missing
    -# nested closures
    -# "builder pattern"
    -
    -require "xml_document"
    -
    -describe XmlDocument do
    -  before do
    -    @xml = XmlDocument.new
    -  end
    -
    -  it "renders an empty tag" do
    -    expect(@xml.hello).to eq("<hello/>")
    -  end
    -
    -  it "renders a tag with attributes" do
    -    expect(@xml.hello(:name => 'dolly')).to eq("<hello name='dolly'/>")
    -  end
    -
    -  it "renders a randomly named tag" do
    -    tag_name = (1..8).map{|i| ('a'..'z').to_a[rand(26)]}.join
    -    expect(@xml.send(tag_name)).to eq("<#{tag_name}/>")
    -  end
    -
    -  it "renders block with text inside" do
    -    expect(@xml.hello do
    -      "dolly"
    -    end).to eq("<hello>dolly</hello>")
    -  end
    -
    -  it "nests one level" do
    -    expect(@xml.hello do
    -      @xml.goodbye
    -    end).to eq("<hello><goodbye/></hello>")
    -  end
    -
    -  it "nests several levels" do
    -    xml = XmlDocument.new
    -    expect(xml.hello do
    -      xml.goodbye do
    -        xml.come_back do
    -          xml.ok_fine(:be => "that_way")
    -        end
    -      end
    -    end).to eq("<hello><goodbye><come_back><ok_fine be='that_way'/></come_back></goodbye></hello>")
    -  end
    -
    -  it "indents" do
    -    @xml = XmlDocument.new(true)
    -    expect(@xml.hello do
    -      @xml.goodbye do
    -        @xml.come_back do
    -          @xml.ok_fine(:be => "that_way")
    -        end
    -      end
    -    end).to eq(
    -    "<hello>\n" +
    -    "  <goodbye>\n" +
    -    "    <come_back>\n" +
    -    "      <ok_fine be='that_way'/>\n" +
    -    "    </come_back>\n" +
    -    "  </goodbye>\n" +
    -    "</hello>\n")
    -  end
    -end
    -
    -
    -
    - - - diff --git a/13_xml_document/xml_document_spec.rb b/13_xml_document/xml_document_spec.rb deleted file mode 100644 index fa1995818..000000000 --- a/13_xml_document/xml_document_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# # Topics -# -# * method_missing -# * blocks -# * strings -# * hashes -# -# # Builder -# -# Here we will implement the so-called Builder Pattern: we will make an object, XmlDocument, that *builds* an XML file, which can contain arbitrary tags. - -# Stuff you'll learn: -# method_missing -# nested closures -# "builder pattern" - -require "xml_document" - -describe XmlDocument do - before do - @xml = XmlDocument.new - end - - it "renders an empty tag" do - expect(@xml.hello).to eq("") - end - - it "renders a tag with attributes" do - expect(@xml.hello(:name => 'dolly')).to eq("") - end - - it "renders a randomly named tag" do - tag_name = (1..8).map{|i| ('a'..'z').to_a[rand(26)]}.join - expect(@xml.send(tag_name)).to eq("<#{tag_name}/>") - end - - it "renders block with text inside" do - expect(@xml.hello do - "dolly" - end).to eq("dolly") - end - - it "nests one level" do - expect(@xml.hello do - @xml.goodbye - end).to eq("") - end - - it "nests several levels" do - xml = XmlDocument.new - expect(xml.hello do - xml.goodbye do - xml.come_back do - xml.ok_fine(:be => "that_way") - end - end - end).to eq("") - end - - it "indents" do - @xml = XmlDocument.new(true) - expect(@xml.hello do - @xml.goodbye do - @xml.come_back do - @xml.ok_fine(:be => "that_way") - end - end - end).to eq( - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "\n") - end -end diff --git a/14_array_extensions/array_extensions_spec.rb b/14_array_extensions/array_extensions_spec.rb deleted file mode 100755 index 4c6b075a2..000000000 --- a/14_array_extensions/array_extensions_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -# # Array Extension -# -# # Topics -# -# * objects, methods, classes -# * reopening classes -# - -require "array_extensions" # we don't call it "array.rb" since that would be confusing - -describe Array do - - describe "#sum" do - it "has a #sum method" do - expect([]).to respond_to(:sum) - end - - it "should be 0 for an empty array" do - expect([].sum).to eq(0) - end - - it "should add all of the elements" do - expect([1,2,4].sum).to eq(7) - end - end - - describe '#square' do - it "does nothing to an empty array" do - expect([].square).to eq([]) - end - - it "returns a new array containing the squares of each element" do - expect([1,2,3].square).to eq([1,4,9]) - end - end - - describe '#square!' do - it "squares each element of the original array" do - array = [1,2,3] - array.square! - expect(array).to eq([1,4,9]) - end - end - -end diff --git a/14_array_extensions/index.html b/14_array_extensions/index.html deleted file mode 100644 index ebbe06502..000000000 --- a/14_array_extensions/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - Test-First Teaching: learn_ruby: array_extensions - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    array_extensions

    -

    Array Extension

    - -

    Topics

    - -
      -
    • objects, methods, classes
    • -
    • reopening classes
    • -
    - -
    -
    -

    Tests

    -array_extensions_spec.rb -
    -require "array_extensions" # we don't call it "array.rb" since that would be confusing
    -
    -describe Array do
    -
    -  describe "#sum" do
    -    it "has a #sum method" do
    -      expect([]).to respond_to(:sum)
    -    end
    -
    -    it "should be 0 for an empty array" do
    -      expect([].sum).to eq(0)
    -    end
    -
    -    it "should add all of the elements" do
    -      expect([1,2,4].sum).to eq(7)
    -    end
    -  end
    -
    -  describe '#square' do
    -    it "does nothing to an empty array" do
    -      expect([].square).to eq([])
    -    end
    -
    -    it "returns a new array containing the squares of each element" do
    -      expect([1,2,3].square).to eq([1,4,9])
    -    end
    -  end
    -
    -  describe '#square!' do
    -    it "squares each element of the original array" do
    -      array = [1,2,3]
    -      array.square!
    -      expect(array).to eq([1,4,9])
    -    end
    -  end
    -
    -end
    -
    -
    -
    - - - diff --git a/15_in_words/in_words_spec.rb b/15_in_words/in_words_spec.rb deleted file mode 100644 index 1f5768575..000000000 --- a/15_in_words/in_words_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -# # Topics -# -# * strings and numbers -# * modules -# * reopening classes -# -# # Extending a built-in class -# -# To make this test pass you'll need to extend a built-in class. You'll see that we're creating a new spec for 'Fixnum' -- this isn't a new class you'll be building, but instead it is a built-in class you will extend. -# -# Remember that in Ruby, everything is an object, even a number. Try this in irb: -# -# >> 4.class -# => Fixnum -# >> 4.methods -# \["inspect", "%", "<<", ... -# -# The number 4 is of class `FixNum` and it has methods on it. Your challenge is to add an `in_words` method to `FixNum`. -# - -require "in_words" - -describe Fixnum do - - it "reads 0 to 9" do - expect(0.in_words).to eq('zero') - expect(1.in_words).to eq('one') - expect(2.in_words).to eq('two') - expect(3.in_words).to eq('three') - expect(4.in_words).to eq('four') - expect(5.in_words).to eq('five') - expect(6.in_words).to eq('six') - expect(7.in_words).to eq('seven') - expect(8.in_words).to eq('eight') - expect(9.in_words).to eq('nine') - end - - it "reads 10 to 12" do - expect(10.in_words).to eq('ten') - expect(11.in_words).to eq('eleven') - expect(12.in_words).to eq ('twelve') - end - - it "reads teens" do - expect(13.in_words).to eq('thirteen') - expect(14.in_words).to eq('fourteen') - expect(15.in_words).to eq('fifteen') - expect(16.in_words).to eq('sixteen') - expect(17.in_words).to eq('seventeen') - expect(18.in_words).to eq('eighteen') - expect(19.in_words).to eq('nineteen') - end - - it "reads tens" do - expect(20.in_words).to eq('twenty') - expect(30.in_words).to eq('thirty') - expect(40.in_words).to eq('forty') - expect(50.in_words).to eq('fifty') - expect(60.in_words).to eq('sixty') - expect(70.in_words).to eq('seventy') - expect(80.in_words).to eq('eighty') - expect(90.in_words).to eq('ninety') - end - - it "reads various other numbers less than 100" do - expect(20.in_words).to eq('twenty') - expect(77.in_words).to eq('seventy seven') - expect(99.in_words).to eq('ninety nine') - end - - it "reads hundreds" do - expect(100.in_words).to eq('one hundred') - expect(200.in_words).to eq('two hundred') - expect(300.in_words).to eq('three hundred') - expect(123.in_words).to eq('one hundred twenty three') - expect(777.in_words).to eq('seven hundred seventy seven') - expect(818.in_words).to eq('eight hundred eighteen') - expect(512.in_words).to eq('five hundred twelve') - expect(999.in_words).to eq('nine hundred ninety nine') - end - - it "reads thousands" do - expect(1000.in_words).to eq('one thousand') - expect(32767.in_words).to eq('thirty two thousand seven hundred sixty seven') - expect(32768.in_words).to eq('thirty two thousand seven hundred sixty eight') - end - - it "reads millions" do - expect(10_000_001.in_words).to eq('ten million one') - end - - it "reads billions" do - expect(1_234_567_890.in_words).to eq('one billion two hundred thirty four million five hundred sixty seven thousand eight hundred ninety') - end - - it "reads trillions" do - expect(1_000_000_000_000.in_words).to eq('one trillion') - expect(1_000_000_000_001.in_words).to eq('one trillion one') - expect(1_888_259_040_036.in_words).to eq('one trillion eight hundred eighty eight billion two hundred fifty nine million forty thousand thirty six') - end - -end diff --git a/15_in_words/index.html b/15_in_words/index.html deleted file mode 100644 index e235d4796..000000000 --- a/15_in_words/index.html +++ /dev/null @@ -1,148 +0,0 @@ - - - Test-First Teaching: learn_ruby: in_words - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    in_words

    -

    Topics

    - -
      -
    • strings and numbers
    • -
    • modules
    • -
    • reopening classes
    • -
    - - -

    Extending a built-in class

    - -

    To make this test pass you'll need to extend a built-in class. You'll see that we're creating a new spec for 'Fixnum' -- this isn't a new class you'll be building, but instead it is a built-in class you will extend.

    - -

    Remember that in Ruby, everything is an object, even a number. Try this in irb:

    - -
    >> 4.class
    -=> Fixnum
    ->> 4.methods
    -\["inspect", "%", "<<", ...
    -
    - -

    The number 4 is of class FixNum and it has methods on it. Your challenge is to add an in_words method to FixNum.

    -
    -
    -

    Tests

    -in_words_spec.rb -
    -require "in_words"
    -
    -describe Fixnum do
    -
    -  it "reads 0 to 9" do
    -    expect(0.in_words).to eq('zero')
    -    expect(1.in_words).to eq('one')
    -    expect(2.in_words).to eq('two')
    -    expect(3.in_words).to eq('three')
    -    expect(4.in_words).to eq('four')
    -    expect(5.in_words).to eq('five')
    -    expect(6.in_words).to eq('six')
    -    expect(7.in_words).to eq('seven')
    -    expect(8.in_words).to eq('eight')
    -    expect(9.in_words).to eq('nine')
    -  end
    -
    -  it "reads 10 to 12" do
    -    expect(10.in_words).to eq('ten')
    -    expect(11.in_words).to eq('eleven')
    -    expect(12.in_words).to eq('twelve')
    -  end
    -
    -  it "reads teens" do
    -    expect(13.in_words).to eq('thirteen')
    -    expect(14.in_words).to eq('fourteen')
    -    expect(15.in_words).to eq('fifteen')
    -    expect(16.in_words).to eq('sixteen')
    -    expect(17.in_words).to eq('seventeen')
    -    expect(18.in_words).to eq('eighteen')
    -    expect(19.in_words).to eq('nineteen')
    -  end
    -
    -  it "reads tens" do
    -    expect(20.in_words).to eq('twenty')
    -    expect(30.in_words).to eq('thirty')
    -    expect(40.in_words).to eq('forty')
    -    expect(50.in_words).to eq('fifty')
    -    expect(60.in_words).to eq('sixty')
    -    expect(70.in_words).to eq('seventy')
    -    expect(80.in_words).to eq('eighty')
    -    expect(90.in_words).to eq('ninety')
    -  end
    -
    -  it "reads various other numbers less than 100" do
    -    expect(20.in_words).to eq('twenty')
    -    expect(77.in_words).to eq('seventy seven')
    -    expect(99.in_words).to eq('ninety nine')
    -  end
    -
    -  it "reads hundreds" do
    -    expect(100.in_words).to eq('one hundred')
    -    expect(200.in_words).to eq('two hundred')
    -    expect(300.in_words).to eq('three hundred')
    -    expect(123.in_words).to eq('one hundred twenty three')
    -    expect(777.in_words).to eq('seven hundred seventy seven')
    -    expect(818.in_words).to eq('eight hundred eighteen')
    -    expect(512.in_words).to eq('five hundred twelve')
    -    expect(999.in_words).to eq('nine hundred ninety nine')
    -  end
    -
    -  it "reads thousands" do
    -    expect(1000.in_words).to eq('one thousand')
    -    expect(32767.in_words).to eq('thirty two thousand seven hundred sixty seven')
    -    expect(32768.in_words).to eq('thirty two thousand seven hundred sixty eight')
    -  end
    -
    -  it "reads millions" do
    -    expect(10_000_001.in_words).to eq('ten million one')
    -  end
    -
    -  it "reads billions" do
    -    expect(1_234_567_890.in_words).to eq('one billion two hundred thirty four million five hundred sixty seven thousand eight hundred ninety')
    -  end
    -
    -  it "reads trillions" do
    -    expect(1_000_000_000_000.in_words).to eq('one trillion')
    -    expect(1_000_000_000_001.in_words).to eq('one trillion one')
    -    expect(1_888_259_040_036.in_words).to eq('one trillion eight hundred eighty eight billion two hundred fifty nine million forty thousand thirty six')
    -  end
    -
    -end
    -
    -
    -
    - - - diff --git a/Gemfile b/Gemfile index 4831cf1c1..20e58363a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,4 @@ source "https://rubygems.org" -gem "rake" -gem "rspec", "~>3.0" - -# So you can use binding.pry anywhere in your -# script to freeze time. This happens when the -# specs run too -gem "pry-byebug" +gem 'rake', '~> 12.3' +gem 'rspec', '~> 3.4' diff --git a/Gemfile.lock b/Gemfile.lock index 1f62661aa..bbb5dd832 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,41 +1,28 @@ GEM remote: https://rubygems.org/ specs: - byebug (5.0.0) - columnize (= 0.9.0) - coderay (1.1.0) - columnize (0.9.0) - diff-lcs (1.2.5) - method_source (0.8.2) - pry (0.10.1) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - pry-byebug (3.2.0) - byebug (~> 5.0) - pry (~> 0.10) - rake (10.4.2) - rspec (3.1.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) - rspec-core (3.1.7) - rspec-support (~> 3.1.0) - rspec-expectations (3.1.2) + diff-lcs (1.3) + rake (12.3.3) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-core (3.5.4) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.1.0) - rspec-mocks (3.1.3) - rspec-support (~> 3.1.0) - rspec-support (3.1.2) - slop (3.6.0) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) PLATFORMS ruby DEPENDENCIES - pry-byebug - rake - rspec (~> 3.0) + rake (~> 12.3) + rspec (~> 3.4) BUNDLED WITH - 1.10.5 + 1.17.3 diff --git a/README.md b/README.md index 706b785e9..7e7616724 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,39 @@ Test First Ruby -- RSpec 3 Edition ========== -See [testfirst.org/learn_ruby](http://testfirst.org/learn_ruby#install) for more information about how this will work. These test-first Ruby challenges have been forked from [https://github.com/alexch/learn_ruby](https://github.com/alexch/learn_ruby) and updated to use RSpec 3 instead of RSpec 2. +### Set up instructions +1. Fork this repo +2. Clone your version of the repo to your local machine +3. On your local machine, `cd` into the root folder of this repo in your terminal +4. run `bundle install` to install all the gems this project needs. -### On a High Level +### Getting started with the exercises -Basically, you will fork this repository and then clone it onto your local computer. For each of the exercises, you will run the specs from the command line to see what tests you need to make pass (see the link above for more info about how to do that). You will then write the Ruby code that makes those tests pass and move on to the next exercise. +To work through the first exercise, follow this process +1. `cd` into `00_hello` from the root folder of this project +2. Run `rake`, to run the tests. It will fail with the following error: + ``` + Failures: -### Getting Started - -To get started, jump into the `/00_hello` directory, run `bundle install` from the command line to install the required libraries, and then view the `hello_spec.rb` file in your text editor. The comments at the top will kick things off. - -Basically, this is "error-driven development"... you'll keep running tests, hitting error messages, fixing those messages, running more tests... It is meant to not only test your Ruby skills but also get you comfortable seeing big scary looking stack traces and error messages. Most of the development you do at first will be just like this. In fact, most of *all* development is error-driven. So get comfortable with it! - + 1) the hello function says hello + Failure/Error: expect(hello).to eq("Hello!") -### Finishing Up + NameError: + undefined local variable or method `hello' for # + # ./00_hello/hello_spec.rb:106:in `block (2 levels) in ' + ``` +3. If the test fails to run and you get a `rake aborted! No Rakefile found` or any other error message not like the one above ensure that your working directory (`pwd` to see the path) contains no spaces as this is a common mistake made by people new to Rspec. +3. Read the failure output carefully and write the code that will make it pass +4. Run the tests again with `rake` +5. This will output that one test has passed and another test failure, write the code to make the next test pass. +4. Continue this process until all tests pass (when they are green) you have now completed the exercise. +5. Do this for all the exercises in this project +5. To get hints and tips about each exercise, view the `index.html` file that is included in each exercise folder -When you're done, push your changes to your forked repo and then submit a pull request to this repo so we can see your solutions and verify that you've completed the exercises. +Basically, this is "error-driven development"... you'll keep running tests, hitting error messages, fixing those messages, running more tests... It is meant to not only test your Ruby skills but also get you comfortable seeing big scary looking stack traces and error messages. Most of the development you do at first will be just like this. In fact, most of *all* development is error-driven. So get comfortable with it! ### Troubleshooting diff --git a/advanced_setup.html b/advanced_setup.html deleted file mode 100644 index 0393a7e2a..000000000 --- a/advanced_setup.html +++ /dev/null @@ -1,85 +0,0 @@ - - - Test-First Teaching: learn_ruby: learn_ruby - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    learn_ruby

    -

    Advanced Setup

    - -

    Pulling changes

    - -

    If you've been working for a while and then notice that the course repository has changed and you want the new stuff:

    - -
      -
    • View the "status" and make sure you have nothing modified

      - -
        git status
      -
    • -
    • Pull the changes

      - -
        git pull origin master
      -
    • -
    - - -

    Forking (not cloning)

    - -

    To save a copy of your own solutions in your own github repo, you'll have to "fork" the course on Github. This will give you a new git url of your very own, which you can then clone as above. For instance, if your github name is ladyhaha, your clone command is

    - -
        git clone git://github.com/ladyhaha/learn_ruby.git
    -
    - -

    To pull changes into this new repo is a little tricky and you should probably ask for help before doing it, but here's the instructions.

    - -
      -
    • Add a reference to the original remote repository

      - -
        git remote add ultrasaurus git://github.com/ultrasaurus/learn_ruby
      -
    • -
    • Pull down the remote repository's master branch. This creates a local branch called ultrasaurus/master

      - -
        git pull origin master
      -
    • -
    • Now merge the ultrasaurus/master stuff into your master branch

      - -
        git merge ultrasaurus/master
      -
    • -
    • Finally push your own master branch back to your origin remote github repository.

      - -
        git push origin master
      -
    • -
    - - -

    If you want to understand all these magical git incantations, watch this great screencast: http://blip.tv/file/4094854 (more at http://www.gitcasts.com)

    -
    - - - diff --git a/index.html b/index.html deleted file mode 100644 index 9e4c3dcf6..000000000 --- a/index.html +++ /dev/null @@ -1,224 +0,0 @@ - - - Test-First Teaching: learn_ruby: learn_ruby - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    learn_ruby

    -

    Learn Ruby Test-First

    - -

    Setup

    - -
      -
    • Install Ruby

      - -
        -
      • You will need Ruby, RubyGems and RSpec to Learn Ruby.
      • -
      • We recommend using rvm but you can use any Ruby you want. We officially support Ruby 1.9 but probably work with 1.8.7 as well.
      • -
      • Here are some good instructions for installing the required software.
      • -
      • Here are some other good instructions, using rvm.
      • -
      -
    • -
    • Open a terminal window. (On Mac OS X you can use the Terminal app.)

    • -
    • Install RSpec

      - -
        gem install rspec
      -
    • -
    • Enter the course directory. (That's the same directory that this index.html file is in.)

      - -
        cd learn_ruby
      -
    • -
    • Enter the 00_hello lab.

      - -
        cd 00_hello
      -
    • -
    • Open the lab's index.html file in a web browser and follow the instructions there.

      - -
        open index.html  # this works on Mac OS X only!
      -
    • -
    - - -

    Using These Exercises

    - -

    Your course directory has a list of lab directories. Each -directory has a spec file. You will write all the code to make all the specs -in it pass.

    - -

    To get your feet wet in this process, go into the "hello" lab with cd -00_hello and read the detailed instructions in its index.html file.

    - -

    If you got through "hello", then congratulations! Now it's time to go to the -next directory (whose name begins with 01_) and start learning Ruby!

    - -

    Course Outline

    - -

    Each course is different, so check with your instructor for details on the -curriculum he or she has chosen. Here is a survey of a few of the labs:

    - -
      -
    • hello -Gives you a feel for how to use these tests. -See 00_hello/index.html for detailed instructions.
    • -
    • temperature -Write and class and do some basic math.
    • -
    • calculator introduces a little more math, and you'll need to iterate.
    • -
    • pig_latin lets you manipulate strings.
    • -
    • in_words asks a number to say itself in English. Extend a built-in class. By the end you'll use conditionals, arrays, iteration, and maybe even some recursion.
    • -
    • blocks introduces block syntax, including yield
    • -
    - - -

    Advanced Setup

    - -

    After you're in the swing of things, you can read about advanced setup techniques like pulling changes and forking. But don't worry about it at first.

    - -

    Problems? Questions?

    - -

    First, ask your neighbor. Then, ask your instructor.

    - -

    Then ask Google (seriously!). If there's an error, try copying the error string and pasting it into a Google search box. If that doesn't help, do a search on one of these sites:

    - - - - -

    You can also find help at the TestFirst.org site or the Test-First Teaching mailing list.

    - -

    And many related lectures, notes and videos are at http://CodeLikeThis.com.

    - -

    Remember, if you post a technical question online, you should

    - -
      -
    1. Include version numbers:

      - -
       $ ruby -v
      - ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
      -
    2. -
    3. Note where you have already looked for an answer

    4. -
    5. If you can, include code snippets that reproduce the problem in isolation
    6. -
    - - -

    Solutions and Submissions

    - -

    This Github repo (learn_ruby) is generated from a different Github repo, http://github.com/ultrasaurus/test-first-teaching.

    - -

    If you want to see how other students solved the problem, go to that repo and click around. (I'm not providing a direct link because I don't want it to be too easy to cheat!)

    - -

    If you want to submit a patch or a solution, please fork the Test-First Teaching repo and submit a Pull Request from there.

    - -

    Also,

    - -

    Resources

    - -

    Here is a broad survey of many resources you may find useful. Don't try to read them all! Just browse around when you feel like learning more about Ruby.

    - -

    Learning Ruby via Tests (and/or Interactively)

    - - - - -

    Learning Ruby and Programming

    - - - - -

    Test-Driven Development

    - - - - -

    Online Ruby References

    - - - - -

    Other good resources

    - - - - -

    Credits

    - -
      -
    • Concept by Alex Chaffee
    • -
    • Exercises by Alex Chaffee, Sarah Allen, Liah Hansen, Kai Middleton
    • -
    • Early quality assurance by Sumiki, Dimitri, Liah, Michael, and Brendan
    • -
    - -
    - - - diff --git a/rspec_config.rb b/rspec_config.rb index d3b116831..fbc53440c 100644 --- a/rspec_config.rb +++ b/rspec_config.rb @@ -1,6 +1,3 @@ -# Allow people to use binding.pry with the pry-byebug gem -require 'pry-byebug' - RSpec.configure do |c| c.fail_fast = true c.color = true diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 000000000..607474b24 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,89 @@ +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause this +# file to always be loaded, without a need to explicitly require it in any files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need it. +# +# The `.rspec` file also contains a few flags that are not defaults but that +# users commonly want. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # These two settings work together to allow you to limit a spec run + # to individual examples or groups you care about by tagging them with + # `:focus` metadata. When nothing is tagged with `:focus`, all examples + # get run. + config.filter_run :focus + config.run_all_when_everything_filtered = true + + # Limits the available syntax to the non-monkey patched syntax that is recommended. + # For more details, see: + # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax + # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching + config.disable_monkey_patching! + + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + config.warnings = true + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = 'doc' + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end diff --git a/teacher_notes.html b/teacher_notes.html deleted file mode 100644 index 90b6bd679..000000000 --- a/teacher_notes.html +++ /dev/null @@ -1,125 +0,0 @@ - - - Test-First Teaching: learn_ruby: learn_ruby - - - -
    -

    TestFirst.org

    -

    the home of test-first teaching

    -
    - -

    learn_ruby

    -

    Teacher Notes

    - -

    Slides

    - -

    Some slides are in test-first-teaching/ruby_notes. They're in Markdown+Showoff format, which means they should be usable either as slides

    - -
    cd ruby_notes
    -showoff ruby_notes
    -
    - -

    or plain HTML

    - -
    cd ruby_notes
    -rdiscount *.md > index.html
    -
    - -

    Rules (for students)

    - -
      -
    • Always read the error!
    • -
    - - -

    Solutions

    - -

    The solutions branch is dead; long live the solution directory.

    - -

    To add a solution, you must put your Ruby file(s) in a directory inside the lab directory with the name solution, e.g. learn_ruby/hello/solution/hello.rb.

    - -

    Solutions only appear in the teacher repository (test-first-teaching) not the generated student repo (learn_ruby). When you run rake the tests will be run against the solutions, to assure that your code is correct.

    - -

    Make sure not to check in any cruft in the lab directory, since that will be seen by (and surely befuddle) students.

    - -

    Multiple solutions aren't supported yet.

    - -

    Notes and instructions

    - -

    Every lab has (or can have) a index.md file that the students can read. This is a good place for background, instructions and hints for solving the exercises.

    - -

    Files ending with .md (Markdown) are converted to HTML and given a .html suffix, and files ending with .scss (Sass/SCSS) are converted to CSS and given a .css suffix. Any other files will be copied over to the student repo as is.

    - -

    Lab directories become numbered; e.g. hello will become 00_hello.

    - -

    Each curriculum contains an assets directory, which is a good place to put shared files like .js and .css and images. You can refer to them using .. in your markdown files, e.g.

    - -
    ![logo](../assets/logo.gif)
    -
    - -

    This works in "preview mode" too, though it's a little weird, since .scss isn't converted into .css until the course is built using rake build.

    - -

    There's also a ubiquitous directory, whose contents are copied into each and every generated lab directory.

    - -

    Tricks

    - -

    Here are some nice git config settings:

    - -
    git config --global alias.st status
    -git config --global alias.ci commit
    -git config --global alias.co checkout
    -git config --global alias.br branch
    -git config --global alias.unadd "reset HEAD"
    -git config --global alias.l "log --oneline --decorate --graph"
    -
    -git config --global push.default matching
    -
    -git config --global color.branch=auto
    -git config --global color.diff=auto
    -git config --global color.interactive=auto
    -git config --global color.status=auto
    -
    - -

    Or, you can edit $HOME/.gitconfig -- you should have sections like this:

    - -
    [color]
    -        branch = auto
    -        diff = auto
    -        interactive = auto
    -        status = auto
    -[alias]
    -        st = status
    -        ci = commit
    -        co = checkout
    -        br = branch
    -        unadd = reset HEAD
    -        l = log --oneline --decorate --graph
    -[push]
    -        default = matching
    -
    -
    - - -