Module: Tap::Test::ShellTest
- Includes:
- Utils
- Defined in:
- lib/tap/test/shell_test.rb,
lib/tap/test/shell_test/regexp_escape.rb
Overview
A module for testing shell scripts.
require 'test/unit'
class ShellTestSample < Test::Unit::TestCase
include Tap::Test::ShellTest
# these are the default sh_test options used
# in tests like test_sh_command_alias
self. = {
:cmd_pattern => '% inspect_argv',
:cmd => 'ruby -e "puts ARGV.inspect"'
}
def test_echo
assert_equal "goodnight moon", sh("echo goodnight moon").strip
end
def test_echo_using_sh_test
sh_test %q{
echo goodnight moon
goodnight moon
}
end
def test_sh_command_alias
sh_test("% inspect_env") do |output|
assert output !~ /NEW_ENV_VAR/
end
sh_test("NEW_ENV_VAR=blue % inspect_env") do |output|
assert output =~ /NEW_ENV_VAR=blue/
end
end
end
Defined Under Namespace
Classes: RegexpEscape
Instance Method Summary collapse
-
#assert_alike(a, b, msg = nil) ⇒ Object
Asserts whether or not b is like a (which should be a Regexp), and provides a more readable output in the case of a failure as compared with assert_match.
-
#assert_alike!(a, b, msg = nil) ⇒ Object
Same as assert_alike but without indentation stripping.
-
#assert_output_equal(a, b, msg = nil) ⇒ Object
Asserts whether or not the a and b strings are equal, with a more readable output than assert_equal for large strings (especially large strings with significant whitespace).
-
#assert_output_equal!(a, b, msg = nil) ⇒ Object
Same as assert_output_equal but without indentation stripping.
-
#quiet? ⇒ Boolean
Returns true if the ENV variable ‘QUIET’ is true or nil.
-
#setup ⇒ Object
Sets up the ShellTest module.
-
#sh(cmd, options = {}) ⇒ Object
Executes the command using IO.popen and returns the stdout content.
-
#sh_match(cmd, *regexps) {|result| ... } ⇒ Object
Similar to sh_test, but matches the output against each of the regexps.
-
#sh_test(cmd, options = {}) {|result| ... } ⇒ Object
Peforms a shell test.
-
#sh_test_options ⇒ Object
Returns a hash of default sh_test options.
-
#verbose? ⇒ Boolean
Returns true if the ENV variable ‘VERBOSE’ is true.
Instance Method Details
#assert_alike(a, b, msg = nil) ⇒ Object
Asserts whether or not b is like a (which should be a Regexp), and provides a more readable output in the case of a failure as compared with assert_match.
If a is a string, then indentation is stripped off and it is turned into a RegexpEscape. Using that syntax, all these pass:
assert_alike %q{
the time is: :...:
now!
}, "the time is: #{Time.now}\nnow!\n"
assert_alike %q{
the time is: :...:
now!
}, "the time is: #{Time.now}\nnow!\n"
assert_alike %q{
the time is: :...:
now!
}, "the time is: #{Time.now}\nnow!\n"
Use assert_alike! to prevent indentation stripping (conversion to a RegexpEscape is still in effect).
297 298 299 300 |
# File 'lib/tap/test/shell_test.rb', line 297 def assert_alike(a, b, msg=nil) a = strip_indent(a) if a.kind_of?(String) assert_alike!(a, b, msg) end |
#assert_alike!(a, b, msg = nil) ⇒ Object
Same as assert_alike but without indentation stripping.
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/tap/test/shell_test.rb', line 303 def assert_alike!(a, b, msg=nil) a = RegexpEscape.new(a) if a.kind_of?(String) if b =~ a assert true else flunk %Q{ #{msg} ================= expected output like ================== #{whitespace_escape(a)} ======================== but was ======================== #{whitespace_escape(b)} ========================================================= } end end |
#assert_output_equal(a, b, msg = nil) ⇒ Object
Asserts whether or not the a and b strings are equal, with a more readable output than assert_equal for large strings (especially large strings with significant whitespace).
One gotcha is that assert_output_equal lstrips indentation off of ‘a’, so that these all pass:
assert_output_equal %q{
line one
line two
}, "line one\nline two\n"
assert_output_equal %q{
line one
line two
}, "line one\nline two\n
assert_output_equal %q{
line one
line two
}, "line one\nline two\n"
Use the assert_output_equal! method to prevent indentation stripping.
252 253 254 255 |
# File 'lib/tap/test/shell_test.rb', line 252 def assert_output_equal(a, b, msg=nil) a = strip_indent(a) assert_output_equal!(a, b, msg) end |
#assert_output_equal!(a, b, msg = nil) ⇒ Object
Same as assert_output_equal but without indentation stripping.
258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/tap/test/shell_test.rb', line 258 def assert_output_equal!(a, b, msg=nil) if a == b assert true else flunk %Q{ #{msg} ==================== expected output ==================== #{whitespace_escape(a)} ======================== but was ======================== #{whitespace_escape(b)} ========================================================= } end end |
#quiet? ⇒ Boolean
Returns true if the ENV variable ‘QUIET’ is true or nil. When quiet, ShellTest does not print any extra information to $stdout.
If ‘VERBOSE’ and ‘QUIET’ are both set, verbose wins.
63 64 65 66 67 68 |
# File 'lib/tap/test/shell_test.rb', line 63 def quiet? return false if verbose? quiet = ENV['QUIET'] quiet.nil? || quiet =~ /^true$/i ? true : false end |
#setup ⇒ Object
Sets up the ShellTest module. Be sure to call super if you override setup in an including module.
47 48 49 50 |
# File 'lib/tap/test/shell_test.rb', line 47 def setup super @notify_method_name = true end |
#sh(cmd, options = {}) ⇒ Object
Executes the command using IO.popen and returns the stdout content.
Note
On Windows this method requires the win32-popen3 utility. If it is not available, it will have to be installed:
% gem install win32-open3
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/tap/test/shell_test.rb', line 78 def sh(cmd, ={}) if @notify_method_name && !quiet? @notify_method_name = false puts puts method_name end original_cmd = cmd if cmd_pattern = [:cmd_pattern] cmd = cmd.sub(cmd_pattern, [:cmd].to_s) end start = Time.now result = with_env([:env], [:replace_env]) do IO.popen(cmd) do |io| yield(io) if block_given? io.read end end finish = Time.now elapsed = "%.3f" % [finish-start] puts " (#{elapsed}s) #{verbose? ? cmd : original_cmd}" unless quiet? result end |
#sh_match(cmd, *regexps) {|result| ... } ⇒ Object
Similar to sh_test, but matches the output against each of the regexps. A hash of sh options can be provided as the last argument; it will be merged with the default sh_test_options.
The output is yielded to the block, if given, for further validation. Returns the sh output.
199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/tap/test/shell_test.rb', line 199 def sh_match(cmd, *regexps) = regexps.last.kind_of?(Hash) ? regexps.pop : {} = .merge() result = sh(cmd, ) regexps.each do |regexp| assert_match regexp, result, cmd end yield(result) if block_given? result end |
#sh_test(cmd, options = {}) {|result| ... } ⇒ Object
Peforms a shell test. Shell tests execute the command and yield the $stdout result to the block for validation. The command is executed through sh, ie using IO.popen.
Options provided to sh_test are merged with the sh_test_options set for the class.
Command Aliases
The options allow specification of a command pattern that gets replaced with a command alias. Only the first instance of the command pattern is replaced. In addition, shell tests allow the expected result to be specified inline with the command. Used together, these allow multiple tests of a complex command to be specified easily:
opts = {
:cmd_pattern => '% argv_inspect',
:cmd => 'ruby -e "puts ARGV.inspect"'
}
sh_test %Q{
% argv_inspect goodnight moon
["goodnight", "moon"]
}, opts
sh_test %Q{
% argv_inspect hello world
["hello", "world"]
}, opts
Indents
To improve the readability of tests, sh_test will lstrip each line in the expected output to the same degree as the command line. So for instance these all pass:
sh_test %Q{
% argv_inspect hello world
["hello", "world"]
}, opts
sh_test %Q{
% argv_inspect hello world
["hello", "world"]
}, opts
sh_test %Q{
% argv_inspect hello world
["hello", "world"]
}, opts
Turn off indent stripping by specifying :indent => false.
ENV variables
Options may specify a hash of env variables that will be set in the subprocess.
sh_test %Q{
ruby -e "puts ENV['SAMPLE']"
value
}, :env => {'SAMPLE' => 'value'}
Note it is better to specify env variables in this way rather than through the command trick ‘VAR=value cmd …’, as that syntax does not work on Windows. As a point of interest, see gist.github.com/107363 for a demonstration of ENV variables being inherited by subprocesses.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/tap/test/shell_test.rb', line 173 def sh_test(cmd, ={}) = .merge() # strip indentiation if possible if cmd =~ /\A(?:\s*?\n)?( *)(.*?\n)(.*)\z/m indent, cmd, expected = $1, $2, $3 cmd.strip! if indent.length > 0 && [:indents] expected.gsub!(/^ {0,#{indent.length}}/, '') end end result = sh(cmd, ) assert_equal(expected, result, cmd) if expected yield(result) if block_given? result end |
#sh_test_options ⇒ Object
Returns a hash of default sh_test options.
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/tap/test/shell_test.rb', line 212 def { :cmd_pattern => '% ', :cmd => '2>&1 ', :indents => true, :env => { 'TAPFILE' => nil, 'TAP_GEMS' => nil, 'TAP_PATH' => nil, 'TAPENV' => nil, 'TAPRC' => nil, 'TAP_DEBUG' => nil }, :replace_env => false } end |
#verbose? ⇒ Boolean
Returns true if the ENV variable ‘VERBOSE’ is true. When verbose, ShellTest prints the expanded commands of sh_test to $stdout.
54 55 56 57 |
# File 'lib/tap/test/shell_test.rb', line 54 def verbose? verbose = ENV['VERBOSE'] verbose && verbose =~ /^true$/i ? true : false end |