Skip to content

Instantly share code, notes, and snippets.

@peterc
Created July 11, 2011 12:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save peterc/1075747 to your computer and use it in GitHub Desktop.
Save peterc/1075747 to your computer and use it in GitHub Desktop.
testrocket: My entry to the CodeBrawl.com "Ruby testing libraries" contest
TestRocket is a simple, tiny testing library for Ruby 1.9.
If => in a hash is a "hash rocket", then +-> and --> for tests should be
"test rockets"!
Simple syntax:
+-> { block that should succeed }
--> { block that should fail }
These tests would both pass:
+-> { 2 == 2 }
--> { 10 / 0 }
See the demonstration test "suite" for more.
Unique features (I hope):
* Unary plus/minus to denote expectations.
* Ability to fit the entire library into a single tweet/single line.
# A SINGLE FILE CONTAINING THE TEST LIBRARY
# A CLASS TO TEST, AND THE TESTS THEMSELVES
# ===========================================================
# TESTROCKET TESTING LIBRARY
module TestRocket
def _test(a, b)
send((call rescue()) ? a : b)
end
def +@; puts _test :_pass, :_fail; end
def -@; puts _test :_fail, :_pass; end
def _pass; ' OK'; end
def _fail; " FAIL @ #{source_location.join(':')}"; end
end
Proc.send :include, TestRocket
# A functionally equivalent single liner. I figured you'd rather be able to read the code and output though.
# class Proc;def _t;call rescue();end;def +@;p _t ? '.' : _f; end;def -@; p _t ? _f : '.'; end;def _f; "F "+to_s;end;end
# ===========================================================
# "DIE" - Simple dice simulator for us to test
class Die
attr_reader :sides
def initialize(sides = 6)
raise ArgumentError if sides < 2
@sides = sides
end
def roll
rand(@sides) + 1
end
end
# ===========================================================
# EXAMPLE TEST "SUITE" FOR "DIE"
#
# USAGE
# +-> { block that should succeed }
# --> { block that should fail }
+-> { Die.new(2) }
--> { Die.new(1) }
+-> { (1..6) === Die.new(6).roll }
+-> { Die.new.sides == 6 }
+-> { die = Die.new(6)
1000.times { raise unless (1..6) === die.roll } }
+-> { die = Die.new(6)
1000.times { raise if die.roll.zero? } }
# These two tests will deliberately fail
+-> { raise }
--> { true }
@jeffkreeftmeijer
Copy link

I'm loving the test rocket idea and the lack of an assert method. Also, the specs are tiny. Awesome work! :)

@asaaki
Copy link

asaaki commented Jul 17, 2011

Wow, that's really cool!

@bltavares
Copy link

Awesome!

@asaaki
Copy link

asaaki commented Jul 18, 2011

I like this approach and extended this test suite a litte bit (with "description" and "pending" operators).

@petebrowne
Copy link

Woah, I haven't seen the @ part of the method definition before. What's the deal with it? Does it only work for Procs?
Would someone be so kind as to point me to the documentation for it? It's one of those things that's hard to Google...

@bltavares
Copy link

@peterbrowne I haven't seen it before also. Some googling led me to know it's overloading the unary method definition.

It means you can to things like

class String
    def !@
      "!! " << self << " !!"
    end
end
! "Hello World" # output =>  "!! Hello World !!"

@asaaki
Copy link

asaaki commented Jul 21, 2011

The @ is for the (four) unary operators, which can be overloaded.

Maybe we should read !@ like "operator in front of object", wrote another example code for showing differences.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment