Skip to content

Commit

Permalink
starting to rewrite tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mattneub committed Sep 18, 2012
1 parent 8b6555d commit a4ea562
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ def [](k)
end

class Symbol # convenience methods
def downcase
self.to_s.downcase.to_sym
unless self.respond_to? :downcase # in Ruby 1.9 it is already defined for us
define_method :downcase do
self.to_s.downcase.to_sym
end
end
end

Expand Down
36 changes: 27 additions & 9 deletions RubyFrontier.tmbundle/Support/tests/tc_classof.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@

require "test/unit"

require File.dirname(File.dirname(File.expand_path(__FILE__))) + '/bin/RubyFrontier/longestJourneyUtilities.rb'

class TestClassof < Test::Unit::TestCase
def test_classof
assert_equal Object, classof(Object)
assert_equal Object, classof(Object.new)
assert_equal TestClassof, classof(self)
assert_equal TestClassof, classof(self.class)
begin
require "minitest/autorun"
rescue LoadError
require 'rubygems'
require 'minitest/autorun'
end

# classof top-level utility

class Classof < MiniTest::Spec
# class does two things: it says "here's a test" and brings "it" to life...
# and it is used as a name if there's a failure
# alternatively, can say something like:
# describe :classof do
it "returns the class when handed a class" do
classof(Object).must_be_same_as Object
classof(String).must_be_same_as String
end
it "returns the class when handed an instance" do
classof(Object.new).must_be_same_as Object
classof("howdy").must_be_same_as String
end
end
it "returns the module when handed a module" do
classof(MiniTest).must_be_same_as MiniTest
end
end


122 changes: 99 additions & 23 deletions RubyFrontier.tmbundle/Support/tests/tc_hash.rb
Original file line number Diff line number Diff line change
@@ -1,32 +1,108 @@

require "test/unit"
begin
require "minitest/autorun"
rescue LoadError
require 'rubygems'
require 'minitest/autorun'
end

require File.dirname(File.dirname(File.expand_path(__FILE__))) + '/bin/RubyFrontier/longestJourneyUtilities.rb'

class TestHash < Test::Unit::TestCase
def setup
describe Symbol do
it "responds to downcase" do
:howdy.must_equal :Howdy.downcase
:howdy.must_equal :howdy.downcase
:howdy.must_equal :hOWDY.downcase
:howdy.wont_equal :howdyy.downcase
end
end

describe Hash do
describe "fetch2" do
before do
@h = {"hey" => 1, :ho => 2, "ho" => 3}
@h2 = {"hey" => 1, "ho" => 3, :ho => 2} # different order
@h3 = Hash.new("yowee").merge @h # different empty-key default
end
it "raises unless key is symbol" do
proc {@h.fetch2("hey")}.must_raise RuntimeError
proc {@h2.fetch2("hey")}.must_raise RuntimeError
proc {@h3.fetch2("hey")}.must_raise RuntimeError
end
it "fetches string key if no symbol key exists" do
@h.fetch2(:hey).must_equal 1
@h2.fetch2(:hey).must_equal 1
# TODO: this next line fails; fetches string key only if symbol key returns nil
# according my comment, I cannot change this because to do so breaks BindingMaker
# need to figure out why and fix
# @h3.fetch2(:hey).must_equal 1
end
it "fetches symbol key if symbol key exists" do
@h.fetch2(:ho).must_equal 2
@h2.fetch2(:ho).must_equal 2
@h2.fetch2(:ho).must_equal 2
end
it "returns default if key doesn't exist" do
@h.fetch2(:ha).must_be_nil
@h2.fetch2(:ha).must_be_nil
@h3.fetch2(:ha).must_equal "yowee"
end
end
end

