assert 1.1.0 → 2.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|