tap 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Basic Overview +151 -0
- data/Command Reference +99 -0
- data/History +24 -0
- data/MIT-LICENSE +1 -1
- data/README +29 -57
- data/Rakefile +30 -37
- data/Tutorial +243 -191
- data/bin/tap +66 -35
- data/lib/tap.rb +47 -29
- data/lib/tap/app.rb +700 -342
- data/lib/tap/{script → cmd}/console.rb +0 -0
- data/lib/tap/{script → cmd}/destroy.rb +0 -0
- data/lib/tap/{script → cmd}/generate.rb +0 -0
- data/lib/tap/cmd/run.rb +156 -0
- data/lib/tap/constants.rb +4 -0
- data/lib/tap/dump.rb +57 -0
- data/lib/tap/env.rb +316 -0
- data/lib/tap/file_task.rb +106 -109
- data/lib/tap/generator.rb +4 -1
- data/lib/tap/generator/generators/command/USAGE +6 -0
- data/lib/tap/generator/generators/command/command_generator.rb +17 -0
- data/lib/tap/generator/generators/{script/templates/script.erb → command/templates/command.erb} +10 -10
- data/lib/tap/generator/generators/config/USAGE +21 -0
- data/lib/tap/generator/generators/config/config_generator.rb +17 -7
- data/lib/tap/generator/generators/file_task/USAGE +3 -0
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -0
- data/lib/tap/generator/generators/file_task/templates/file.txt +2 -0
- data/lib/tap/generator/generators/file_task/templates/file.yml +3 -0
- data/lib/tap/generator/generators/file_task/templates/task.erb +26 -20
- data/lib/tap/generator/generators/file_task/templates/test.erb +20 -10
- data/lib/tap/generator/generators/generator/generator_generator.rb +1 -1
- data/lib/tap/generator/generators/generator/templates/generator.erb +21 -12
- data/lib/tap/generator/generators/root/templates/Rakefile +33 -24
- data/lib/tap/generator/generators/root/templates/tap.yml +28 -31
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +1 -0
- data/lib/tap/generator/generators/task/USAGE +3 -0
- data/lib/tap/generator/generators/task/task_generator.rb +18 -5
- data/lib/tap/generator/generators/task/templates/task.erb +7 -12
- data/lib/tap/generator/generators/task/templates/test.erb +10 -11
- data/lib/tap/generator/generators/workflow/templates/task.erb +1 -1
- data/lib/tap/generator/generators/workflow/templates/test.erb +1 -1
- data/lib/tap/patches/rake/rake_test_loader.rb +8 -0
- data/lib/tap/patches/rake/testtask.rb +55 -0
- data/lib/tap/patches/ruby19/backtrace_filter.rb +51 -0
- data/lib/tap/patches/ruby19/parsedate.rb +16 -0
- data/lib/tap/root.rb +172 -67
- data/lib/tap/script.rb +70 -336
- data/lib/tap/support/aggregator.rb +55 -0
- data/lib/tap/support/audit.rb +281 -280
- data/lib/tap/support/batchable.rb +59 -0
- data/lib/tap/support/class_configuration.rb +279 -0
- data/lib/tap/support/configurable.rb +92 -0
- data/lib/tap/support/configurable_methods.rb +296 -0
- data/lib/tap/support/executable.rb +98 -0
- data/lib/tap/support/executable_queue.rb +82 -0
- data/lib/tap/support/logger.rb +9 -15
- data/lib/tap/support/rake.rb +43 -54
- data/lib/tap/support/run_error.rb +32 -13
- data/lib/tap/support/shell_utils.rb +47 -0
- data/lib/tap/support/tdoc.rb +9 -8
- data/lib/tap/support/tdoc/config_attr.rb +40 -16
- data/lib/tap/support/validation.rb +77 -0
- data/lib/tap/support/versions.rb +36 -36
- data/lib/tap/task.rb +276 -482
- data/lib/tap/test.rb +20 -261
- data/lib/tap/test/env_vars.rb +7 -5
- data/lib/tap/test/file_methods.rb +126 -121
- data/lib/tap/test/subset_methods.rb +86 -45
- data/lib/tap/test/tap_methods.rb +271 -0
- data/lib/tap/workflow.rb +174 -46
- data/test/app/config/another/task.yml +1 -0
- data/test/app/config/erb.yml +2 -1
- data/test/app/config/some/task.yml +1 -0
- data/test/app/config/template.yml +2 -6
- data/test/app_test.rb +1241 -1008
- data/test/env/test_configure/recurse_a.yml +2 -0
- data/test/env/test_configure/recurse_b.yml +2 -0
- data/test/env/test_configure/tap.yml +23 -0
- data/test/env/test_load_env_config/dir/tap.yml +3 -0
- data/test/env/test_load_env_config/recurse_a.yml +2 -0
- data/test/env/test_load_env_config/recurse_b.yml +2 -0
- data/test/env/test_load_env_config/tap.yml +3 -0
- data/test/env_test.rb +198 -0
- data/test/file_task_test.rb +70 -53
- data/{lib/tap/generator/generators/package/USAGE → test/root/file.txt} +0 -0
- data/test/root_test.rb +621 -454
- data/test/script_test.rb +38 -174
- data/test/support/aggregator_test.rb +99 -0
- data/test/support/audit_test.rb +409 -416
- data/test/support/batchable_test.rb +74 -0
- data/test/support/{task_configuration_test.rb → class_configuration_test.rb} +106 -47
- data/test/{task/config/overriding.yml → support/configurable/config/configured.yml} +0 -0
- data/test/support/configurable_test.rb +295 -0
- data/test/support/executable_queue_test.rb +103 -0
- data/test/support/executable_test.rb +38 -0
- data/test/support/logger_test.rb +17 -17
- data/test/support/rake_test.rb +4 -2
- data/test/support/shell_utils_test.rb +24 -0
- data/test/support/tdoc_test.rb +265 -258
- data/test/support/validation_test.rb +54 -0
- data/test/support/versions_test.rb +38 -38
- data/test/tap_test_helper.rb +19 -5
- data/test/tap_test_suite.rb +5 -2
- data/test/task_base_test.rb +13 -104
- data/test/task_syntax_test.rb +300 -0
- data/test/task_test.rb +258 -381
- data/test/test/env_vars_test.rb +40 -40
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/one.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/expected/two.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/one.txt +0 -0
- data/test/test/file_methods/{test_assert_output_files_equal → test_assert_files}/input/two.txt +0 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/one.txt +0 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_can_have_no_expected_files_if_specified}/input/two.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +1 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_different_content}/expected/two.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +1 -0
- data/test/test/{test_file_task_test → file_methods/test_assert_files_fails_for_missing_expected_file}/expected/one.txt +0 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +1 -0
- data/test/test/file_methods_doc/test_sub/expected/one.txt +1 -0
- data/test/test/file_methods_doc/test_sub/expected/two.txt +1 -0
- data/test/test/file_methods_doc/test_sub/input/one.txt +1 -0
- data/test/test/file_methods_doc/test_sub/input/two.txt +1 -0
- data/test/test/file_methods_doc_test.rb +29 -0
- data/test/test/file_methods_test.rb +214 -143
- data/test/test/subset_methods_test.rb +111 -115
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/a.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/expected/task/name/b.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/a.txt +0 -0
- data/test/test/{test_assert_expected_result_files → tap_methods/test_assert_files}/input/b.txt +0 -0
- data/test/test/tap_methods_test.rb +399 -0
- data/test/workflow_test.rb +101 -91
- metadata +86 -70
- data/lib/tap/generator/generators/package/package_generator.rb +0 -38
- data/lib/tap/generator/generators/package/templates/package.erb +0 -186
- data/lib/tap/generator/generators/script/USAGE +0 -0
- data/lib/tap/generator/generators/script/script_generator.rb +0 -17
- data/lib/tap/script/run.rb +0 -154
- data/lib/tap/support/batch_queue.rb +0 -162
- data/lib/tap/support/combinator.rb +0 -114
- data/lib/tap/support/task_configuration.rb +0 -169
- data/lib/tap/support/template.rb +0 -81
- data/lib/tap/support/templater.rb +0 -155
- data/lib/tap/version.rb +0 -4
- data/test/app/config/addition_template.yml +0 -6
- data/test/app_class_test.rb +0 -33
- data/test/check/binding_eval.rb +0 -23
- data/test/check/define_method_check.rb +0 -22
- data/test/check/dependencies_check.rb +0 -175
- data/test/check/inheritance_check.rb +0 -22
- data/test/support/batch_queue_test.rb +0 -320
- data/test/support/combinator_test.rb +0 -249
- data/test/support/template_test.rb +0 -122
- data/test/support/templater/erb.txt +0 -2
- data/test/support/templater/erb.yml +0 -2
- data/test/support/templater/somefile.txt +0 -2
- data/test/support/templater_test.rb +0 -192
- data/test/task/config/template.yml +0 -4
- data/test/task_class_test.rb +0 -170
- data/test/task_execute_test.rb +0 -262
- data/test/test/file_methods/test_assert_expected/expected/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/expected/folder/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/input/file.txt +0 -1
- data/test/test/file_methods/test_assert_expected/input/folder/file.txt +0 -1
- data/test/test/file_methods/test_assert_files_exist/input/input_1.txt +0 -0
- data/test/test/file_methods/test_assert_files_exist/input/input_2.txt +0 -0
- data/test/test/file_methods/test_file_compare/expected/output_1.txt +0 -3
- data/test/test/file_methods/test_file_compare/expected/output_2.txt +0 -1
- data/test/test/file_methods/test_file_compare/input/input_1.txt +0 -3
- data/test/test/file_methods/test_file_compare/input/input_2.txt +0 -3
- data/test/test/file_methods/test_infer_glob/expected/file.yml +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_1.txt +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_2.txt +0 -0
- data/test/test/file_methods/test_yml_compare/expected/output_1.yml +0 -6
- data/test/test/file_methods/test_yml_compare/expected/output_2.yml +0 -6
- data/test/test/file_methods/test_yml_compare/input/input_1.yml +0 -4
- data/test/test/file_methods/test_yml_compare/input/input_2.yml +0 -4
- data/test/test_test.rb +0 -373
|
@@ -5,7 +5,6 @@ require 'tap/test/env_vars'
|
|
|
5
5
|
|
|
6
6
|
module Test # :nodoc:
|
|
7
7
|
module Unit # :nodoc:
|
|
8
|
-
# Methods extending TestCase. See the TestTutorial for more information.
|
|
9
8
|
class TestCase
|
|
10
9
|
class << self
|
|
11
10
|
include Tap::Test::EnvVars
|
|
@@ -16,7 +15,9 @@ module Test # :nodoc:
|
|
|
16
15
|
subclass_conditions = conditions.inject({}) do |memo, (key, value)|
|
|
17
16
|
memo.update(key => (value.dup rescue value))
|
|
18
17
|
end
|
|
19
|
-
subclass.instance_variable_set(
|
|
18
|
+
subclass.instance_variable_set(:@conditions, subclass_conditions)
|
|
19
|
+
subclass.instance_variable_set(:@run_test_suite, nil)
|
|
20
|
+
subclass.instance_variable_set(:@skip_messages, [])
|
|
20
21
|
|
|
21
22
|
# subclass_inputs = prompt_inputs.inject({}) do |memo, (key, value)|
|
|
22
23
|
# memo.update(key => (value.dup rescue value))
|
|
@@ -107,8 +108,8 @@ module Test # :nodoc:
|
|
|
107
108
|
# true if no platforms are specified.
|
|
108
109
|
#
|
|
109
110
|
# Some common platforms:
|
|
110
|
-
#
|
|
111
|
-
#
|
|
111
|
+
# mswin Windows
|
|
112
|
+
# darwin Mac
|
|
112
113
|
def match_platform?(*platforms)
|
|
113
114
|
platforms.each do |platform|
|
|
114
115
|
platform.to_s =~ /^(non_)?(.*)/
|
|
@@ -139,11 +140,11 @@ module Test # :nodoc:
|
|
|
139
140
|
# Causes a test suite to be skipped. If a message is given, it will
|
|
140
141
|
# print and notify the user the test suite has been skipped.
|
|
141
142
|
def skip_test(msg=nil)
|
|
142
|
-
|
|
143
|
+
self.run_test_suite = false
|
|
143
144
|
|
|
144
145
|
# experimental -- perhaps use this so that a test can be skipped
|
|
145
146
|
# for multiple reasons?
|
|
146
|
-
|
|
147
|
+
@skip_messages << msg unless msg.nil?
|
|
147
148
|
end
|
|
148
149
|
|
|
149
150
|
alias :original_suite :suite
|
|
@@ -153,7 +154,6 @@ module Test # :nodoc:
|
|
|
153
154
|
if run_test_suite?
|
|
154
155
|
original_suite
|
|
155
156
|
else
|
|
156
|
-
@skip_messages ||= []
|
|
157
157
|
puts "Skipping #{name}: #{@skip_messages.join(', ')}" unless @skip_messages.empty?
|
|
158
158
|
Test::Unit::TestSuite.new(name)
|
|
159
159
|
end
|
|
@@ -169,7 +169,7 @@ module Tap
|
|
|
169
169
|
# Ideally you always run all of your tests and they all run and pass everywhere. In
|
|
170
170
|
# practice it's useful to suppress the execution of some tests -- long running tests,
|
|
171
171
|
# tests specific for a given platform, or tests that depend on some condition, such
|
|
172
|
-
# as the version of some third-party software your code interacts with.
|
|
172
|
+
# as the version of some optional third-party software your code interacts with.
|
|
173
173
|
#
|
|
174
174
|
# SubsetMethods extends TestCase with methods for defining conditions that can be
|
|
175
175
|
# used to conditionally perform some action, or skip a test suite entirely. When
|
|
@@ -185,54 +185,64 @@ module Tap
|
|
|
185
185
|
# condition(:non_windows) { match_platform?('non_mswin') }
|
|
186
186
|
# end
|
|
187
187
|
#
|
|
188
|
-
# class
|
|
189
|
-
#
|
|
190
|
-
# # (maybe you're not allowed to tie up a computer until after hours)
|
|
191
|
-
# condition(:afterhours) { Time.now > 18 || Time.now < 6 }
|
|
192
|
-
#
|
|
193
|
-
# skip_test unless satisfied?(:windows, :afterhours)
|
|
188
|
+
# class WindowsOnlyTest < Test::Unit::TestCase
|
|
189
|
+
# skip_test unless satisfied?(:windows)
|
|
194
190
|
# end
|
|
195
191
|
#
|
|
196
|
-
#
|
|
197
|
-
#
|
|
192
|
+
# WindowsOnlyTest will only run on a Windows platform. These conditions can be used
|
|
193
|
+
# in specific tests, when only some tests need to be skipped.
|
|
198
194
|
#
|
|
199
195
|
# class RunOnlyAFewTest < Test::Unit::TestCase
|
|
200
196
|
# include SubsetMethods
|
|
201
|
-
# include Benchmark
|
|
202
197
|
#
|
|
203
198
|
# def test_runs_all_the_time
|
|
204
199
|
# assert true
|
|
205
200
|
# end
|
|
206
201
|
#
|
|
207
|
-
# def
|
|
208
|
-
# condition_test(:
|
|
209
|
-
# ...
|
|
202
|
+
# def test_runs_only_if_non_windows_condition_is_true
|
|
203
|
+
# condition_test(:non_windows) { assert true }
|
|
210
204
|
# end
|
|
211
205
|
# end
|
|
212
206
|
#
|
|
213
|
-
# def
|
|
214
|
-
# extended_test
|
|
215
|
-
# ...
|
|
216
|
-
# end
|
|
207
|
+
# def test_runs_only_when_ENV_variable_EXTENDED_is_true
|
|
208
|
+
# extended_test { assert true }
|
|
217
209
|
# end
|
|
218
210
|
#
|
|
219
|
-
# def
|
|
211
|
+
# def test_runs_only_when_ENV_variable_BENCHMARK_is_true
|
|
220
212
|
# benchmark_test do |x|
|
|
221
213
|
# x.report("init speed") { 10000.times { Object.new } }
|
|
222
214
|
# end
|
|
223
215
|
# end
|
|
216
|
+
#
|
|
217
|
+
# def test_runs_only_when_ENV_variable_CUSTOM_is_true
|
|
218
|
+
# subset_test('CUSTOM') { assert true }
|
|
219
|
+
# end
|
|
224
220
|
# end
|
|
225
221
|
#
|
|
226
|
-
# In the example, EXTENDED
|
|
227
|
-
#
|
|
222
|
+
# In the example, the ENV variables EXTENDED, BENCHMARK, and CUSTOM act as flags
|
|
223
|
+
# to run specific tests. If you're running your test using Rake, ENV variables
|
|
224
|
+
# can be set from the command line like so:
|
|
228
225
|
#
|
|
229
|
-
# %
|
|
230
|
-
# %
|
|
226
|
+
# % rake test EXTENDED=true
|
|
227
|
+
# % rake test BENCHMARK=true
|
|
231
228
|
#
|
|
232
|
-
#
|
|
233
|
-
# To run all tests that get switched using an environment variable, set ALL=true.
|
|
229
|
+
# Since tap can run rake tasks as well, these are equivalent:
|
|
234
230
|
#
|
|
235
|
-
#
|
|
231
|
+
# % tap run test EXTENDED=true
|
|
232
|
+
# % tap run test BENCHMARK=true
|
|
233
|
+
#
|
|
234
|
+
# In so far as SubsetMethods is concerned, the environment variables are
|
|
235
|
+
# case-insensitive. As in the example, additional ENV-variable-dependent
|
|
236
|
+
# tests can be defined using the subset_test method. To run all tests that
|
|
237
|
+
# get switched using an environment variable, set ALL=true.
|
|
238
|
+
#
|
|
239
|
+
# # also runs benchmark tests
|
|
240
|
+
# % tap run test BenchMark=true
|
|
241
|
+
#
|
|
242
|
+
# # runs all tests
|
|
243
|
+
# % tap run test all=true
|
|
244
|
+
#
|
|
245
|
+
# === Class Methods
|
|
236
246
|
#
|
|
237
247
|
# See Test::Unit::TestCase for documentation of the class methods added by SubsetMethods
|
|
238
248
|
module SubsetMethods
|
|
@@ -247,13 +257,14 @@ module Tap
|
|
|
247
257
|
self.class.run_subset?(type)
|
|
248
258
|
end
|
|
249
259
|
|
|
250
|
-
# Returns true if the
|
|
251
|
-
# Returns the default value if 'ALL' is specified in
|
|
252
|
-
|
|
260
|
+
# Returns true if the input string matches the regexp specified in
|
|
261
|
+
# env_var(type). Returns the default value if 'ALL' is specified in
|
|
262
|
+
# ENV or type is not specified in ENV.
|
|
263
|
+
def match_regexp?(type, str, default=true)
|
|
253
264
|
return true if env_true?("ALL")
|
|
254
265
|
return default unless env(type)
|
|
255
266
|
|
|
256
|
-
|
|
267
|
+
str =~ Regexp.new(env(type)) ? true : false
|
|
257
268
|
end
|
|
258
269
|
|
|
259
270
|
# Platform-specific test. Useful for specifying test that should only
|
|
@@ -298,16 +309,47 @@ module Tap
|
|
|
298
309
|
end
|
|
299
310
|
|
|
300
311
|
# Basic method for a subset test. The provided block will run if:
|
|
301
|
-
#
|
|
302
|
-
#
|
|
312
|
+
# - The subset type is specified in ENV
|
|
313
|
+
# - The subset 'ALL' is specified in ENV
|
|
314
|
+
# - The test method name matches the regexp provided in the <TYPE>_TEST ENV variable
|
|
303
315
|
#
|
|
304
|
-
# Otherwise the block will be skipped and +skip+ will be printed.
|
|
305
|
-
# is the first letter of +type+.
|
|
316
|
+
# Otherwise the block will be skipped and +skip+ will be printed in the test output.
|
|
317
|
+
# By default skip is the first letter of +type+.
|
|
318
|
+
#
|
|
319
|
+
# For example, with these methods:
|
|
320
|
+
#
|
|
321
|
+
# def test_one
|
|
322
|
+
# subset_test('CUSTOM') { assert true }
|
|
323
|
+
# end
|
|
324
|
+
#
|
|
325
|
+
# def test_two
|
|
326
|
+
# subset_test('CUSTOM') { assert true }
|
|
327
|
+
# end
|
|
328
|
+
#
|
|
329
|
+
# Condition Tests that get run
|
|
330
|
+
# ENV['ALL']=true test_one, test_two
|
|
331
|
+
# ENV['CUSTOM']=true test_one, test_two
|
|
332
|
+
# ENV['CUSTOM_TEST']=test_ test_one, test_two
|
|
333
|
+
# ENV['CUSTOM_TEST']=test_one test_one
|
|
334
|
+
# ENV['CUSTOM']=nil no tests get run
|
|
335
|
+
#
|
|
336
|
+
# If you're running your tests with Rake, ENV variables can be set from the
|
|
337
|
+
# command line, so you might use these command line statements:
|
|
338
|
+
#
|
|
339
|
+
# # all tests
|
|
340
|
+
# % rake test all=true
|
|
341
|
+
#
|
|
342
|
+
# # custom subset tests
|
|
343
|
+
# % rake test custom=true
|
|
344
|
+
#
|
|
345
|
+
# # just test_one
|
|
346
|
+
# % rake test custom_test=test_one
|
|
347
|
+
#
|
|
306
348
|
def subset_test(type, skip=type[0..0].downcase)
|
|
307
349
|
type = type.upcase
|
|
308
350
|
type_test = "#{type}_TEST"
|
|
309
351
|
if run_subset?(type) || env(type_test)
|
|
310
|
-
if match_regexp?(type_test,
|
|
352
|
+
if match_regexp?(type_test, method_name.to_s)
|
|
311
353
|
yield
|
|
312
354
|
else
|
|
313
355
|
print skip
|
|
@@ -328,9 +370,8 @@ module Tap
|
|
|
328
370
|
end
|
|
329
371
|
|
|
330
372
|
# Declares a subset_test for the ENV variable 'BENCHMARK'. If run,
|
|
331
|
-
# benchmark_test sets up benchmarking using the bm method
|
|
332
|
-
# input length and block.
|
|
333
|
-
# in the test class. Prints 'b' if the test is not run.
|
|
373
|
+
# benchmark_test sets up benchmarking using the Benchmark.bm method
|
|
374
|
+
# using the input length and block. Prints 'b' if the test is not run.
|
|
334
375
|
#
|
|
335
376
|
# include Benchmark
|
|
336
377
|
# def test_speed
|
|
@@ -340,7 +381,7 @@ module Tap
|
|
|
340
381
|
subset_test("BENCHMARK") do
|
|
341
382
|
puts
|
|
342
383
|
puts method_name
|
|
343
|
-
bm(length, &block)
|
|
384
|
+
Benchmark.bm(length, &block)
|
|
344
385
|
end
|
|
345
386
|
end
|
|
346
387
|
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'tap/test/file_methods'
|
|
3
|
+
require 'tap/test/subset_methods'
|
|
4
|
+
|
|
5
|
+
module Test # :nodoc:
|
|
6
|
+
module Unit # :nodoc:
|
|
7
|
+
class TestCase
|
|
8
|
+
class << self
|
|
9
|
+
# Causes a unit test to act as a tap test -- resulting in the following:
|
|
10
|
+
# - setup using acts_as_file_test
|
|
11
|
+
# - inclusion of Tap::Test::SubsetMethods
|
|
12
|
+
# - inclusion of Tap::Test::InstanceMethods
|
|
13
|
+
#
|
|
14
|
+
# Note: Unless otherwise specified, <tt>acts_as_tap_test</tt> infers a root directory
|
|
15
|
+
# based on the calling file. Be sure to specify the root directory explicitly
|
|
16
|
+
# if you call acts_as_file_test from a file that is NOT meant to be test file.
|
|
17
|
+
def acts_as_tap_test(options={})
|
|
18
|
+
options = {:root => file_test_root}.merge(options.symbolize_keys)
|
|
19
|
+
acts_as_file_test(options)
|
|
20
|
+
|
|
21
|
+
include Tap::Test::SubsetMethods
|
|
22
|
+
include Tap::Test::TapMethods
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module Tap
|
|
31
|
+
module Test
|
|
32
|
+
|
|
33
|
+
# Used during check_audit to hold the sources and values of an audit
|
|
34
|
+
# in the correct order. Oriented so that the next value to be checked
|
|
35
|
+
# is at the top of the stack. Used internally.
|
|
36
|
+
class AuditStack # :nodoc:
|
|
37
|
+
attr_reader :test
|
|
38
|
+
|
|
39
|
+
def initialize(test)
|
|
40
|
+
@test = test
|
|
41
|
+
@stack = []
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def load_audit(values)
|
|
45
|
+
[values._sources, values._values].transpose.reverse_each do |sv|
|
|
46
|
+
load(*sv)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def load(source, value)
|
|
51
|
+
@stack.unshift [source, value]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def next
|
|
55
|
+
@stack.shift
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Tap-specific testing methods to help with testing Tasks, such as the
|
|
60
|
+
# checking of audits and test-specific modification of application
|
|
61
|
+
# configuration.
|
|
62
|
+
module TapMethods
|
|
63
|
+
|
|
64
|
+
# Returns the test-method-specific application.
|
|
65
|
+
attr_reader :app
|
|
66
|
+
|
|
67
|
+
# Setup creates a test-method-specific application that is initialized
|
|
68
|
+
# to the method_root, and uses the directories and absolute paths from
|
|
69
|
+
# trs (the test root structure, see Tap::Test::FileMethods).
|
|
70
|
+
#
|
|
71
|
+
# Also makes sure Tap::App.instance returns the test method app.
|
|
72
|
+
def setup
|
|
73
|
+
super
|
|
74
|
+
@app = Tap::App.new(
|
|
75
|
+
:root => method_root,
|
|
76
|
+
:directories => trs.directories,
|
|
77
|
+
:absolute_paths => trs.absolute_paths)
|
|
78
|
+
Tap::App.instance = @app
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#
|
|
82
|
+
# audit test methods
|
|
83
|
+
#
|
|
84
|
+
|
|
85
|
+
# Used to define expected audits in Tap::Test::TapMethods#assert_audit_equal
|
|
86
|
+
class ExpAudit < Array
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Used to define merged audit trails in Tap::Test::TapMethods#assert_audit_equal
|
|
90
|
+
class ExpMerge < Array
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Asserts that an array of audits are all equal, basically feeding
|
|
94
|
+
# each pair of audits to assert_audit_equal.
|
|
95
|
+
def assert_audits_equal(expected, audits)
|
|
96
|
+
each_pair_with_index(expected, audits) do |exp, audit, index|
|
|
97
|
+
assert_audit_equal(exp, audit, [index])
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Asserts that an audit is as expected. The expected audit should
|
|
102
|
+
# be an ExpAudit (just a subclass of Array) that records the sources
|
|
103
|
+
# and the values at each step in the audit trail. Proc objects can
|
|
104
|
+
# be provided in place of expected records that are hard or impossible
|
|
105
|
+
# to provide directly; the Proc will be used to validate the actual
|
|
106
|
+
# record. Merges must be marked in the ExpAudit using ExpMerge.
|
|
107
|
+
#
|
|
108
|
+
# Simple assertion:
|
|
109
|
+
#
|
|
110
|
+
# a = Tap::Support::Audit.new
|
|
111
|
+
# a._record(:a, 'a')
|
|
112
|
+
# a._record(:b, 'b')
|
|
113
|
+
#
|
|
114
|
+
# e = ExpAudit[[:a, 'a'], [:b, 'b']]
|
|
115
|
+
# assert_audit_equal(e, a)
|
|
116
|
+
#
|
|
117
|
+
# Assertion validating a record with a Proc (any number of
|
|
118
|
+
# records can be validated with a Proc):
|
|
119
|
+
#
|
|
120
|
+
# a = Tap::Support::Audit.new
|
|
121
|
+
# a._record(:a, 'a')
|
|
122
|
+
# a._record(:b, 'b')
|
|
123
|
+
#
|
|
124
|
+
# e = ExpAudit[
|
|
125
|
+
# lambda {|source, value| source == :a && value == 'a'},
|
|
126
|
+
# [:b, 'b']]
|
|
127
|
+
# assert_audit_equal(e, a)
|
|
128
|
+
#
|
|
129
|
+
# Assertion with merge:
|
|
130
|
+
#
|
|
131
|
+
# a = Tap::Support::Audit.new
|
|
132
|
+
# a._record(:a, 'a')
|
|
133
|
+
# a._record(:b, 'b')
|
|
134
|
+
#
|
|
135
|
+
# b = Tap::Support::Audit.new
|
|
136
|
+
# b._record(:c, 'c')
|
|
137
|
+
# b._record(:d, 'd')
|
|
138
|
+
#
|
|
139
|
+
# c = Tap::Support::Audit.merge(a,b)
|
|
140
|
+
# c._record(:e, 'e')
|
|
141
|
+
# c._record(:f, 'f')
|
|
142
|
+
#
|
|
143
|
+
# ea = ExpAudit[[:a, "a"], [:b, "b"]]
|
|
144
|
+
# eb = ExpAudit[[:c, "c"], [:d, "d"]]
|
|
145
|
+
# e = ExpAudit[ExpMerge[ea, eb], [:e, "e"], [:f, "f"]]
|
|
146
|
+
#
|
|
147
|
+
# assert_audit_equal(e, c)
|
|
148
|
+
#
|
|
149
|
+
# When assert_audit_equal fails, a string of indicies is provided
|
|
150
|
+
# to help locate which record was unequal. For instance in the last
|
|
151
|
+
# example, say we used:
|
|
152
|
+
#
|
|
153
|
+
# ea = ExpAudit[[:a, "a"], [:b, "FLUNK"]]
|
|
154
|
+
# eb = ExpAudit[[:c, "c"], [:d, "d"]]
|
|
155
|
+
# e = ExpAudit[ExpMerge[ea, eb], [:e, "e"], [:f, "f"]]
|
|
156
|
+
#
|
|
157
|
+
# The failure message will read something like 'unequal record 0:0:1'
|
|
158
|
+
# indicating it was e[0][0][1] that failed. Working through it,
|
|
159
|
+
# remembering that ExpAudit and ExpMerge are just subclasses of
|
|
160
|
+
# Array:
|
|
161
|
+
#
|
|
162
|
+
# e # => ExpAudit[ExpMerge[ea, eb], [:e, "e"], [:f, "f"]]
|
|
163
|
+
# e[0] # => ExpMerge[ea, eb]
|
|
164
|
+
# e[0][0] # => ExpAudit[[:a, "a"], [:b, "FLUNK"]]
|
|
165
|
+
# e[0][0][1] # => [:b, "FLUNK"]
|
|
166
|
+
#
|
|
167
|
+
def assert_audit_equal(expected, audit, nesting=[])
|
|
168
|
+
actual = audit._collect_records {|source, value| [source, value]}
|
|
169
|
+
assert_audit_records_equal(expected, actual, nesting)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
private
|
|
173
|
+
|
|
174
|
+
def assert_audit_records_equal(expected, actual, nesting=[])
|
|
175
|
+
assert_equal ExpAudit, expected.class
|
|
176
|
+
assert_equal expected.length, actual.length, "unequal number of records"
|
|
177
|
+
|
|
178
|
+
expected.each_with_index do |exp_record, i|
|
|
179
|
+
case exp_record
|
|
180
|
+
when ExpMerge
|
|
181
|
+
exp_record.each_with_index do |exp_audit, j|
|
|
182
|
+
assert_audit_records_equal(exp_audit, actual[i][j], nesting + [i,j])
|
|
183
|
+
end
|
|
184
|
+
when Proc
|
|
185
|
+
assert exp_record.call(*actual[i]), "unconfirmed record #{(nesting + [i]).join(':')}"
|
|
186
|
+
else
|
|
187
|
+
assert_equal exp_record, actual[i], "unequal record #{(nesting + [i]).join(':')}"
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
public
|
|
193
|
+
|
|
194
|
+
#
|
|
195
|
+
# application methods
|
|
196
|
+
#
|
|
197
|
+
|
|
198
|
+
# Applies the input options to the specified app for the duration
|
|
199
|
+
# of the block. Unless merge_with_existing is false, the input
|
|
200
|
+
# options will be merged with the existing options; otherwise
|
|
201
|
+
# the app options will be reconfigured to just the inputs.
|
|
202
|
+
#
|
|
203
|
+
# For convenience, with_options is setup such that options
|
|
204
|
+
# {:debug => true, :quiet => true} are implicitly specified.
|
|
205
|
+
# Overrides are respected.
|
|
206
|
+
#
|
|
207
|
+
# app = Tap::App.new(:options => {:one => 1, :two => 2})
|
|
208
|
+
#
|
|
209
|
+
# with_options({:one => 'one', :quiet => false}, app) do
|
|
210
|
+
# app.options.marshal_dump # => {:one => 'one', :two => 2, :debug => true, :quiet => false}
|
|
211
|
+
# end
|
|
212
|
+
#
|
|
213
|
+
# app.options.marshal_dump # => {:one => 1, :two => 2}
|
|
214
|
+
#
|
|
215
|
+
def with_options(options={}, app=self.app, merge_with_existing=true, &block)
|
|
216
|
+
app_config = {:options => options}
|
|
217
|
+
with_config(app_config, app, merge_with_existing, &block)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Applies the input configurations to the specified app for the
|
|
221
|
+
# duration of the block. Unless merge_with_existing is false,
|
|
222
|
+
# the input configurations will be merged with the existing
|
|
223
|
+
# configurations; otherwise the app will be reconfigured to
|
|
224
|
+
# using the inputs as specified.
|
|
225
|
+
#
|
|
226
|
+
# For convenience, with_config is setup such that options
|
|
227
|
+
# {:debug => true, :quiet => true} are implicitly specified.
|
|
228
|
+
# Overrides are respected.
|
|
229
|
+
#
|
|
230
|
+
# app = Tap::App.new(:directories => {:dir => 'dir', :alt => 'alt_dir'})
|
|
231
|
+
# tmp_config = {
|
|
232
|
+
# :directories => {:alt => 'another', :new => 'new_dir'},
|
|
233
|
+
# :options => {:one => 1, :quiet => false}}
|
|
234
|
+
#
|
|
235
|
+
# with_config(tmp_config, app) do
|
|
236
|
+
# app.directories # => {:dir => 'dir', :alt => 'another', :new => 'new_dir'}
|
|
237
|
+
# app.options.marshal_dump # => {:one => 1, :debug => true, :quiet => false}
|
|
238
|
+
# end
|
|
239
|
+
#
|
|
240
|
+
# app.directories # => {:dir => 'dir', :alt => 'alt_dir'}
|
|
241
|
+
# app.options.marshal_dump # => {}
|
|
242
|
+
#
|
|
243
|
+
def with_config(app_config={}, app=self.app, merge_with_existing=true, default_options={:debug => true, :quiet => true}, &block)
|
|
244
|
+
begin
|
|
245
|
+
hold = app.config
|
|
246
|
+
|
|
247
|
+
app_config[:options] = default_options.merge(app_config[:options] || {})
|
|
248
|
+
if merge_with_existing
|
|
249
|
+
hold.each_pair do |key, value|
|
|
250
|
+
next unless app_config.has_key?(key)
|
|
251
|
+
next unless value.kind_of?(Hash)
|
|
252
|
+
|
|
253
|
+
app_config[key] = value.merge(app_config[key])
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
app.reconfigure(app_config)
|
|
258
|
+
|
|
259
|
+
yield block if block_given?
|
|
260
|
+
ensure
|
|
261
|
+
app.reconfigure(hold)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|