describe LCHash do
before do
@h = {"hey" => 1, :ho => 2, "ho" => 3}
@h2 = LCHash.new.merge @h
@h2 = {"hey" => 1, "ho" => 3, :ho => 2} # different order
@lch = LCHash.new.merge(@h)
@lch2 = LCHash.new.merge(@h2)
@lch3 = LCHash.new("yowee").merge(@h)
end
def test_symbollc # symbols are downcaseable
assert_equal(:howdy, :Howdy.downcase)
assert_equal(:howdy, :howdy.downcase)
assert_equal(:howdy, :hOWDY.downcase)
it "returns value given exact key normally" do
@lch["hey"].must_equal 1
@lch2["hey"].must_equal 1
@lch3["hey"].must_equal 1
@lch["ho"].must_equal 3
@lch2["ho"].must_equal 3
@lch3["ho"].must_equal 3
@lch[:ho].must_equal 2
@lch2[:ho].must_equal 2
@lch3[:ho].must_equal 2
end
def test_fetch2
assert_raises RuntimeError do
@h.fetch2("hey") # key must be a symbol
end
assert_equal(1, @h.fetch2(:hey)) # symbol key fetches using string key
assert_equal(2, @h.fetch2(:ho)) # symbol key works normally, prior to string
assert_nil(@h.fetch2(:ha)) # non-existent key returns nil as usual
it "returns value given key incorrectly cased" do
@lch["hEy"].must_equal 1
@lch2["Hey"].must_equal 1
@lch3["heY"].must_equal 1
@lch["hO"].must_equal 3
@lch2["Ho"].must_equal 3
@lch3["HO"].must_equal 3
@lch[:Ho].must_equal 2
@lch2[:hO].must_equal 2
@lch3[:HO].must_equal 2
end
def test_lchash # LCHash: keys work even if you throw uppercase string or symbol at it
assert_equal(1, @h2["Hey"])
assert_equal(1, @h2["hey"])
assert_equal(nil, @h["Hey"])
assert_equal(2, @h2[:Ho])
assert_equal(2, @h2[:ho])
assert_equal(nil, @h[:Ho])
describe "fetch2" do
it "raises unless key is symbol" do
proc {@lch.fetch2("hey")}.must_raise RuntimeError
proc {@lch2.fetch2("hey")}.must_raise RuntimeError
proc {@lch3.fetch2("hey")}.must_raise RuntimeError
end
it "fetches string key if no symbol key exists" do
@lch.fetch2(:Hey).must_equal 1
@lch2.fetch2(:hEy).must_equal 1
# TODO: this next line fails; fetches string key only if symbol key returns nil
# according my comment, I cannot change this because to do so breaks BindingMaker
# need to figure out why and fix
# @h3.fetch2(:heY).must_equal 1
end
it "fetches symbol key if symbol key exists" do
@lch.fetch2(:Ho).must_equal 2
@lch2.fetch2(:hO).must_equal 2
@lch2.fetch2(:HO).must_equal 2
end
it "returns default if key doesn't exist" do
@lch.fetch2(:Ha).must_be_nil
@lch2.fetch2(:hA).must_be_nil
@lch3.fetch2(:HA).must_equal "yowee"
end
end
end

170 changes: 121 additions & 49 deletions RubyFrontier.tmbundle/Support/tests/tc_memoize.rb
Original file line number Diff line number Diff line change
@@ -1,65 +1,137 @@
require "test/unit"
#require "test/unit"

require File.dirname(File.dirname(File.expand_path(__FILE__))) + '/bin/RubyFrontier/longestJourneyUtilities.rb'

class Memoizer
def initialize
@memoize = true
begin
require "minitest/autorun"
rescue LoadError
require 'rubygems'
require 'minitest/autorun'
end

#class Memoize < MiniTest::Spec
describe "memoization of a class method" do
before do
# let's memoize a class method
class Memoizer
class << self
def randy2(s)
rand
end
extend Memoizable
memoize :randy2
end
end
# let's obtain a memoized result
@origarg = "howdy"
@randy2memoized = Memoizer.randy2(@origarg)
end
def randy(s)
rand
# just for safety, we can destroy our test Memoizer class...
# ...so it doesn't wash over into the next test
after do
Object.send :remove_const, :Memoizer
end
def domem(tf)
@memoize = tf

it "gives memoized result if args are the same" do
Memoizer.randy2(@origarg).must_equal @randy2memoized
end
def showcache
@@memoized_randy
it "gives a different result if args are not the same" do
Memoizer.randy2(@origarg + "not").wont_equal @randy2memoized
end
extend Memoizable
memoize :randy
end

