assert 1.1.0 → 2.0.0.rc.1
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/.assert.rb +3 -0
- data/README.md +182 -108
- data/Rakefile +0 -3
- data/bin/assert +1 -1
- data/lib/assert.rb +75 -4
- data/lib/assert/assert_runner.rb +76 -0
- data/lib/assert/cli.rb +25 -46
- data/lib/assert/context.rb +3 -3
- data/lib/assert/result.rb +65 -55
- data/lib/assert/runner.rb +19 -38
- data/lib/assert/suite.rb +0 -7
- data/lib/assert/test.rb +4 -16
- data/lib/assert/version.rb +1 -1
- data/lib/assert/view.rb +23 -0
- data/lib/assert/view/base.rb +10 -19
- data/lib/assert/view/default_view.rb +16 -11
- data/lib/assert/view/helpers/ansi_styles.rb +1 -1
- data/lib/assert/view/helpers/common.rb +37 -16
- data/test/assert_test.rb +29 -14
- data/test/context/class_methods_test.rb +2 -2
- data/test/context_test.rb +28 -50
- data/test/helper.rb +4 -2
- data/test/runner_test.rb +5 -4
- data/test/suite_test.rb +1 -1
- data/test/test_test.rb +8 -15
- data/test/view/base_tests.rb +20 -37
- metadata +17 -39
- data/lib/assert/autorun.rb +0 -37
- data/lib/assert/options.rb +0 -43
- data/lib/assert/rake_tasks.rb +0 -75
- data/lib/assert/rake_tasks/irb.rb +0 -33
- data/lib/assert/rake_tasks/scope.rb +0 -100
- data/lib/assert/rake_tasks/test_task.rb +0 -66
- data/lib/assert/result_set.rb +0 -17
- data/lib/assert/setup.rb +0 -3
- data/lib/assert/setup/all.rb +0 -5
- data/lib/assert/setup/helpers.rb +0 -72
- data/lib/assert/setup/options.rb +0 -6
- data/lib/assert/setup/runner.rb +0 -13
- data/lib/assert/setup/suite.rb +0 -13
- data/lib/assert/setup/view.rb +0 -39
- data/lib/assert/view/helpers/capture_output.rb +0 -23
- data/test/default_view_test.rb +0 -16
- data/test/irb.rb +0 -5
- data/test/options_test.rb +0 -40
- data/test/rake_tasks/irb_test.rb +0 -45
- data/test/rake_tasks/scope_test.rb +0 -63
- data/test/rake_tasks/test_task_test.rb +0 -80
- data/test/result_set_test.rb +0 -72
@@ -0,0 +1,76 @@
|
|
1
|
+
module Assert
|
2
|
+
|
3
|
+
class AssertRunner
|
4
|
+
TEST_FILE_SUFFIXES = ['_tests.rb', '_test.rb']
|
5
|
+
USER_SETTINGS_FILE = ".assert/init.rb"
|
6
|
+
LOCAL_SETTINGS_FILE = ".assert.rb"
|
7
|
+
|
8
|
+
def initialize(test_paths, test_options)
|
9
|
+
require 'assert' # inits config singleton with the default settings
|
10
|
+
|
11
|
+
apply_user_settings
|
12
|
+
apply_local_settings
|
13
|
+
apply_option_settings(test_options)
|
14
|
+
apply_env_settings
|
15
|
+
|
16
|
+
files = test_files(test_paths.empty? ? Assert.config.test_dir : test_paths)
|
17
|
+
Assert.init(files, {
|
18
|
+
:test_dir_path => path_of(Assert.config.test_dir, files.first)
|
19
|
+
})
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
Assert.runner.run(Assert.suite, Assert.view)
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def apply_user_settings
|
29
|
+
safe_require("#{ENV['HOME']}/#{USER_SETTINGS_FILE}") if ENV['HOME']
|
30
|
+
end
|
31
|
+
|
32
|
+
def apply_local_settings
|
33
|
+
safe_require(ENV['ASSERT_LOCALFILE'] || path_of(LOCAL_SETTINGS_FILE, Dir.pwd))
|
34
|
+
end
|
35
|
+
|
36
|
+
def apply_option_settings(options)
|
37
|
+
Assert.config.apply(options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def apply_env_settings
|
41
|
+
Assert.configure do |c|
|
42
|
+
c.runner_seed ENV['ASSERT_RUNNER_SEED'].to_i if ENV['ASSERT_RUNNER_SEED']
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def test_files(test_paths)
|
49
|
+
test_paths.inject(Set.new) do |paths, path|
|
50
|
+
paths += Dir.glob("#{path}*") + Dir.glob("#{path}*/**/*")
|
51
|
+
end.select{ |p| is_test_file?(p) }.sort
|
52
|
+
end
|
53
|
+
|
54
|
+
def is_test_file?(path)
|
55
|
+
TEST_FILE_SUFFIXES.inject(false) do |result, suffix|
|
56
|
+
result || path =~ /#{suffix}$/
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def safe_require(settings_file)
|
61
|
+
require settings_file if File.exists?(settings_file)
|
62
|
+
end
|
63
|
+
|
64
|
+
# this method inspects a test path and finds the test dir path.
|
65
|
+
|
66
|
+
def path_of(segment, a_path)
|
67
|
+
full_path = File.expand_path(a_path || '.', Dir.pwd)
|
68
|
+
seg_pos = full_path.index(segment_regex(segment))
|
69
|
+
File.join(seg_pos && (seg_pos > 0) ? full_path[0..(seg_pos-1)] : full_path, segment)
|
70
|
+
end
|
71
|
+
|
72
|
+
def segment_regex(seg); /^#{seg}$|^#{seg}\/|\/#{seg}\/|\/#{seg}$/; end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
data/lib/assert/cli.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'set'
|
2
|
+
require 'assert/assert_runner'
|
2
3
|
require 'assert/version'
|
3
4
|
|
4
5
|
module Assert
|
@@ -10,75 +11,53 @@ module Assert
|
|
10
11
|
end
|
11
12
|
|
12
13
|
def initialize
|
13
|
-
@cli = CLIRB.new
|
14
|
+
@cli = CLIRB.new do
|
15
|
+
option 'runner_seed', 'Use a given seed to run tests', {
|
16
|
+
:abbrev => 's', :value => Fixnum
|
17
|
+
}
|
18
|
+
option 'show_output', 'show stdout output (do not capture)', {
|
19
|
+
:abbrev => 'o'
|
20
|
+
}
|
21
|
+
option 'halt_on_fail', 'halt a test when it fails', {
|
22
|
+
:abbrev => 't'
|
23
|
+
}
|
24
|
+
# show loaded test files, cli err backtraces, etc
|
25
|
+
option 'debug', 'run in debug mode'
|
26
|
+
end
|
14
27
|
end
|
15
28
|
|
16
29
|
def run(*args)
|
30
|
+
# default debug_mode to the env var
|
31
|
+
debug_mode = ENV['ASSERT_DEBUG'] == 'true'
|
17
32
|
begin
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
Assert::
|
33
|
+
# parse manually in the case that parsing fails before the debug arg
|
34
|
+
debug_mode ||= args.include?('-d') || args.include?('--debug')
|
35
|
+
@cli.parse!(args)
|
36
|
+
Assert::AssertRunner.new(@cli.args, @cli.opts).run
|
22
37
|
rescue CLIRB::HelpExit
|
23
38
|
puts help
|
24
39
|
rescue CLIRB::VersionExit
|
25
40
|
puts Assert::VERSION
|
26
41
|
rescue CLIRB::Error => exception
|
27
|
-
puts "#{exception.message}\n"
|
28
|
-
puts help
|
42
|
+
puts "#{exception.message}\n\n"
|
43
|
+
puts debug_mode ? exception.backtrace.join("\n") : help
|
29
44
|
exit(1)
|
30
45
|
rescue Exception => exception
|
31
46
|
puts "#{exception.class}: #{exception.message}"
|
32
|
-
puts exception.backtrace.join("\n") if
|
47
|
+
puts exception.backtrace.join("\n") if debug_mode
|
33
48
|
exit(1)
|
34
49
|
end
|
35
|
-
|
36
|
-
# Don't call `exit(0)`. The test suite runs as the by an `at_exit`
|
37
|
-
# callback. Calling `exit(0)` bypasses that callback.
|
50
|
+
exit(0)
|
38
51
|
end
|
39
52
|
|
40
53
|
def help
|
41
|
-
"Usage: assert [
|
54
|
+
"Usage: assert [options] [TESTS]\n\n"\
|
42
55
|
"Options:"\
|
43
56
|
"#{@cli}"
|
44
57
|
end
|
45
58
|
|
46
59
|
end
|
47
60
|
|
48
|
-
class CLIRunner
|
49
|
-
TEST_FILE_SUFFIXES = ['_tests.rb', '_test.rb']
|
50
|
-
|
51
|
-
attr_reader :test_files
|
52
|
-
|
53
|
-
def initialize(*args)
|
54
|
-
options, test_paths = [
|
55
|
-
args.last.kind_of?(::Hash) ? args.pop : {},
|
56
|
-
args
|
57
|
-
]
|
58
|
-
|
59
|
-
@test_files = file_paths(test_paths).select{ |f| test_file?(f) }
|
60
|
-
end
|
61
|
-
|
62
|
-
def run
|
63
|
-
@test_files.each{ |file| require file }
|
64
|
-
require 'assert' if @test_files.empty? # show empty test output
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def file_paths(test_paths)
|
70
|
-
test_paths.inject(Set.new) do |paths, path|
|
71
|
-
paths += Dir.glob("#{path}*") + Dir.glob("#{path}*/**/*")
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_file?(path)
|
76
|
-
TEST_FILE_SUFFIXES.inject(false) do |result, suffix|
|
77
|
-
result || path =~ /#{suffix}$/
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
61
|
class CLIRB # Version 1.0.0, https://github.com/redding/cli.rb
|
83
62
|
Error = Class.new(RuntimeError);
|
84
63
|
HelpExit = Class.new(RuntimeError); VersionExit = Class.new(RuntimeError)
|
data/lib/assert/context.rb
CHANGED
@@ -204,11 +204,11 @@ module Assert
|
|
204
204
|
end
|
205
205
|
|
206
206
|
# adds a Fail result to the end of the test's results
|
207
|
-
#
|
207
|
+
# break test execution if Assert.config.halt_on_fail
|
208
208
|
def fail(fail_msg=nil)
|
209
209
|
message = (fail_message(fail_msg) { }).call
|
210
|
-
if Assert
|
211
|
-
raise
|
210
|
+
if Assert.config.halt_on_fail
|
211
|
+
raise Result::TestFailure, message
|
212
212
|
else
|
213
213
|
capture_result do |test, backtrace|
|
214
214
|
Assert::Result::Fail.new(test, message, backtrace)
|
data/lib/assert/result.rb
CHANGED
@@ -17,59 +17,6 @@ module Assert::Result
|
|
17
17
|
}
|
18
18
|
end
|
19
19
|
|
20
|
-
class Backtrace < ::Array
|
21
|
-
# ripped from minitest...
|
22
|
-
|
23
|
-
file = File.expand_path __FILE__
|
24
|
-
# if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
|
25
|
-
# File.expand_path __FILE__
|
26
|
-
# elsif __FILE__ =~ /^[^\.]/ then # assume both relative
|
27
|
-
# require 'pathname'
|
28
|
-
# pwd = Pathname.new Dir.pwd
|
29
|
-
# pn = Pathname.new File.expand_path(__FILE__)
|
30
|
-
# relpath = pn.relative_path_from(pwd) rescue pn
|
31
|
-
# pn = File.join ".", relpath unless pn.relative?
|
32
|
-
# pn.to_s
|
33
|
-
# else # assume both are expanded
|
34
|
-
# __FILE__
|
35
|
-
# end
|
36
|
-
|
37
|
-
# './lib' in project dir, or '/usr/local/blahblah' if installed
|
38
|
-
ASSERT_DIR = File.dirname(File.dirname(file))
|
39
|
-
|
40
|
-
def initialize(value=nil)
|
41
|
-
super(value || ["No backtrace"])
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_s
|
45
|
-
self.join("\n")
|
46
|
-
end
|
47
|
-
|
48
|
-
def filtered
|
49
|
-
new_bt = []
|
50
|
-
|
51
|
-
self.each do |line|
|
52
|
-
break if filter_out?(line)
|
53
|
-
new_bt << line
|
54
|
-
end
|
55
|
-
|
56
|
-
new_bt = self.reject { |line| filter_out?(line) } if new_bt.empty?
|
57
|
-
new_bt = self.dup if new_bt.empty?
|
58
|
-
|
59
|
-
self.class.new(new_bt)
|
60
|
-
end
|
61
|
-
|
62
|
-
protected
|
63
|
-
|
64
|
-
def filter_out?(line)
|
65
|
-
line.rindex(ASSERT_DIR, 0)
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
# Result classes...
|
72
|
-
|
73
20
|
class Base
|
74
21
|
|
75
22
|
attr_reader :test, :message, :backtrace
|
@@ -138,8 +85,7 @@ module Assert::Result
|
|
138
85
|
end
|
139
86
|
|
140
87
|
# raised by the 'fail' context helper to break test execution
|
141
|
-
|
142
|
-
class TestFailure < RuntimeError; end
|
88
|
+
TestFailure = Class.new(RuntimeError)
|
143
89
|
|
144
90
|
class Fail < Base
|
145
91
|
|
@@ -213,6 +159,70 @@ module Assert::Result
|
|
213
159
|
def trace
|
214
160
|
self.backtrace.to_s
|
215
161
|
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
# Utility Classes
|
166
|
+
|
167
|
+
class Set < ::Array
|
168
|
+
attr_accessor :callback
|
169
|
+
|
170
|
+
def initialize(callback=nil)
|
171
|
+
@callback = callback
|
172
|
+
super()
|
173
|
+
end
|
174
|
+
|
175
|
+
def <<(result)
|
176
|
+
super
|
177
|
+
@callback.call(result) if @callback
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class Backtrace < ::Array
|
182
|
+
def initialize(value=nil)
|
183
|
+
super(value || ["No backtrace"])
|
184
|
+
end
|
185
|
+
|
186
|
+
def to_s; self.join("\n"); end
|
187
|
+
|
188
|
+
def filtered
|
189
|
+
new_bt = []
|
190
|
+
|
191
|
+
self.each do |line|
|
192
|
+
break if filter_out?(line)
|
193
|
+
new_bt << line
|
194
|
+
end
|
195
|
+
|
196
|
+
new_bt = self.reject { |line| filter_out?(line) } if new_bt.empty?
|
197
|
+
new_bt = self.dup if new_bt.empty?
|
198
|
+
|
199
|
+
self.class.new(new_bt)
|
200
|
+
end
|
201
|
+
|
202
|
+
protected
|
203
|
+
|
204
|
+
# filter a line out if it's an assert lib line
|
205
|
+
|
206
|
+
def filter_out?(line)
|
207
|
+
# from minitest (for reference)...
|
208
|
+
# file = File.expand_path __FILE__
|
209
|
+
# if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
|
210
|
+
# File.expand_path __FILE__
|
211
|
+
# elsif __FILE__ =~ /^[^\.]/ then # assume both relative
|
212
|
+
# require 'pathname'
|
213
|
+
# pwd = Pathname.new Dir.pwd
|
214
|
+
# pn = Pathname.new File.expand_path(__FILE__)
|
215
|
+
# relpath = pn.relative_path_from(pwd) rescue pn
|
216
|
+
# pn = File.join ".", relpath unless pn.relative?
|
217
|
+
# pn.to_s
|
218
|
+
# else # assume both are expanded
|
219
|
+
# __FILE__
|
220
|
+
# end
|
221
|
+
|
222
|
+
# './lib' in project dir, or '/usr/local/blahblah' if installed
|
223
|
+
assert_lib_path = File.expand_path('../..', __FILE__)
|
224
|
+
line.rindex(assert_lib_path, 0)
|
225
|
+
end
|
216
226
|
end
|
217
227
|
|
218
228
|
end
|
data/lib/assert/runner.rb
CHANGED
@@ -1,54 +1,35 @@
|
|
1
1
|
module Assert
|
2
|
+
|
2
3
|
class Runner
|
3
4
|
|
4
|
-
#
|
5
|
+
# Runner runs a suite of tests.
|
5
6
|
|
6
|
-
def
|
7
|
+
def run(suite, view)
|
7
8
|
raise ArgumentError if !suite.kind_of?(Suite)
|
8
|
-
@suite = suite
|
9
|
-
@view = view
|
10
|
-
end
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
@suite.setup
|
10
|
+
view.fire(:on_start)
|
11
|
+
suite.setup
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
suite.start_time = Time.now
|
14
|
+
# TODO: parallel running
|
15
|
+
tests_to_run(suite).each do |test|
|
16
|
+
view.fire(:before_test, test)
|
17
|
+
test.run{ |result| view.fire(:on_result, result) }
|
18
|
+
view.fire(:after_test, test)
|
19
|
+
end
|
20
|
+
suite.end_time = Time.now
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
suite.teardown
|
23
|
+
view.fire(:on_finish)
|
23
24
|
|
24
|
-
|
25
|
-
@suite.count(type)
|
25
|
+
suite.count(:failed) + suite.count(:errored)
|
26
26
|
end
|
27
27
|
|
28
28
|
protected
|
29
29
|
|
30
|
-
def tests_to_run
|
31
|
-
#
|
32
|
-
tests
|
33
|
-
srand @suite.runner_seed
|
34
|
-
tests.sort.sort_by { rand tests.size }
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def benchmark
|
40
|
-
@suite.start_time = Time.now
|
41
|
-
yield if block_given?
|
42
|
-
@suite.end_time = Time.now
|
43
|
-
end
|
44
|
-
|
45
|
-
def run_suite
|
46
|
-
# TODO: parallel running
|
47
|
-
tests_to_run.each do |test|
|
48
|
-
@view.fire(:before_test, test)
|
49
|
-
test.run {|result| @view.fire(:on_result, result)}
|
50
|
-
@view.fire(:after_test, test)
|
51
|
-
end
|
30
|
+
def tests_to_run(suite)
|
31
|
+
srand Assert.config.runner_seed # TODO: secure random??
|
32
|
+
suite.tests.sort.sort_by { rand suite.tests.size }
|
52
33
|
end
|
53
34
|
|
54
35
|
end
|
data/lib/assert/suite.rb
CHANGED
data/lib/assert/test.rb
CHANGED
@@ -1,20 +1,8 @@
|
|
1
|
-
require 'assert/result'
|
2
|
-
require 'assert/result_set'
|
3
|
-
require 'assert/options'
|
4
|
-
|
5
1
|
require 'stringio'
|
2
|
+
require 'assert/result'
|
6
3
|
|
7
4
|
module Assert
|
8
5
|
class Test
|
9
|
-
include Assert::Options
|
10
|
-
options do
|
11
|
-
default_capture_output false
|
12
|
-
default_halt_on_fail true
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.halt_on_fail?
|
16
|
-
ENV['halt_on_fail'] == 'true' || self.options.halt_on_fail
|
17
|
-
end
|
18
6
|
|
19
7
|
# a Test is some code/method to run in the scope of a Context. After a
|
20
8
|
# a test runs, it should have some assertions which are its results.
|
@@ -26,7 +14,7 @@ module Assert
|
|
26
14
|
@context_info = suite_context_info
|
27
15
|
@name = name_from_context(name)
|
28
16
|
@code = (code || block)
|
29
|
-
@results =
|
17
|
+
@results = Result::Set.new
|
30
18
|
@output = ""
|
31
19
|
end
|
32
20
|
|
@@ -36,7 +24,7 @@ module Assert
|
|
36
24
|
|
37
25
|
def run(&result_callback)
|
38
26
|
# setup the a new test run
|
39
|
-
@results =
|
27
|
+
@results = Result::Set.new(result_callback)
|
40
28
|
run_scope = self.context_class.new(self)
|
41
29
|
|
42
30
|
# run the test, capturing its output
|
@@ -118,7 +106,7 @@ module Assert
|
|
118
106
|
end
|
119
107
|
|
120
108
|
def capture_output(&block)
|
121
|
-
if
|
109
|
+
if Assert.config.show_output == false
|
122
110
|
orig_stdout = $stdout.clone
|
123
111
|
$stdout = capture_io
|
124
112
|
block.call
|