I'm releasing this little script I wrote called unitirb in the hopes
that other people might find it useful. It's a hacky little
interactive unit test creator. I like it, anyway. Let's call this one
0.1.
Here's how to use it:
% unitirb -r rubylib testname.rb
unitirb starts up a regular irb session, and logs the commands and
their output to a test file named on the command line. The file can be
an existing unitirb test, or a new one is created if none exists. Once
you exit the irb session, you can re-run the session like this:
% ruby testname.rb
The commands are re-run and the output compared to what was originally
obtained. If there's any difference, the test fails.
Unitirb session scripts use Test::Unit, but they aren't too pretty.
There are lots of ways to fool unitirb, I'm sure. I've tried to handle
the most obvious and common stuff, but I can't get all the cases.
Here's one I didn't: rand. Don't do stuff like that, this is just a
stupid little script.
If you accidently hit return at the wrong time and cause a syntax
error, the errored code will be copied into the session anyway...
you'll have to remove it by hand before your test works.
I'm using (a mangled form of) #inspect to dump the results of commands
in a form that can be re-read later in another process. It would be
nice to use yaml for this instead, but I found that yaml doesn't
handle a bunch of classes that I want to work in unitirb.
unitirb:
#!/usr/bin/env ruby
···
#
# unitirb.rb - interactive ruby unit test creation
# $Release Version: 0.7.3 $
# $Revision: 1.1 $
# $Date: 2005/6/6 02:00:18 $
# Copyright 2005 by Caleb Clausen
# based on irb.rb
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
#
ARGV.push "unit" if /^-/===ARGV.last
def_inspect=<<end
class Object
#define a more stable version of inspect (for testing purposes)
alias pristine_inspect inspect
def inspect
res=pristine_inspect
res[/^#</] or return res
res=["#<",self.class,": ",instance_variables.sort.collect{|v|
[v,"=",instance_variable_get(v).inspect," "]
}]
res.last.pop
res.push('>')
res.to_s
end
end
class MatchData
def inspect
'#<MatchData: >'
end
end
end
name=ARGV.pop
/\.rb$/===name or name="test_#{name}.rb"
print "#{File.exists?(name)?"Append":"Creat"}ing file #{name}\n"
$UnitCode=File.open(name,'a')
$UnitCode.pos==0 and $UnitCode.print "require 'test/unit'\n",def_inspect
$SuiteName="T#{$UnitCode.pos}"
$UnitCode.print <<end
class #{$SuiteName} < Test::Unit::TestCase
define_method :test_unnamed do begin
end
END {
$UnitCode.print %{ rescue Test::Unit::AssertionFailedError:
raise\n rescue e: assert false, "Exception: #{ e.inspect}";\n
end end\n end\n}
$UnitCode.close
}
eval def_inspect
require "irb"
module IRB
class WorkSpace
alias evaluate__nonunit evaluate
def evaluate(context,code,file=__FILE__,line=__LINE__)
/^(__? = |[\s\t\v\f\r\n]*exit[\s\t\v\f\r\n]*$)/===code and
return(evaluate__nonunit context,code,file,line)
if /^[\s\t\v\f\r\n]*require(_gem)?[^a-zA-Z_0-9?!]/===code
$UnitCode.print(" #{code}")
return(evaluate__nonunit context,code,file,line)
end
$UnitCode.print(" _=#{code}")
result=evaluate__nonunit context,code,file,line
$UnitCode.print(' assert_equal
"'+result.inspect.gsub(/([\\"])/){|k|"\\"+k}+'"'+", _.inspect\n\n")
return result
end
end
end
if __FILE__ == $0
IRB.start(__FILE__)
else
# check -e option
if /^-e$/ =~ $0
IRB.start(__FILE__)
else
IRB.setup(__FILE__)
end
end