class Memoizer
class << self
def randy2(s)
rand
describe "memoization of a class method in a module" do
before do
# let's memoize a module method
module Memoizer
class << self
def randy3(s)
rand
end
extend Memoizable
memoize :randy3
end
end
extend Memoizable
memoize :randy2
# let's obtain a memoized result
@origarg = "howdy"
@randy3memoized = Memoizer.randy3(@origarg)
end
# just for safety, we can destroy our test Memoizer class...
# ...so it doesn't wash over into the next test
after do
Object.send :remove_const, :Memoizer
end

it "gives memoized result if args are the same" do
Memoizer.randy3(@origarg).must_equal @randy3memoized
end
it "gives a different result if args are not the same" do
Memoizer.randy3(@origarg + "not").wont_equal @randy3memoized
end
end

class TestMemoize < Test::Unit::TestCase
def test_memoize
mem = Memoizer.new
res = mem.randy("howdy")
# if args are the same, result is the same
assert_equal res, mem.randy("howdy")
# if args are not the same, result is not the same
assert_not_equal res, mem.randy("howdy2")
# backdoor on-off switch
mem.domem false
assert_not_equal res, mem.randy("howdy")
mem.domem true
assert_equal res, mem.randy("howdy")
# access original method
assert_raises(NoMethodError) do # private
mem.__unmemoized_randy__ "howdy"
describe "memoization of an instance method" do
before do
# let's memoize an instance method
class Memoizer
def randy(s)
rand
end
extend Memoizable
memoize :randy
end
# let's make an instance and obtain a memoized result
@mem = Memoizer.new
@origarg = "howdy"
@randymemoized = @mem.randy(@origarg)
# here's how to peek at the cache (class_variable_get is private in Ruby 1.8)
@the_cache = @mem.class.send :class_variable_get, :@@memoized_randy
end
# just for safety, we can destroy our test Memoizer class...
# ...so it doesn't wash over into the next test
after do
Object.send :remove_const, :Memoizer
end

it "gives memoized result if args are the same" do
@mem.randy(@origarg).must_equal @randymemoized
@mem.randy(@origarg).must_equal @mem.randy(@origarg)
end
it "gives a different result if args are not the same" do
@mem.randy(@origarg + "not").wont_equal @randymemoized
end
it "gives a different result if args are the same but backdoor switch is turned off" do
@mem.instance_variable_set :@memoize, false
@mem.randy(@origarg).wont_equal @randymemoized
@mem.randy(@origarg).wont_equal @mem.randy(@origarg)
# setting to nil is like setting to true, it turns the backdoor switch back on
@mem.instance_variable_set :@memoize, nil
@mem.randy(@origarg).must_equal @randymemoized
@mem.randy(@origarg).must_equal @mem.randy(@origarg)
@mem.instance_variable_set :@memoize, true
@mem.randy(@origarg).must_equal @randymemoized
@mem.randy(@origarg).must_equal @mem.randy(@origarg)
end

it "has privatized the original method" do
privateMethodCall = proc {@mem.__unmemoized_randy__ @origarg}
privateMethodCall.must_raise NoMethodError
privateMethodCall.call rescue $!.message.must_match(/private/)
# but of course we can bypass that privacy using send
privateMethodSend = proc {@mem.send :__unmemoized_randy__, @origarg}
privateMethodSend.call.wont_equal privateMethodSend.call
end

it "caches in a hash" do
@the_cache.must_be_instance_of Hash
end
describe "details of the hash" do
it "keys on array of args" do
@the_cache.fetch(Array(@origarg)).wont_be_nil
end
it "marshals the value" do
Marshal.load(@the_cache[Array(@origarg)]).must_equal @mem.randy(@origarg)
end
assert_not_equal res, mem.send(:__unmemoized_randy__, "howdy") # bypass privacy
# direct inspection of cache
cache = mem.showcache
assert_kind_of(Hash, cache)
assert_equal(2, cache.length) # once for howdy, once for howdy2
# direct access to contents of cache
# notice that our original args have been arrayified to form key
# contents are marshalled to prevent accidental direct mutation within cache
assert_equal res, Marshal.load(cache[Array("howdy")])
# also works for class methods
res = Memoizer.randy2("howdy")
# if args are the same, result is the same
assert_equal res, Memoizer.randy2("howdy")
# if args are not the same, result is not the same
assert_not_equal res, Memoizer.randy2("howdy2")
end
end

0 comments on commit a4ea562

Please sign in to comment.