SlideShare a Scribd company logo
Test First Teaching




Alex Chaffee
@alexch
Sarah Allen
@ultrasaurus
Why should you care?

•   you want to learn Ruby
•   you want to improve your Ruby skills
•   you have a friend or colleague who wants to
    learn Ruby
•   you want to help us improve our materials
•   by teaching, you learn...
No, seriously:
by teaching, you learn!
•   the best engineers are good teachers
•   we live and work in collaborative
    environments
•   it is not enough to know any thing well
•   we must teach in order to effectively produce
    software
What is
        Test-First Teaching?
•   teacher provides microtests
•   student makes them pass
    •   one test at a time
•   can be used guided (in classroom) or solo
    •   or with a pair
Pairing Is Teaching
Pairing in the classroom




   •   students learn together and teach each other
   •   each pair can proceed through exercises at
       their own pace
   •   teacher is freed to wander the room
How do we know it's a
            good idea?
                                  2002 Alex Chaffee
                                       jGuru Java curriculum
                                  2005 Mike Clark
                 many                  Ruby Learning Tests
          independent             2006 ara.t.howard
             inventors                 Ruby Quiz #67
                                       "Metakoans"
                                  2008 Yehuda Katz
                                       & Matt Aimonetti
                                       Ruby on Rails training
                                  Who else?
http://www.flickr.com/photos/annais/9335897/sizes/z/
How do we know it's a
     good idea?


it works
Learning Ruby via Tests

•   [Test-First Teaching](http://testfirst.org)
    by Sarah Allen and Alex Chaffee
•   [Ruby Koans](http://rubykoans.com)
    by Jim Weirich and Joe O’Brien
•   [Metakoans](http://rubyquiz.com/quiz67.html)
    by ara.t.howard
Other Guided Learning
•   [ruby-warrior](http://github.com/ryanb/ruby-warrior) by Ryan
    Bates - a game written in Ruby for learning Ruby

•   [Try Ruby](http://tryruby.org) runs a Ruby interpreter in your
    browser, with hints and advice

•   [Growing OO Software In Ruby](http://www.exampler.com/
    blog/2009/12/17/growing-object-oriented-software-in-ruby/) by
    Brian Marick

    •   Ruby version of [Growing Object-Oriented Software
        Guided by Tests](http://www.growing-object-oriented-
        software.com/)
Created by:
                                              Sarah Allen
                                              Alex Chaffee
                                              Liah Hansen
                                              and friends
       Test-First Teaching....
http://testfirst.org
             Maybe we should call it Test-First Learning
http://github.com/ultrasaurus/test-first-teaching
Traditional Professional
              Programming Classes
                                                 Big, Boring Lecture
                                                 Followed by Exercises
                                                  •   multiple choice
                                                  •   fill in the blanks with words
                                                      or pseudocode
                                                  •   skeleton code - big program
                                                      with chunks excised and
                                                      replaced with comments
                                                  •   large task - soup to nuts
                                                      without feedback
.flickr.com/photos/chasephotography/3890300709/
writing code
 is engaging
Methodology

•   Run the test
•   Watch it fail
•   Write code to fix the first failure
•   See it pass
•   Refactor

    Sound familiar?
Why TFT?
•   makes the assignment very clear
•   student gets immediate feedback on progress
    (or lack thereof)
•   removes the magic
    •   leads the student through all the steps to
        writing the code
•   teaches student to read errors
Embrace Failure
Embrace Failure

•   start from a point of failure
    •   it feels like it's not your fault
•   people learn better when they're not stressed
•   playfulness enhances learning
In a classroom setting,
           do more...
•   Conceptual Overview
•   Experimentation (Play, irb)
•   Live Coding a Real-World Example
•   Simple hands-on exercise
•   Name what they learned
TFT Examples



        Let's look at some code
Arithmetic
require "calculator"

describe Calculator do

  before do
    @calculator = Calculator.new
  end

  it "adds 0 and 0" do
    @calculator.add(0,0).should == 0
  end

  it "adds 2 and 2" do
    @calculator.add(2,2).should == 4
  end

  it "adds positive numbers" do
    @calculator.add(2,6).should == 8
  end

  it "subtracts numbers" do
    @calculator.subtract(10,4).should == 6
  end
end
require "pig_latin"

describe "#translate" do
                                   Strings
  include PigLatinTranslator

  it "should translate a simple word" do
    s = translate("nix")
    s.should == "ixnay"
  end

  it "should translate a word beginning with a vowel" do
    s = translate("apple")
    s.should == "appleay"
  end

  it "should translate a word with two consonants" do
    s = translate("stupid")
    s.should == "upidstay"
  end

  it "should translate two words" do
    s = translate("eat pie")
    s.should == "eatay iepay"
  end

  it "should translate many words" do
    s = translate("the quick brown fox")
    s.should == "ethay ickquay ownbray oxfay"
  end
end
Pig Latin Solution
module PigLatinTranslator
  def translate(s)
    s.split.map do |word|
      v = first_vowel(word)
      word.slice(v..-1) + word[0,v] + "ay"
    end.join(" ")
  end

  def first_vowel(word)
    if word =~ /^qu/
      2
    else
      word.gsub(/[aeiou].*$/, '').size
    end
  end
end
Another
          Pig Latin Solution
module PigLatinTranslator
  def translate(s)
    words = s.split
      s = words.map do |s|
      l = s.length
        if /^[aeiou]/ .match(s)
            s + "ay"
        elsif /^qu/ .match(s[0..1])
             s[2..(l+1)] + s[0..1] + "ay"
        elsif /[aeiou]/ .match(s[1..1])
             s[1..(l+1)] + s[0..0] + "ay"
        else
             s[2..(l+1)] + s[0..1] + "ay"
        end
      end
      s = s.join(" ")
  end
end
And Another
             Pig Latin Solution
module PigLatinTranslator
  def translate(word)
    words = word.split(" ")
    arrResult = []
    words.each do |word|
      m = word.match(/^(qu)*[^aeiou]*/)
      if(m.nil?)
        arrResult << add_ay(word)
      else
        arrResult << add_ay(m.post_match + m.to_s)
      end
    end
    arrResult.join(" ")
  end

  def add_ay(word)
    word + "ay"
  end
end
Iterators
describe Calculator do

  before do
    @calculator = Calculator.new
  end

  describe "#sum" do
    it "computes the sum of an empty array" do
      @calculator.sum([]).should == 0
    end

    it "computes the sum of an array of one number" do
      @calculator.sum([7]).should == 7
    end

    it "computes the sum of an array of two numbers" do
      @calculator.sum([7,11]).should == 18
    end

    it "computes the sum of an array of many numbers" do
      @calculator.sum([1,3,5,7,9]).should == 25
    end
  end
Iterators
require "array_extension"

describe Array do

  describe "#sum" do
    it "should be 0 for an empty array" do
      [].sum.should == 0
    end

    it "should add all of the elements" do
      [1,2,4].sum.should == 7
    end
  end

end


            (and open classes)
TDD Extra Credit!
  # Test-Driving Bonus: once the above tests pass,
  # write tests and code for the following:

  it "multiplies two numbers"

  it "multiplies an array of numbers"

  it "raises one number to the power of another number"

  # 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"
  end

end
But...
  that's
impossible
Solutions for
 Challenging
   Idioms
        blocks
         time
   method missing
   builder pattern
Blocks
require "performance_monitor"
                                  (and mocks)             it "takes exactly 1 second to run a block that
describe PerformanceMonitor do                          sleeps for 1 second (with stubs)" do
  before do                                                 fake_time = 100
    @monitor = PerformanceMonitor.new                       Time.stub!(:now).and_return {fake_time}
  end                                                       @monitor.run do
                                                              fake_time += 1
  it "takes about 0 seconds to run an empty block" do       end.should == 1
    @monitor.run do                                       end
    end.should be_close(0, 0.1)
  end                                                     it "runs a block N times" do
                                                            n = 0
  it "takes exactly 0 seconds to run an empty block         @monitor.run(4) do
(with stubs)" do                                              n += 1
    Time.stub!(:now).and_return(100)                        end
    @monitor.run do                                         n.should == 4
    end.should == 0                                       end
  end
                                                          it "returns the average time, not the total time,
  it "takes about 1 second to run a block that sleeps   when running multiple times" do
for 1 second" do                                            run_times = [8,6,5,7]
    @monitor.run do                                         run_index = 0
      sleep 1                                               fake_time = 100
    end.should be_close(1, 0.1)                             Time.stub(:now).and_return { fake_time }
  end                                                       @monitor.run(4) do
                                                              fake_time += run_times[run_index]
                                                              run_index += 1
                                                            end.should == 6
                                                          end

                                                        end
method_missing, nested
       closures, and the builder pattern
require "xml_document"
                                                       it "nests several levels" do
describe XmlDocument do                                  @xml.hello do
  before do                                                @xml.goodbye do
    @xml = XmlDocument.new                                   @xml.come_back do
  end                                                          @xml.ok_fine(:be => "that_way")
                                                             end
  it "renders an empty tag" do                             end
    @xml.hello.should == "<hello/>"                      end.should ==
  end                                                "<hello><goodbye><come_back><ok_fine be='that_way'/
                                                     ></come_back></goodbye></hello>"
  it "renders a tag with attributes" do                end
    @xml.hello(:name => 'dolly').should == "<hello
name='dolly'/>"                                        it "indents" do
  end                                                    @xml = XmlDocument.new(true)
                                                         @xml.hello do
  it "renders a randomly named tag" do                     @xml.goodbye do
    tag_name = (1..8).map{|i|                                @xml.come_back do
('a'..'z').to_a[rand(26)]}.join                                 @xml.ok_fine(:be => "that_way")
    @xml.send(tag_name).should == "<#{tag_name}/>"           end
  end                                                      end
                                                         end.should ==
  it "renders block with text inside" do                 "<hello>n" +
    @xml.hello do                                        " <goodbye>n" +
      "dolly"                                            "     <come_back>n" +
    end.should == "<hello>dolly</hello>"                 "       <ok_fine be='that_way'/>n" +
  end                                                    "     </come_back>n" +
                                                         " </goodbye>n" +
  it "nests one level" do                                "</hello>n"
    @xml.hello do                                      end
      @xml.goodbye                                   end
    end.should == "<hello><goodbye/></hello>"
  end
threads
               (sorry for the Java)
public void testThreadSafe() throws InterruptedException
{
    int DEPOSITORS = 50;
    int AMOUNT = 2;
    // note: increase this value until it *fails* on your CPU.
    // Then fix it.
    int REPS = 25000;
    Account account = new Account("Joe", 0);
    Thread[] depositors = new Thread[DEPOSITORS];
    for (int i=0; i< DEPOSITORS; ++i) {
        depositors[i] = new Depositor(account, AMOUNT, REPS);
        depositors[i].start();
    }
    for (int i=0; i< DEPOSITORS; ++i) {
        depositors[i].join();
    }
    assertEquals(REPS * DEPOSITORS * AMOUNT, account.getBalance());
}
ruby koans


•   self-guided, test-driven
•   Ruby language basics
•   very fun, whimsical and elegant
ruby koans example
require File.expand_path(File.dirname(__FILE__) + '/edgecase')

class AboutStrings < EdgeCase::Koan
  def test_double_quoted_strings_are_strings
    string = "Hello, World"
                                                                    usually self-
    assert_equal __, string.is_a?(String)
  end                                                               contained
  def test_single_quoted_strings_are_also_strings
                                                                    just tests and fixtures,
    string = 'Goodbye, World'                                       with no class declaration
    assert_equal __, string.is_a?(String)
  end

  def test_use_single_quotes_to_create_string_with_double_quotes
                                                                    “fill in the
    string = 'He said, "Go Away."'
    assert_equal __, string                                         blanks”
  end
                                                                    technique
  def test_use_double_quotes_to_create_strings_with_single_quotes
    string = "Don't"
    assert_equal __, string
  end
                                                                    teaching through
  def test_use_backslash_for_those_hard_cases                       practice and
    a = "He said, "Don't""
    b = 'He said, "Don't"'                                         challenge
    assert_equal __, a == b
  end
TFT != TDD
•   Mechanics of testing are hard to learn
•   TFT teaches programming; TDD is design
•   At the end of some modules,
    students write their own tests for “extra
    credit”
    •   doesn’t really flex the creative muscles
        required for software design
What about TDD?
•   easier to learn TDD, post-TFT
    •   know the language
    •   know the test framework
    •   used to the rhythm of test-first
•   study design patterns, or check out [GOOS]
    (http://www.exampler.com/blog/2009/12/17/
    growing-object-oriented-software-in-ruby).
Credits
•   Mr. Clean® is a registered trademark of Procter &
    Gamble, used without permission
    •   Parody is fair use!
•   Fail Whale illustrated by Yiying Lu (http://
    www.yiyinglu.com/)
•   Pair Programming photos by Lee Lundrigan
•   Thank you Flickr and Creative Commons
    (see slides for attribution)
Sarah

Blazing Cloud
Alex
          alexch.github.com
          @alexch
Erector

Moodlog

Cohuman

 Wrong
Learning should be fun

•   Questions?

More Related Content

What's hot

Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016
Charles Nutter
 
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Charles Nutter
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for Dummies
Charles Nutter
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?
Mario Camou Riveroll
 
JavaOne 2012 - JVM JIT for Dummies
JavaOne 2012 - JVM JIT for DummiesJavaOne 2012 - JVM JIT for Dummies
JavaOne 2012 - JVM JIT for DummiesCharles Nutter
 
Oscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneOscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast Lane
Andres Almiray
 
Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Anton Arhipov
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
Paul King
 
Pg py-and-squid-pypgday
Pg py-and-squid-pypgdayPg py-and-squid-pypgday
Pg py-and-squid-pypgday
PostgreSQL Experts, Inc.
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVM
Charles Nutter
 
The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196
Mahmoud Samir Fayed
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws
loffenauer
 
Mastering Java ByteCode
Mastering Java ByteCodeMastering Java ByteCode
Mastering Java ByteCode
Ecommerce Solution Provider SysIQ
 
Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygook
Pawel Szulc
 
Why GC is eating all my CPU?
Why GC is eating all my CPU?Why GC is eating all my CPU?
Why GC is eating all my CPU?
Roman Elizarov
 
Who go Types in my Systems Programing!
Who go Types in my Systems Programing!Who go Types in my Systems Programing!
Who go Types in my Systems Programing!
Jared Roesch
 
Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passageErik Rose
 
Do more than one thing at the same time, the Python way
Do more than one thing at the same time, the Python wayDo more than one thing at the same time, the Python way
Do more than one thing at the same time, the Python wayJaime Buelta
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicGraham Dumpleton
 
JavaScript Patterns
JavaScript PatternsJavaScript Patterns
JavaScript Patterns
Stoyan Stefanov
 

What's hot (20)

Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016
 
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
 
JavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for DummiesJavaOne 2011 - JVM Bytecode for Dummies
JavaOne 2011 - JVM Bytecode for Dummies
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?
 
JavaOne 2012 - JVM JIT for Dummies
JavaOne 2012 - JVM JIT for DummiesJavaOne 2012 - JVM JIT for Dummies
JavaOne 2012 - JVM JIT for Dummies
 
Oscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneOscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast Lane
 
Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012Mastering java bytecode with ASM - GeeCON 2012
Mastering java bytecode with ASM - GeeCON 2012
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Pg py-and-squid-pypgday
Pg py-and-squid-pypgdayPg py-and-squid-pypgday
Pg py-and-squid-pypgday
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVM
 
The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws
 
Mastering Java ByteCode
Mastering Java ByteCodeMastering Java ByteCode
Mastering Java ByteCode
 
Real world gobbledygook
Real world gobbledygookReal world gobbledygook
Real world gobbledygook
 
Why GC is eating all my CPU?
Why GC is eating all my CPU?Why GC is eating all my CPU?
Why GC is eating all my CPU?
 
Who go Types in my Systems Programing!
Who go Types in my Systems Programing!Who go Types in my Systems Programing!
Who go Types in my Systems Programing!
 
Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passage
 
Do more than one thing at the same time, the Python way
Do more than one thing at the same time, the Python wayDo more than one thing at the same time, the Python way
Do more than one thing at the same time, the Python way
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New Relic
 
JavaScript Patterns
JavaScript PatternsJavaScript Patterns
JavaScript Patterns
 

Similar to Test First Teaching

Zhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With NotesZhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With Notes
ottawaruby
 
Ruby basics
Ruby basicsRuby basics
Ruby basics
Tushar Pal
 
Leveling Up at JavaScript
Leveling Up at JavaScriptLeveling Up at JavaScript
Leveling Up at JavaScript
Raymond Camden
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
Luke Donnet
 
Ruby for C# Developers
Ruby for C# DevelopersRuby for C# Developers
Ruby for C# Developers
Cory Foy
 
Brixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 RecapBrixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 Recap
Basil Bibi
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
Hiroshi SHIBATA
 
Java Tutorial
Java Tutorial Java Tutorial
Java Tutorial
Akash Pandey
 
Refactoring Workshop (Rails Pacific 2014)
Refactoring Workshop (Rails Pacific 2014)Refactoring Workshop (Rails Pacific 2014)
Refactoring Workshop (Rails Pacific 2014)
Bruce Li
 
Conf orm - explain
Conf orm - explainConf orm - explain
Conf orm - explain
Louise Grandjonc
 
Lessons Learnt in 2009
Lessons Learnt in 2009Lessons Learnt in 2009
Lessons Learnt in 2009
pratiknaik
 
ppt7
ppt7ppt7
ppt7
callroom
 
ppt2
ppt2ppt2
ppt2
callroom
 
name name2 n
name name2 nname name2 n
name name2 n
callroom
 
ppt9
ppt9ppt9
ppt9
callroom
 
Ruby for Perl Programmers
Ruby for Perl ProgrammersRuby for Perl Programmers
Ruby for Perl Programmers
amiable_indian
 
name name2 n2
name name2 n2name name2 n2
name name2 n2
callroom
 

Similar to Test First Teaching (20)

Zhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With NotesZhifu Ge - How To Be Weird In Ruby - With Notes
Zhifu Ge - How To Be Weird In Ruby - With Notes
 
Ruby basics
Ruby basicsRuby basics
Ruby basics
 
Lightning talk- testing
Lightning talk- testingLightning talk- testing
Lightning talk- testing
 
Leveling Up at JavaScript
Leveling Up at JavaScriptLeveling Up at JavaScript
Leveling Up at JavaScript
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
Ruby for C# Developers
Ruby for C# DevelopersRuby for C# Developers
Ruby for C# Developers
 
Ruby
RubyRuby
Ruby
 
Brixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 RecapBrixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 Recap
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
 
Java Tutorial
Java Tutorial Java Tutorial
Java Tutorial
 
Refactoring Workshop (Rails Pacific 2014)
Refactoring Workshop (Rails Pacific 2014)Refactoring Workshop (Rails Pacific 2014)
Refactoring Workshop (Rails Pacific 2014)
 
The Joy Of Ruby
The Joy Of RubyThe Joy Of Ruby
The Joy Of Ruby
 
Conf orm - explain
Conf orm - explainConf orm - explain
Conf orm - explain
 
Lessons Learnt in 2009
Lessons Learnt in 2009Lessons Learnt in 2009
Lessons Learnt in 2009
 
ppt7
ppt7ppt7
ppt7
 
ppt2
ppt2ppt2
ppt2
 
name name2 n
name name2 nname name2 n
name name2 n
 
ppt9
ppt9ppt9
ppt9
 
Ruby for Perl Programmers
Ruby for Perl ProgrammersRuby for Perl Programmers
Ruby for Perl Programmers
 
name name2 n2
name name2 n2name name2 n2
name name2 n2
 

More from Sarah Allen

Internet security: a landscape of unintended consequences
Internet security: a landscape of unintended consequencesInternet security: a landscape of unintended consequences
Internet security: a landscape of unintended consequences
Sarah Allen
 
RTMP: how did we get to now? (Demuxed 2019)
RTMP: how did we get to now? (Demuxed 2019)RTMP: how did we get to now? (Demuxed 2019)
RTMP: how did we get to now? (Demuxed 2019)
Sarah Allen
 
Communication is a Technical Skill
Communication is a Technical SkillCommunication is a Technical Skill
Communication is a Technical Skill
Sarah Allen
 
Improving Federal Government Services
Improving Federal Government ServicesImproving Federal Government Services
Improving Federal Government Services
Sarah Allen
 
Transparency Wins
Transparency WinsTransparency Wins
Transparency Wins
Sarah Allen
 
A Short History of Computers
A Short History of ComputersA Short History of Computers
A Short History of Computers
Sarah Allen
 
Making Software Fun
Making Software FunMaking Software Fun
Making Software Fun
Sarah Allen
 
Power of Transparency
Power of TransparencyPower of Transparency
Power of Transparency
Sarah Allen
 
Designing for Fun
Designing for FunDesigning for Fun
Designing for Fun
Sarah Allen
 
Ruby in the US Government for Ruby World Conference
Ruby in the US Government for Ruby World ConferenceRuby in the US Government for Ruby World Conference
Ruby in the US Government for Ruby World Conference
Sarah Allen
 
Identities of Dead People
Identities of Dead PeopleIdentities of Dead People
Identities of Dead People
Sarah Allen
 
Let's pretend
Let's pretendLet's pretend
Let's pretend
Sarah Allen
 
3 Reasons Not to Use Ruby
3 Reasons Not to Use Ruby 3 Reasons Not to Use Ruby
3 Reasons Not to Use Ruby
Sarah Allen
 
Ruby Nation: Why no haz Ruby?
Ruby Nation: Why no haz Ruby?Ruby Nation: Why no haz Ruby?
Ruby Nation: Why no haz Ruby?
Sarah Allen
 
Why no ruby in gov?
Why no ruby in gov?Why no ruby in gov?
Why no ruby in gov?
Sarah Allen
 
People Patterns or What I learned from Toastmasters
People Patterns or What I learned from ToastmastersPeople Patterns or What I learned from Toastmasters
People Patterns or What I learned from Toastmasters
Sarah Allen
 
Blazing Cloud: Agile Product Development
Blazing Cloud: Agile Product DevelopmentBlazing Cloud: Agile Product Development
Blazing Cloud: Agile Product Development
Sarah Allen
 
Crowdsourced Transcription Landscape
Crowdsourced Transcription LandscapeCrowdsourced Transcription Landscape
Crowdsourced Transcription Landscape
Sarah Allen
 
Lessons Learned Future Thoughts
Lessons Learned Future ThoughtsLessons Learned Future Thoughts
Lessons Learned Future Thoughts
Sarah Allen
 
Mobile Web Video
Mobile Web VideoMobile Web Video
Mobile Web Video
Sarah Allen
 

More from Sarah Allen (20)

Internet security: a landscape of unintended consequences
Internet security: a landscape of unintended consequencesInternet security: a landscape of unintended consequences
Internet security: a landscape of unintended consequences
 
RTMP: how did we get to now? (Demuxed 2019)
RTMP: how did we get to now? (Demuxed 2019)RTMP: how did we get to now? (Demuxed 2019)
RTMP: how did we get to now? (Demuxed 2019)
 
Communication is a Technical Skill
Communication is a Technical SkillCommunication is a Technical Skill
Communication is a Technical Skill
 
Improving Federal Government Services
Improving Federal Government ServicesImproving Federal Government Services
Improving Federal Government Services
 
Transparency Wins
Transparency WinsTransparency Wins
Transparency Wins
 
A Short History of Computers
A Short History of ComputersA Short History of Computers
A Short History of Computers
 
Making Software Fun
Making Software FunMaking Software Fun
Making Software Fun
 
Power of Transparency
Power of TransparencyPower of Transparency
Power of Transparency
 
Designing for Fun
Designing for FunDesigning for Fun
Designing for Fun
 
Ruby in the US Government for Ruby World Conference
Ruby in the US Government for Ruby World ConferenceRuby in the US Government for Ruby World Conference
Ruby in the US Government for Ruby World Conference
 
Identities of Dead People
Identities of Dead PeopleIdentities of Dead People
Identities of Dead People
 
Let's pretend
Let's pretendLet's pretend
Let's pretend
 
3 Reasons Not to Use Ruby
3 Reasons Not to Use Ruby 3 Reasons Not to Use Ruby
3 Reasons Not to Use Ruby
 
Ruby Nation: Why no haz Ruby?
Ruby Nation: Why no haz Ruby?Ruby Nation: Why no haz Ruby?
Ruby Nation: Why no haz Ruby?
 
Why no ruby in gov?
Why no ruby in gov?Why no ruby in gov?
Why no ruby in gov?
 
People Patterns or What I learned from Toastmasters
People Patterns or What I learned from ToastmastersPeople Patterns or What I learned from Toastmasters
People Patterns or What I learned from Toastmasters
 
Blazing Cloud: Agile Product Development
Blazing Cloud: Agile Product DevelopmentBlazing Cloud: Agile Product Development
Blazing Cloud: Agile Product Development
 
Crowdsourced Transcription Landscape
Crowdsourced Transcription LandscapeCrowdsourced Transcription Landscape
Crowdsourced Transcription Landscape
 
Lessons Learned Future Thoughts
Lessons Learned Future ThoughtsLessons Learned Future Thoughts
Lessons Learned Future Thoughts
 
Mobile Web Video
Mobile Web VideoMobile Web Video
Mobile Web Video
 

Recently uploaded

Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
Bhaskar Mitra
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 

Recently uploaded (20)

Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 

Test First Teaching

  • 1. Test First Teaching Alex Chaffee @alexch Sarah Allen @ultrasaurus
  • 2. Why should you care? • you want to learn Ruby • you want to improve your Ruby skills • you have a friend or colleague who wants to learn Ruby • you want to help us improve our materials • by teaching, you learn...
  • 3. No, seriously: by teaching, you learn! • the best engineers are good teachers • we live and work in collaborative environments • it is not enough to know any thing well • we must teach in order to effectively produce software
  • 4. What is Test-First Teaching? • teacher provides microtests • student makes them pass • one test at a time • can be used guided (in classroom) or solo • or with a pair
  • 6. Pairing in the classroom • students learn together and teach each other • each pair can proceed through exercises at their own pace • teacher is freed to wander the room
  • 7. How do we know it's a good idea? 2002 Alex Chaffee jGuru Java curriculum 2005 Mike Clark many Ruby Learning Tests independent 2006 ara.t.howard inventors Ruby Quiz #67 "Metakoans" 2008 Yehuda Katz & Matt Aimonetti Ruby on Rails training Who else? http://www.flickr.com/photos/annais/9335897/sizes/z/
  • 8. How do we know it's a good idea? it works
  • 9. Learning Ruby via Tests • [Test-First Teaching](http://testfirst.org) by Sarah Allen and Alex Chaffee • [Ruby Koans](http://rubykoans.com) by Jim Weirich and Joe O’Brien • [Metakoans](http://rubyquiz.com/quiz67.html) by ara.t.howard
  • 10. Other Guided Learning • [ruby-warrior](http://github.com/ryanb/ruby-warrior) by Ryan Bates - a game written in Ruby for learning Ruby • [Try Ruby](http://tryruby.org) runs a Ruby interpreter in your browser, with hints and advice • [Growing OO Software In Ruby](http://www.exampler.com/ blog/2009/12/17/growing-object-oriented-software-in-ruby/) by Brian Marick • Ruby version of [Growing Object-Oriented Software Guided by Tests](http://www.growing-object-oriented- software.com/)
  • 11. Created by: Sarah Allen Alex Chaffee Liah Hansen and friends Test-First Teaching.... http://testfirst.org Maybe we should call it Test-First Learning http://github.com/ultrasaurus/test-first-teaching
  • 12. Traditional Professional Programming Classes Big, Boring Lecture Followed by Exercises • multiple choice • fill in the blanks with words or pseudocode • skeleton code - big program with chunks excised and replaced with comments • large task - soup to nuts without feedback .flickr.com/photos/chasephotography/3890300709/
  • 13. writing code is engaging
  • 14. Methodology • Run the test • Watch it fail • Write code to fix the first failure • See it pass • Refactor Sound familiar?
  • 15.
  • 16. Why TFT? • makes the assignment very clear • student gets immediate feedback on progress (or lack thereof) • removes the magic • leads the student through all the steps to writing the code • teaches student to read errors
  • 18. Embrace Failure • start from a point of failure • it feels like it's not your fault • people learn better when they're not stressed • playfulness enhances learning
  • 19. In a classroom setting, do more... • Conceptual Overview • Experimentation (Play, irb) • Live Coding a Real-World Example • Simple hands-on exercise • Name what they learned
  • 20. TFT Examples Let's look at some code
  • 21. Arithmetic require "calculator" describe Calculator do before do @calculator = Calculator.new end it "adds 0 and 0" do @calculator.add(0,0).should == 0 end it "adds 2 and 2" do @calculator.add(2,2).should == 4 end it "adds positive numbers" do @calculator.add(2,6).should == 8 end it "subtracts numbers" do @calculator.subtract(10,4).should == 6 end end
  • 22.
  • 23. require "pig_latin" describe "#translate" do Strings include PigLatinTranslator it "should translate a simple word" do s = translate("nix") s.should == "ixnay" end it "should translate a word beginning with a vowel" do s = translate("apple") s.should == "appleay" end it "should translate a word with two consonants" do s = translate("stupid") s.should == "upidstay" end it "should translate two words" do s = translate("eat pie") s.should == "eatay iepay" end it "should translate many words" do s = translate("the quick brown fox") s.should == "ethay ickquay ownbray oxfay" end end
  • 24. Pig Latin Solution module PigLatinTranslator def translate(s) s.split.map do |word| v = first_vowel(word) word.slice(v..-1) + word[0,v] + "ay" end.join(" ") end def first_vowel(word) if word =~ /^qu/ 2 else word.gsub(/[aeiou].*$/, '').size end end end
  • 25. Another Pig Latin Solution module PigLatinTranslator def translate(s) words = s.split s = words.map do |s| l = s.length if /^[aeiou]/ .match(s) s + "ay" elsif /^qu/ .match(s[0..1]) s[2..(l+1)] + s[0..1] + "ay" elsif /[aeiou]/ .match(s[1..1]) s[1..(l+1)] + s[0..0] + "ay" else s[2..(l+1)] + s[0..1] + "ay" end end s = s.join(" ") end end
  • 26. And Another Pig Latin Solution module PigLatinTranslator def translate(word) words = word.split(" ") arrResult = [] words.each do |word| m = word.match(/^(qu)*[^aeiou]*/) if(m.nil?) arrResult << add_ay(word) else arrResult << add_ay(m.post_match + m.to_s) end end arrResult.join(" ") end def add_ay(word) word + "ay" end end
  • 27. Iterators describe Calculator do before do @calculator = Calculator.new end describe "#sum" do it "computes the sum of an empty array" do @calculator.sum([]).should == 0 end it "computes the sum of an array of one number" do @calculator.sum([7]).should == 7 end it "computes the sum of an array of two numbers" do @calculator.sum([7,11]).should == 18 end it "computes the sum of an array of many numbers" do @calculator.sum([1,3,5,7,9]).should == 25 end end
  • 28. Iterators require "array_extension" describe Array do describe "#sum" do it "should be 0 for an empty array" do [].sum.should == 0 end it "should add all of the elements" do [1,2,4].sum.should == 7 end end end (and open classes)
  • 29. TDD Extra Credit! # Test-Driving Bonus: once the above tests pass, # write tests and code for the following: it "multiplies two numbers" it "multiplies an array of numbers" it "raises one number to the power of another number" # 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" end end
  • 31. Solutions for Challenging Idioms blocks time method missing builder pattern
  • 32. Blocks require "performance_monitor" (and mocks) it "takes exactly 1 second to run a block that describe PerformanceMonitor do sleeps for 1 second (with stubs)" do before do fake_time = 100 @monitor = PerformanceMonitor.new Time.stub!(:now).and_return {fake_time} end @monitor.run do fake_time += 1 it "takes about 0 seconds to run an empty block" do end.should == 1 @monitor.run do end end.should be_close(0, 0.1) end it "runs a block N times" do n = 0 it "takes exactly 0 seconds to run an empty block @monitor.run(4) do (with stubs)" do n += 1 Time.stub!(:now).and_return(100) end @monitor.run do n.should == 4 end.should == 0 end end it "returns the average time, not the total time, it "takes about 1 second to run a block that sleeps when running multiple times" do for 1 second" do run_times = [8,6,5,7] @monitor.run do run_index = 0 sleep 1 fake_time = 100 end.should be_close(1, 0.1) Time.stub(:now).and_return { fake_time } end @monitor.run(4) do fake_time += run_times[run_index] run_index += 1 end.should == 6 end end
  • 33. method_missing, nested closures, and the builder pattern require "xml_document" it "nests several levels" do describe XmlDocument do @xml.hello do before do @xml.goodbye do @xml = XmlDocument.new @xml.come_back do end @xml.ok_fine(:be => "that_way") end it "renders an empty tag" do end @xml.hello.should == "<hello/>" end.should == end "<hello><goodbye><come_back><ok_fine be='that_way'/ ></come_back></goodbye></hello>" it "renders a tag with attributes" do end @xml.hello(:name => 'dolly').should == "<hello name='dolly'/>" it "indents" do end @xml = XmlDocument.new(true) @xml.hello do it "renders a randomly named tag" do @xml.goodbye do tag_name = (1..8).map{|i| @xml.come_back do ('a'..'z').to_a[rand(26)]}.join @xml.ok_fine(:be => "that_way") @xml.send(tag_name).should == "<#{tag_name}/>" end end end end.should == it "renders block with text inside" do "<hello>n" + @xml.hello do " <goodbye>n" + "dolly" " <come_back>n" + end.should == "<hello>dolly</hello>" " <ok_fine be='that_way'/>n" + end " </come_back>n" + " </goodbye>n" + it "nests one level" do "</hello>n" @xml.hello do end @xml.goodbye end end.should == "<hello><goodbye/></hello>" end
  • 34. threads (sorry for the Java) public void testThreadSafe() throws InterruptedException { int DEPOSITORS = 50; int AMOUNT = 2; // note: increase this value until it *fails* on your CPU. // Then fix it. int REPS = 25000; Account account = new Account("Joe", 0); Thread[] depositors = new Thread[DEPOSITORS]; for (int i=0; i< DEPOSITORS; ++i) { depositors[i] = new Depositor(account, AMOUNT, REPS); depositors[i].start(); } for (int i=0; i< DEPOSITORS; ++i) { depositors[i].join(); } assertEquals(REPS * DEPOSITORS * AMOUNT, account.getBalance()); }
  • 35. ruby koans • self-guided, test-driven • Ruby language basics • very fun, whimsical and elegant
  • 36. ruby koans example require File.expand_path(File.dirname(__FILE__) + '/edgecase') class AboutStrings < EdgeCase::Koan def test_double_quoted_strings_are_strings string = "Hello, World" usually self- assert_equal __, string.is_a?(String) end contained def test_single_quoted_strings_are_also_strings just tests and fixtures, string = 'Goodbye, World' with no class declaration assert_equal __, string.is_a?(String) end def test_use_single_quotes_to_create_string_with_double_quotes “fill in the string = 'He said, "Go Away."' assert_equal __, string blanks” end technique def test_use_double_quotes_to_create_strings_with_single_quotes string = "Don't" assert_equal __, string end teaching through def test_use_backslash_for_those_hard_cases practice and a = "He said, "Don't"" b = 'He said, "Don't"' challenge assert_equal __, a == b end
  • 37. TFT != TDD • Mechanics of testing are hard to learn • TFT teaches programming; TDD is design • At the end of some modules, students write their own tests for “extra credit” • doesn’t really flex the creative muscles required for software design
  • 38. What about TDD? • easier to learn TDD, post-TFT • know the language • know the test framework • used to the rhythm of test-first • study design patterns, or check out [GOOS] (http://www.exampler.com/blog/2009/12/17/ growing-object-oriented-software-in-ruby).
  • 39. Credits • Mr. Clean® is a registered trademark of Procter & Gamble, used without permission • Parody is fair use! • Fail Whale illustrated by Yiying Lu (http:// www.yiyinglu.com/) • Pair Programming photos by Lee Lundrigan • Thank you Flickr and Creative Commons (see slides for attribution)
  • 41. Alex alexch.github.com @alexch Erector Moodlog Cohuman Wrong
  • 42. Learning should be fun • Questions?

Editor's Notes

  1. TFT is not sufficient for learning, but needs to be one component of a curriculum or course of self-study.