shell_test 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ == 0.1.0 2011/07/07
2
+
3
+ Initial release.
4
+
5
+ Much of this code started in the {Tap-Test}[http://rubygems.org/gems/tap-test]
6
+ gem and was later added-to by Linecook[http://rubygems.org/gems/linecook]. It
7
+ has long wished to be it's own gem, and now it is.
data/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011, Simon Chiang.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,146 @@
1
+ = ShellTest
2
+
3
+ Test modules for shell scripts.
4
+
5
+ == Description
6
+
7
+ Provides test modules to simplify testing of shell scripts.
8
+
9
+ ShellTest is not a testing framework. ShellTest integrates with Test::Unit and
10
+ MiniTest out of the box, but it should be possible to include the test modules
11
+ into other test frameworks.
12
+
13
+ == Usage
14
+
15
+ ShellTest builds on modules that provide specific functionality. The modules
16
+ may be used independently, but by including ShellTest you get them all:
17
+
18
+ require 'shell_test/unit'
19
+
20
+ class ShellTestExample < Test::Unit::TestCase
21
+ include ShellTest
22
+
23
+ def test_a_script
24
+ script = prepare('script.sh') do |io|
25
+ io.puts "echo goodnight $1"
26
+ end
27
+
28
+ assert_script %{
29
+ $ sh '#{script}' moon
30
+ goodnight moon
31
+ }
32
+ end
33
+ end
34
+
35
+ ==== {ShellMethods}[link:classes/ShellTest/ShellMethods.html]
36
+
37
+ Provides the shell testing methods. These methods are designed to input a
38
+ string that looks like terminal input/output. Commands are parsed out of the
39
+ string, run, and then anything printed to stdout is compared to the expected
40
+ output. In addition the exit status is checked for success (0).
41
+
42
+ Special comments following the first line of a command can turn off
43
+ output/status checking, or specify a different exit status to expect.
44
+
45
+ require 'shell_test/unit'
46
+
47
+ class ShellMethodsExample < Test::Unit::TestCase
48
+ include ShellTest::ShellMethods
49
+
50
+ def test_a_script_using_variables
51
+ with_env("THING" => "moon") do
52
+ assert_script %{
53
+ $ echo "goodnight $THING"
54
+ goodnight moon
55
+ }
56
+ end
57
+ end
58
+
59
+ def test_multiple_commands
60
+ assert_script %{
61
+ $ echo one
62
+ one
63
+ $ echo two
64
+ two
65
+ }
66
+ end
67
+
68
+ def test_multiline_commands
69
+ assert_script %{
70
+ $ for n in one two; do
71
+ > echo $n
72
+ > done
73
+ one
74
+ two
75
+ }
76
+ end
77
+
78
+ def test_exit_statuses
79
+ assert_script %{
80
+ $ true # [0]
81
+ $ false # [1]
82
+ }
83
+ end
84
+
85
+ def test_exit_status_and_not_ouptut
86
+ assert_script %{
87
+ $ date # [0] ...
88
+ }
89
+ end
90
+
91
+ def test_output_with_inline_regexps
92
+ assert_script_match %{
93
+ $ cal
94
+ :...:
95
+ Su Mo Tu We Th Fr Sa
96
+ :...:
97
+ }
98
+ end
99
+ end
100
+
101
+ ==== {FileMethods}[link:classes/ShellTest/FileMethods.html]
102
+
103
+ Sets up a temporary, test-specific directory for working with files. This
104
+ approach is better in most cases than using Tempfile because you can flag the
105
+ directory to be saved on a failure (using ENV['KEEP_OUTPUTS']='true').
106
+
107
+ By default the directory is guessed based off of the test file and test
108
+ method. If this example were located in the 'test/file_methods_example.rb'
109
+ file, then the directory for the test case would be
110
+ 'test/file_methods_example/test_preparation_of_a_test_specific_file'.
111
+
112
+ require 'shell_test/unit'
113
+
114
+ class FileMethodsExample < Test::Unit::TestCase
115
+ include ShellTest::FileMethods
116
+
117
+ def test_preparation_of_a_test_specific_file
118
+ path = prepare('dir/file.txt') {|io| io << 'content' }
119
+ assert_equal "content", File.read(path)
120
+ end
121
+ end
122
+
123
+ == Installation
124
+
125
+ ShellTest is available as a gem[http://rubygems.org/gems/shell_test].
126
+
127
+ $ gem install shell_test
128
+
129
+ == Development
130
+
131
+ To get started, checkout the code from GitHub[http://github.com/thinkerbot/shell_test] and run:
132
+
133
+ git clone https://thinkerbot@github.com/thinkerbot/shell_test.git
134
+ cd shell_test
135
+ rake test
136
+
137
+ To test against multiple platforms I suggest using rvm. In that case:
138
+
139
+ rvm rake test
140
+
141
+ Please report any issues {here}[http://github.com/thinkerbot/shell_test/issues].
142
+
143
+ == Info
144
+
145
+ Developer:: {Simon Chiang}[http://thinkerbot.posterous.com]
146
+ License:: {MIT-Style}[link:files/MIT-LICENSE.html]
@@ -0,0 +1,67 @@
1
+ module ShellTest
2
+ class CommandParser
3
+ attr_reader :ps1
4
+ attr_reader :ps2
5
+
6
+ def initialize(options={})
7
+ options = {
8
+ :ps1 => '$ ',
9
+ :ps2 => '> '
10
+ }.merge(options)
11
+
12
+ @ps1 = options[:ps1]
13
+ @ps2 = options[:ps2]
14
+ end
15
+
16
+ def parse_cmd(cmd)
17
+ cmd =~ /.*?#\s*(?:\[(\d+)\])?\s*(\.{3})?/
18
+ exit_status = $1 ? $1.to_i : 0
19
+ output = $2 ? nil : ""
20
+
21
+ [cmd, output, exit_status]
22
+ end
23
+
24
+ def parse(script)
25
+ commands = []
26
+
27
+ command, output, exit_status = nil, "", 0
28
+ script.each_line do |line|
29
+ case
30
+ when line.index(ps1) == 0
31
+ if command
32
+ commands << [command, output, exit_status]
33
+ end
34
+
35
+ command, output, exit_status = parse_cmd lchomp(ps1, line)
36
+
37
+ when command.nil?
38
+ unless line.strip.empty?
39
+ command, output, exit_status = parse_cmd(line)
40
+ end
41
+
42
+ when line.index(ps2) == 0
43
+ command << lchomp(ps2, line)
44
+
45
+ when output.nil?
46
+ output = line
47
+
48
+ else
49
+ output << line
50
+ end
51
+ end
52
+
53
+ if command
54
+ commands << [command, output, exit_status]
55
+ end
56
+
57
+ commands
58
+ end
59
+
60
+ private
61
+
62
+ def lchomp(prefix, line) # :nodoc:
63
+ length = prefix.length
64
+ line[length, line.length - length]
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,208 @@
1
+ require 'fileutils'
2
+
3
+ module ShellTest
4
+ module FileMethods
5
+ module ClassMethods
6
+ attr_accessor :class_dir
7
+
8
+ attr_reader :cleanup_method_registry
9
+
10
+ def cleanup_methods
11
+ @cleanup_methods ||= begin
12
+ cleanup_methods = {}
13
+
14
+ ancestors.reverse.each do |ancestor|
15
+ next unless ancestor.kind_of?(ClassMethods)
16
+ ancestor.cleanup_method_registry.each_pair do |key, value|
17
+ if value.nil?
18
+ cleanup_methods.delete(key)
19
+ else
20
+ cleanup_methods[key] = value
21
+ end
22
+ end
23
+ end
24
+
25
+ cleanup_methods
26
+ end
27
+ end
28
+
29
+ def reset_cleanup_methods
30
+ @cleanup_methods = nil
31
+ end
32
+
33
+ protected
34
+
35
+ def self.initialize(base)
36
+ # Infers the test directory from the calling file.
37
+ # 'some_class_test.rb' => 'some_class_test'
38
+ call_line = caller.find {|value| value !~ /`(includ|inherit|extend)ed'$/ }
39
+
40
+ if call_line
41
+ calling_file = call_line.gsub(/:\d+(:in .*)?$/, "")
42
+ base.class_dir = calling_file.chomp(File.extname(calling_file))
43
+ else
44
+ unless Dir.respond_to?(:tmpdir)
45
+ require 'tmpdir'
46
+ end
47
+ base.class_dir = Dir.tmpdir
48
+ end
49
+
50
+ base.reset_cleanup_methods
51
+ unless base.instance_variable_defined?(:@cleanup_method_registry)
52
+ base.instance_variable_set(:@cleanup_method_registry, {})
53
+ end
54
+
55
+ unless base.instance_variable_defined?(:@cleanup_paths)
56
+ base.instance_variable_set(:@cleanup_paths, ['.'])
57
+ end
58
+
59
+ unless base.instance_variable_defined?(:@cleanup)
60
+ base.instance_variable_set(:@cleanup, true)
61
+ end
62
+ end
63
+
64
+ def inherited(base) # :nodoc:
65
+ ClassMethods.initialize(base)
66
+ super
67
+ end
68
+
69
+ def define_method_cleanup(method_name, dirs)
70
+ reset_cleanup_methods
71
+ cleanup_method_registry[method_name.to_sym] = dirs
72
+ end
73
+
74
+ def remove_method_cleanup(method_name)
75
+ reset_cleanup_methods
76
+ cleanup_method_registry.delete(method_name.to_sym)
77
+ end
78
+
79
+ def undef_method_cleanup(method_name)
80
+ reset_cleanup_methods
81
+ cleanup_method_registry[method_name.to_sym] = nil
82
+ end
83
+
84
+ def cleanup_paths(*dirs)
85
+ @cleanup_paths = dirs
86
+ end
87
+
88
+ def cleanup(*method_names)
89
+ if method_names.empty?
90
+ @cleanup = true
91
+ else
92
+ method_names.each do |method_name|
93
+ define_method_cleanup method_name, @cleanup_paths
94
+ end
95
+ end
96
+ end
97
+
98
+ def no_cleanup(*method_names)
99
+ if method_names.empty?
100
+ @cleanup = false
101
+ else
102
+ method_names.each do |method_name|
103
+ undef_method_cleanup method_name
104
+ end
105
+ end
106
+ end
107
+
108
+ def method_added(sym)
109
+ if @cleanup && !cleanup_method_registry.has_key?(sym.to_sym) && sym.to_s[0, 5] == "test_"
110
+ cleanup sym
111
+ end
112
+ end
113
+ end
114
+
115
+ module ModuleMethods
116
+ module_function
117
+
118
+ def included(base)
119
+ base.extend ClassMethods
120
+ base.extend ModuleMethods unless base.kind_of?(Class)
121
+
122
+ ClassMethods.initialize(base)
123
+ super
124
+ end
125
+ end
126
+
127
+ extend ModuleMethods
128
+
129
+ def setup
130
+ super
131
+ cleanup
132
+ end
133
+
134
+ def teardown
135
+ Dir.chdir(user_dir)
136
+
137
+ unless ENV["KEEP_OUTPUTS"] == "true"
138
+ cleanup
139
+
140
+ dir = method_dir
141
+ while dir != class_dir
142
+ dir = File.dirname(dir)
143
+ Dir.rmdir(dir)
144
+ end rescue(SystemCallError)
145
+ end
146
+
147
+ super
148
+ end
149
+
150
+ def user_dir
151
+ @user_dir ||= File.expand_path('.')
152
+ end
153
+
154
+ def class_dir
155
+ @class_dir ||= File.expand_path(self.class.class_dir, user_dir)
156
+ end
157
+
158
+ def method_dir
159
+ @method_dir ||= File.expand_path(method_name.to_s, class_dir)
160
+ end
161
+
162
+ def method_name
163
+ __name__
164
+ end
165
+
166
+ def cleanup_methods
167
+ self.class.cleanup_methods
168
+ end
169
+
170
+ def cleanup
171
+ if cleanup_paths = cleanup_methods[method_name.to_sym]
172
+ cleanup_paths.each {|relative_path| remove(relative_path) }
173
+ end
174
+ end
175
+
176
+ def path(relative_path)
177
+ path = File.expand_path(relative_path, method_dir)
178
+
179
+ unless path.index(method_dir) == 0
180
+ raise "does not make a path relative to method_dir: #{relative_path.inspect}"
181
+ end
182
+
183
+ path
184
+ end
185
+
186
+ def prepare(relative_path, content=nil, &block)
187
+ target = path(relative_path)
188
+
189
+ if File.exists?(target)
190
+ FileUtils.rm(target)
191
+ else
192
+ target_dir = File.dirname(target)
193
+ FileUtils.mkdir_p(target_dir) unless File.exists?(target_dir)
194
+ end
195
+
196
+ FileUtils.touch(target)
197
+ File.open(target, 'w') {|io| io << content } if content
198
+ File.open(target, 'a', &block) if block
199
+
200
+ target
201
+ end
202
+
203
+ def remove(relative_path)
204
+ full_path = path(relative_path)
205
+ FileUtils.rm_r(full_path) if File.exists?(full_path)
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,84 @@
1
+ module ShellTest
2
+ # RegexpEscape is a subclass of regexp that escapes all but the text in a
3
+ # special escape sequence. This allows the creation of complex regexps
4
+ # to match, for instance, console output.
5
+ #
6
+ # The RegexpEscape.escape (or equivalently the quote) method does the
7
+ # work; all regexp-active characters are escaped except for characters
8
+ # enclosed by ':.' and '.:' delimiters.
9
+ #
10
+ # RegexpEscape.escape('reg[exp]+ chars. are(quoted)') # => 'reg\[exp\]\+\ chars\.\ are\(quoted\)'
11
+ # RegexpEscape.escape('these are not: :.a(b*)c.:') # => 'these\ are\ not:\ a(b*)c'
12
+ #
13
+ # In addition, all-period regexps are automatically upgraded to '.*?';
14
+ # use the '.{n}' notation to specify n arbitrary characters.
15
+ #
16
+ # RegexpEscape.escape('_:..:_:...:_:....:') # => '_.*?_.*?_.*?'
17
+ # RegexpEscape.escape(':..{1}.:') # => '.{1}'
18
+ #
19
+ # RegexpEscape instances are initialized using the escaped input string
20
+ # and return the original string upon to_s.
21
+ #
22
+ # str = %q{
23
+ # a multiline
24
+ # :...:
25
+ # example}
26
+ # r = RegexpEscape.new(str)
27
+ #
28
+ # r =~ %q{
29
+ # a multiline
30
+ # matching
31
+ # example} # => true
32
+ #
33
+ # r !~ %q{
34
+ # a failing multiline
35
+ # example} # => true
36
+ #
37
+ # r.to_s # => str
38
+ #
39
+ class RegexpEscape < Regexp
40
+
41
+ # matches the escape sequence
42
+ ESCAPE_SEQUENCE = /:\..*?\.:/
43
+
44
+ class << self
45
+
46
+ # Escapes regexp-active characters in str, except for character
47
+ # delimited by ':.' and '.:'. See the class description for
48
+ # details.
49
+ def escape(str)
50
+ substituents = []
51
+ str.scan(ESCAPE_SEQUENCE) do
52
+ regexp_str = $&[2...-2]
53
+ regexp_str = ".*?" if regexp_str =~ /^\.*$/
54
+ substituents << regexp_str
55
+ end
56
+ substituents << ""
57
+
58
+ splits = str.split(ESCAPE_SEQUENCE).collect do |split|
59
+ super(split)
60
+ end
61
+ splits << "" if splits.empty?
62
+
63
+ splits.zip(substituents).to_a.flatten.join
64
+ end
65
+
66
+ # Same as escape.
67
+ def quote(str)
68
+ escape(str)
69
+ end
70
+ end
71
+
72
+ # Generates a new RegexpEscape by escaping the str, using the same
73
+ # options as Regexp.
74
+ def initialize(str, *options)
75
+ super(RegexpEscape.escape(str), *options)
76
+ @original_str = str
77
+ end
78
+
79
+ # Returns the original string for self
80
+ def to_s
81
+ @original_str
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,176 @@
1
+ require 'shell_test/regexp_escape'
2
+ require 'shell_test/command_parser'
3
+
4
+ module ShellTest
5
+ module ShellMethods
6
+ def setup
7
+ super
8
+ @notify_method_name = true
9
+ end
10
+
11
+ # Parse a script into an array of [cmd, output, status] triplets.
12
+ def parse_script(script, options={})
13
+ CommandParser.new(options).parse(script)
14
+ end
15
+
16
+ # Returns true if the ENV variable 'VERBOSE' is true. When verbose,
17
+ # ShellTest prints the expanded commands of sh_test to $stdout.
18
+ def verbose?
19
+ verbose = ENV['VERBOSE']
20
+ verbose && verbose =~ /^true$/i ? true : false
21
+ end
22
+
23
+ # Sets the specified ENV variables and returns the *current* env.
24
+ # If replace is true, current ENV variables are replaced; otherwise
25
+ # the new env variables are simply added to the existing set.
26
+ def set_env(env={}, replace=false)
27
+ current_env = {}
28
+ ENV.each_pair do |key, value|
29
+ current_env[key] = value
30
+ end
31
+
32
+ ENV.clear if replace
33
+
34
+ env.each_pair do |key, value|
35
+ if value.nil?
36
+ ENV.delete(key)
37
+ else
38
+ ENV[key] = value
39
+ end
40
+ end if env
41
+
42
+ current_env
43
+ end
44
+
45
+ # Sets the specified ENV variables for the duration of the block.
46
+ # If replace is true, current ENV variables are replaced; otherwise
47
+ # the new env variables are simply added to the existing set.
48
+ #
49
+ # Returns the block return.
50
+ def with_env(env={}, replace=false)
51
+ current_env = nil
52
+ begin
53
+ current_env = set_env(env, replace)
54
+ yield
55
+ ensure
56
+ if current_env
57
+ set_env(current_env, true)
58
+ end
59
+ end
60
+ end
61
+
62
+ def sh(cmd)
63
+ if @notify_method_name && verbose?
64
+ @notify_method_name = false
65
+ puts
66
+ puts method_name
67
+ end
68
+
69
+ start = Time.now
70
+ result = `#{cmd}`
71
+ finish = Time.now
72
+
73
+ if verbose?
74
+ elapsed = "%.3f" % [finish-start]
75
+ puts " (#{elapsed}s) #{cmd}"
76
+ end
77
+
78
+ result
79
+ end
80
+
81
+ def assert_script(script, options={})
82
+ _assert_script outdent(script), options
83
+ end
84
+
85
+ def _assert_script(script, options={})
86
+ parse_script(script, options).each do |cmd, output, status|
87
+ result = sh(cmd)
88
+
89
+ _assert_output_equal(output, result, cmd) if output
90
+ assert_equal(status, $?.exitstatus, cmd) if status
91
+ end
92
+ end
93
+
94
+ def assert_script_match(script, options={})
95
+ _assert_script_match outdent(script), options
96
+ end
97
+
98
+ def _assert_script_match(script, options={})
99
+ parse_script(script, options).each do |cmd, output, status|
100
+ result = sh(cmd)
101
+
102
+ _assert_alike(output, result, cmd) if output
103
+ assert_equal(status, $?.exitstatus, cmd) if status
104
+ end
105
+ end
106
+
107
+ # Asserts whether or not the a and b strings are equal, with a more
108
+ # readable output than assert_equal for large strings (especially large
109
+ # strings with significant whitespace).
110
+ def assert_output_equal(a, b, msg=nil)
111
+ _assert_output_equal outdent(a), b, msg
112
+ end
113
+
114
+ def _assert_output_equal(a, b, msg=nil)
115
+ if a == b
116
+ assert true
117
+ else
118
+ flunk %Q{
119
+ #{msg}
120
+ ==================== expected output ====================
121
+ #{whitespace_escape(a)}
122
+ ======================== but was ========================
123
+ #{whitespace_escape(b)}
124
+ =========================================================
125
+ }
126
+ end
127
+ end
128
+
129
+ # Asserts whether or not b is like a (which should be a Regexp), and
130
+ # provides a more readable output in the case of a failure as compared
131
+ # with assert_match.
132
+ #
133
+ # If a is a string it is turned into a RegexpEscape.
134
+ def assert_alike(a, b, msg=nil)
135
+ a = outdent(a) if a.kind_of?(String)
136
+ _assert_alike a, b, msg
137
+ end
138
+
139
+ def _assert_alike(a, b, msg=nil)
140
+ if a.kind_of?(String)
141
+ a = RegexpEscape.new(a)
142
+ end
143
+
144
+ if b =~ a
145
+ assert true
146
+ else
147
+ flunk %Q{
148
+ #{msg}
149
+ ================= expected output like ==================
150
+ #{whitespace_escape(a)}
151
+ ======================== but was ========================
152
+ #{whitespace_escape(b)}
153
+ =========================================================
154
+ }
155
+ end
156
+ end
157
+
158
+ # helper for stripping indentation off a string
159
+ def outdent(str)
160
+ str =~ /\A(?:\s*?\n)( *)(.*)\z/m ? $2.gsub!(/^ {0,#{$1.length}}/, '') : str
161
+ end
162
+
163
+ # helper for formatting escaping whitespace into readable text
164
+ def whitespace_escape(str)
165
+ str.to_s.gsub(/\s/) do |match|
166
+ case match
167
+ when "\n" then "\\n\n"
168
+ when "\t" then "\\t"
169
+ when "\r" then "\\r"
170
+ when "\f" then "\\f"
171
+ else match
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,72 @@
1
+ # :stopdoc:
2
+ module ShellTest
3
+ module Unit
4
+
5
+ # An exception class to flag skips.
6
+ class SkipException < StandardError
7
+ end
8
+
9
+ # Modifies how errors related to a SkipException are displayed.
10
+ module SkipDisplay
11
+ # Display S rather than E in the progress.
12
+ def single_character_display
13
+ "S"
14
+ end
15
+
16
+ # Removes the exception class from the message.
17
+ def message
18
+ @exception.message
19
+ end
20
+
21
+ # Updates the output to look like a MiniTest skip error.
22
+ def long_display
23
+ backtrace = filter_backtrace(@exception.backtrace)
24
+ "Skipped:\n#@test_name [#{backtrace[0].sub(/:in `.*$/, "")}]:\n#{message}\n"
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ require 'test/unit/testresult'
31
+ class Test::Unit::TestResult
32
+ # Returns an array of skips recorded for self.
33
+ def skips
34
+ @skips ||= []
35
+ end
36
+
37
+ # Partition errors from a SkipException from other errors and records as
38
+ # them as skips (the error is extended to display as a skip).
39
+ def add_error(error)
40
+ if error.exception.kind_of?(ShellTest::Unit::SkipException)
41
+ error.extend ShellTest::Unit::SkipDisplay
42
+ skips << error
43
+ else
44
+ @errors << error
45
+ end
46
+
47
+ notify_listeners(FAULT, error)
48
+ notify_listeners(CHANGED, self)
49
+ end
50
+
51
+ alias shell_test_original_to_s to_s
52
+
53
+ # Adds the skip count to the summary.
54
+ def to_s
55
+ "#{shell_test_original_to_s}, #{skips.length} skips"
56
+ end
57
+ end
58
+
59
+ require 'test/unit/testcase'
60
+ class Test::Unit::TestCase
61
+ # Alias method_name to __name__ such that FileMethods can redefine
62
+ # method_name to call __name__ (circular I know, but necessary for
63
+ # compatibility with MiniTest)
64
+ alias __name__ method_name
65
+
66
+ # Call to skip a test.
67
+ def skip(msg = nil, bt = caller)
68
+ msg ||= "Skipped, no message given"
69
+ raise ShellTest::Unit::SkipException, msg, bt
70
+ end
71
+ end
72
+ # :startdoc:
@@ -0,0 +1,40 @@
1
+ require 'test/unit'
2
+ require 'shell_test'
3
+
4
+ module ShellTest
5
+ # ShellTest is designed to work with MiniTest, which is the standard testing
6
+ # framework included in ruby 1.9. Minor changes in the API break backward
7
+ # compatibility with Test::Unit and/or add functionality expected by
8
+ # ShellTest.
9
+ #
10
+ # Test::Unit can be patched by requiring the shim file before defining
11
+ # specific TestCase subclasses.
12
+ #
13
+ # require 'test/unit'
14
+ # unless Object.const_defined?(:MiniTest)
15
+ # require 'shell_test/unit/shim'
16
+ # end
17
+ #
18
+ # To let ShellTest do this for you:
19
+ #
20
+ # require 'shell_test/unit'
21
+ #
22
+ # Note that the shim script has only been tested vs the Test::Unit that
23
+ # comes with ruby 1.8.x. A Test::Unit 2.0 gem exists; use with caution.
24
+ #
25
+ # ==== Patches
26
+ #
27
+ # The shim script adds two things to Test::Unit:
28
+ #
29
+ # 1) A __name__ method which returns the test method name (alias for
30
+ # method_name)
31
+ #
32
+ # 2) A skip method which can be used to skip a test (use it like flunk)
33
+ #
34
+ module Unit
35
+ end
36
+ end
37
+
38
+ unless Object.const_defined?(:MiniTest)
39
+ require 'shell_test/unit/shim'
40
+ end
@@ -0,0 +1,3 @@
1
+ module ShellTest
2
+ VERSION = "0.1.0"
3
+ end
data/lib/shell_test.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'shell_test/version'
2
+ require 'shell_test/file_methods'
3
+ require 'shell_test/shell_methods'
4
+
5
+ module ShellTest
6
+ include FileMethods
7
+ include ShellMethods
8
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shell_test
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Simon Chiang
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-07 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Provides test modules to simplify testing of shell scripts. ShellTest is not a testing framework. ShellTest integrates with Test::Unit and MiniTest out of the box, but it should be possible to include the test modules into other test frameworks.
23
+ email:
24
+ - simon.a.chiang@gmail.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files:
30
+ - History.rdoc
31
+ - README.rdoc
32
+ - MIT-LICENSE
33
+ files:
34
+ - lib/shell_test.rb
35
+ - lib/shell_test/command_parser.rb
36
+ - lib/shell_test/file_methods.rb
37
+ - lib/shell_test/regexp_escape.rb
38
+ - lib/shell_test/shell_methods.rb
39
+ - lib/shell_test/unit.rb
40
+ - lib/shell_test/unit/shim.rb
41
+ - lib/shell_test/version.rb
42
+ - History.rdoc
43
+ - README.rdoc
44
+ - MIT-LICENSE
45
+ has_rdoc: true
46
+ homepage: ""
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --main
52
+ - README.rdoc
53
+ - -S
54
+ - -N
55
+ - --title
56
+ - ShellTest
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ requirements: []
78
+
79
+ rubyforge_project: shell_test
80
+ rubygems_version: 1.6.2
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Test modules for shell scripts
84
+ test_files: []
85
+