assert 0.7.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +16 -4
- data/{CHANGELOG.rdoc → CHANGELOG.md} +14 -3
- data/LICENSE +22 -0
- data/README.md +261 -0
- data/Rakefile +1 -1
- data/assert.gemspec +2 -1
- data/lib/assert/assertions.rb +16 -0
- data/lib/assert/autorun.rb +11 -7
- data/lib/assert/macros/methods.rb +49 -3
- data/lib/assert/rake_tasks.rb +13 -7
- data/lib/assert/rake_tasks/irb.rb +1 -1
- data/lib/assert/rake_tasks/scope.rb +55 -28
- data/lib/assert/rake_tasks/test_task.rb +4 -1
- data/lib/assert/result.rb +7 -9
- data/lib/assert/result_set.rb +7 -4
- data/lib/assert/runner.rb +10 -10
- data/lib/assert/setup/helpers.rb +5 -3
- data/lib/assert/setup/runner.rb +2 -3
- data/lib/assert/setup/suite.rb +2 -5
- data/lib/assert/setup/view.rb +26 -3
- data/lib/assert/test.rb +56 -37
- data/lib/assert/version.rb +1 -1
- data/lib/assert/view/base.rb +75 -0
- data/lib/assert/view/default_view.rb +75 -0
- data/lib/assert/view/helpers/ansi_styles.rb +25 -0
- data/lib/assert/view/helpers/capture_output.rb +23 -0
- data/lib/assert/view/helpers/common.rb +154 -0
- data/test/assertions/assert_file_exists_test.rb +43 -0
- data/test/assertions/assert_not_file_exists_test.rb +43 -0
- data/test/assertions_test.rb +4 -1
- data/test/macro_test.rb +25 -0
- data/test/rake_tasks/irb_test.rb +2 -2
- data/test/rake_tasks/scope_test.rb +9 -9
- data/test/result_set_test.rb +13 -23
- data/test/runner_test.rb +1 -1
- data/test/test/{running_test.rb → running_tests.rb} +14 -14
- data/test/view/base_tests.rb +65 -0
- metadata +29 -18
- data/Gemfile.lock +0 -23
- data/README.rdoc +0 -183
data/lib/assert/rake_tasks.rb
CHANGED
@@ -9,18 +9,24 @@ require 'assert/rake_tasks/test_task'
|
|
9
9
|
|
10
10
|
module Assert::RakeTasks
|
11
11
|
|
12
|
-
FILE_SUFFIX = "_test.rb"
|
13
|
-
|
14
12
|
# Setup the rake tasks for testing
|
15
13
|
# * add 'include Assert::RakeTasks' to your Rakefile
|
16
14
|
def self.included(receiver)
|
17
|
-
# auto-
|
18
|
-
self.
|
15
|
+
# auto-install rake tasks
|
16
|
+
self.install
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.install
|
20
|
+
assert_test_root = ENV['ASSERT_TEST_ROOT'] || './test'
|
21
|
+
|
22
|
+
if File.exists?(assert_test_root)
|
23
|
+
self.irb_task(Assert::RakeTasks::Irb.new(assert_test_root))
|
24
|
+
self.to_tasks(Assert::RakeTasks::Scope.new(assert_test_root))
|
25
|
+
end
|
19
26
|
end
|
20
27
|
|
21
|
-
def self.for(
|
22
|
-
|
23
|
-
self.to_tasks(Assert::RakeTasks::Scope.new(test_root.to_s))
|
28
|
+
def self.for(test_root_name)
|
29
|
+
warn "[DEPRECATED] `Assert::RakeTasts.for` has been deprecated. Use `Assert::RakeTasks.install` instead."
|
24
30
|
end
|
25
31
|
|
26
32
|
class << self
|
@@ -4,29 +4,25 @@ require 'assert/rake_tasks/test_task'
|
|
4
4
|
module Assert::RakeTasks
|
5
5
|
class Scope
|
6
6
|
|
7
|
-
def self.
|
8
|
-
|
7
|
+
def self.test_file_suffixes
|
8
|
+
['_test.rb', '_tests.rb']
|
9
9
|
end
|
10
10
|
|
11
|
+
attr_reader :path, :nested_files, :path_file_list, :test_tasks, :scopes
|
12
|
+
|
11
13
|
def initialize(path)
|
12
14
|
@path = path
|
15
|
+
|
16
|
+
@nested_files = get_nested_files
|
17
|
+
@path_file_list = build_path_file_list
|
18
|
+
@test_tasks = build_test_tasks
|
19
|
+
@scopes = build_scopes
|
13
20
|
end
|
14
21
|
|
15
22
|
def namespace
|
16
23
|
File.basename(@path).to_sym
|
17
24
|
end
|
18
25
|
|
19
|
-
# nested test files under the path
|
20
|
-
def nested_files
|
21
|
-
nested_files = Rake::FileList["#{@path}/**/*#{self.class.test_file_suffix}"]
|
22
|
-
end
|
23
|
-
|
24
|
-
# a list with the path test file "#{path}_test.rb" (if it exists)
|
25
|
-
def path_file_list
|
26
|
-
path_file_name = @path+self.class.test_file_suffix
|
27
|
-
(File.exists?(path_file_name) ? Rake::FileList[path_file_name] : [])
|
28
|
-
end
|
29
|
-
|
30
26
|
# return a test task covering the scopes nested files plus path file
|
31
27
|
# but only if there are nested files
|
32
28
|
def to_test_task
|
@@ -37,32 +33,63 @@ module Assert::RakeTasks
|
|
37
33
|
end
|
38
34
|
end
|
39
35
|
|
36
|
+
protected
|
37
|
+
|
38
|
+
# nested test files under the path
|
39
|
+
|
40
|
+
def get_nested_files
|
41
|
+
self.class.test_file_suffixes.map do |suffix|
|
42
|
+
Rake::FileList["#{@path}/**/*#{suffix}"]
|
43
|
+
end.flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
# a list with the path test file "#{path}_test.rb" (if it exists)
|
47
|
+
|
48
|
+
def build_path_file_list
|
49
|
+
self.class.test_file_suffixes.map do |suffix|
|
50
|
+
path_file_name = "#{@path}#{suffix}"
|
51
|
+
File.exists?(path_file_name) ? Rake::FileList[path_file_name] : []
|
52
|
+
end.flatten
|
53
|
+
end
|
54
|
+
|
40
55
|
# a collection of test tasks for every standalone child test file
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# get
|
45
|
-
|
46
|
-
|
56
|
+
|
57
|
+
def build_test_tasks
|
58
|
+
self.class.test_file_suffixes.map do |suffix|
|
59
|
+
# get immediate child test files
|
60
|
+
Dir.glob("#{@path}/*#{suffix}").collect do |f|
|
61
|
+
# get just the path name for each file
|
62
|
+
File.join(File.dirname(f), File.basename(f, suffix))
|
63
|
+
end
|
64
|
+
end.flatten.reject do |p|
|
47
65
|
# reject any that have deeply nested test files
|
48
|
-
|
66
|
+
self.class.test_file_suffixes.inject(false) do |result, suffix|
|
67
|
+
result || !Dir.glob("#{p}/**/*#{suffix}").empty?
|
68
|
+
end
|
49
69
|
end.collect do |p|
|
50
70
|
# build a test task for the standalone test file of the path
|
51
71
|
TestTask.new(p) do |tt|
|
52
|
-
tt.files =
|
72
|
+
tt.files = self.class.test_file_suffixes.map do |suffix|
|
73
|
+
(File.exists?("#{p}#{suffix}") ? Rake::FileList["#{p}#{suffix}"] : [])
|
74
|
+
end.flatten
|
53
75
|
end
|
54
76
|
end
|
55
77
|
end
|
56
78
|
|
57
79
|
# a collection of scopes for every child test dir or test dir/file combo
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
# get
|
62
|
-
|
63
|
-
|
80
|
+
|
81
|
+
def build_scopes
|
82
|
+
self.class.test_file_suffixes.map do |suffix|
|
83
|
+
# get immediate child paths
|
84
|
+
Dir.glob("#{@path}/*").collect do |p|
|
85
|
+
# get just the path name for each dir/file and uniq it
|
86
|
+
File.join(File.dirname(p), File.basename(p, suffix))
|
87
|
+
end
|
88
|
+
end.flatten.uniq.select do |p|
|
64
89
|
# select any that have deeply nested test files
|
65
|
-
|
90
|
+
self.class.test_file_suffixes.inject(false) do |result, suffix|
|
91
|
+
result || !Dir.glob("#{p}/**/*#{suffix}").empty?
|
92
|
+
end
|
66
93
|
end.collect do |p|
|
67
94
|
# build a scope for each path
|
68
95
|
self.class.new(p)
|
@@ -26,7 +26,10 @@ module Assert::RakeTasks
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def name
|
29
|
-
File.basename(@path, Scope.test_file_suffix).to_sym
|
29
|
+
# File.basename(@path, Scope.test_file_suffix).to_sym
|
30
|
+
@name ||= File.basename(@path).tap do |bname|
|
31
|
+
Scope.test_file_suffixes.each { |suffix| bname.gsub(suffix, '') }
|
32
|
+
end.to_sym
|
30
33
|
end
|
31
34
|
|
32
35
|
def file_list # :nodoc:
|
data/lib/assert/result.rb
CHANGED
@@ -8,15 +8,13 @@ module Assert::Result
|
|
8
8
|
class Error < Base; end
|
9
9
|
class Skip < Base; end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
}
|
19
|
-
end
|
11
|
+
def self.types
|
12
|
+
{ :pass => Pass,
|
13
|
+
:fail => Fail,
|
14
|
+
:ignore => Ignore,
|
15
|
+
:skip => Skip,
|
16
|
+
:error => Error
|
17
|
+
}
|
20
18
|
end
|
21
19
|
|
22
20
|
class Backtrace < ::Array
|
data/lib/assert/result_set.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
module Assert
|
2
2
|
class ResultSet < ::Array
|
3
3
|
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :callback
|
5
|
+
|
6
|
+
def initialize(callback=nil)
|
7
|
+
@callback = callback
|
8
|
+
super()
|
9
|
+
end
|
5
10
|
|
6
11
|
def <<(result)
|
7
12
|
super
|
8
|
-
|
9
|
-
@view.handle_runtime_result(result)
|
10
|
-
end
|
13
|
+
@callback.call(result) if @callback
|
11
14
|
end
|
12
15
|
|
13
16
|
end
|
data/lib/assert/runner.rb
CHANGED
@@ -9,19 +9,15 @@ module Assert
|
|
9
9
|
@view = view
|
10
10
|
end
|
11
11
|
|
12
|
-
def run
|
12
|
+
def run
|
13
|
+
@view.fire(:on_start)
|
13
14
|
@suite.setup
|
14
15
|
|
15
|
-
|
16
|
-
# render the view, passing it a callback block to run the test suite
|
17
|
-
@view.render do
|
18
|
-
benchmark { run_suite }
|
19
|
-
end
|
20
|
-
else
|
21
|
-
benchmark { run_suite }
|
22
|
-
end
|
16
|
+
benchmark { run_suite }
|
23
17
|
|
24
18
|
@suite.teardown
|
19
|
+
@view.fire(:on_finish)
|
20
|
+
|
25
21
|
count(:failed) + count(:errored)
|
26
22
|
end
|
27
23
|
|
@@ -48,7 +44,11 @@ module Assert
|
|
48
44
|
|
49
45
|
def run_suite
|
50
46
|
# TODO: parallel running
|
51
|
-
tests_to_run.each
|
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
|
52
52
|
end
|
53
53
|
|
54
54
|
end
|
data/lib/assert/setup/helpers.rb
CHANGED
@@ -8,9 +8,10 @@ module Assert
|
|
8
8
|
# the user-specific helper file will always be required in after the
|
9
9
|
# package-specific one
|
10
10
|
|
11
|
-
|
11
|
+
USER_TEST_DIR = './.assert'
|
12
|
+
USER_TEST_HELPER = 'options'
|
12
13
|
|
13
|
-
|
14
|
+
class << self
|
14
15
|
|
15
16
|
# assume the test dir path is ./test and look for helpers in ./test/helper.rb
|
16
17
|
def package_test_dir
|
@@ -34,7 +35,8 @@ module Assert
|
|
34
35
|
|
35
36
|
def require_user_test_helper
|
36
37
|
if ENV['HOME']
|
37
|
-
|
38
|
+
helper_path = File.join(USER_TEST_DIR, USER_TEST_HELPER)
|
39
|
+
safe_require File.expand_path(helper_path, ENV['HOME'])
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
data/lib/assert/setup/runner.rb
CHANGED
@@ -2,13 +2,12 @@ require 'assert/options'
|
|
2
2
|
require 'assert/runner'
|
3
3
|
|
4
4
|
module Assert
|
5
|
+
|
5
6
|
# Setup the default global runner for running tests
|
6
7
|
options do
|
7
8
|
default_runner Runner
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
def runner; self.options.runner; end
|
12
|
-
end
|
11
|
+
def self.runner; self.options.runner; end
|
13
12
|
|
14
13
|
end
|
data/lib/assert/setup/suite.rb
CHANGED
@@ -2,15 +2,12 @@ require 'assert/context'
|
|
2
2
|
require 'assert/suite'
|
3
3
|
|
4
4
|
module Assert
|
5
|
+
|
5
6
|
# Setup the default global suite for collecting tests as contexts are defined
|
6
7
|
options do
|
7
8
|
default_suite Suite.new
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
def suite
|
12
|
-
self.options.suite
|
13
|
-
end
|
14
|
-
end
|
11
|
+
def self.suite; self.options.suite; end
|
15
12
|
|
16
13
|
end
|
data/lib/assert/setup/view.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'assert/setup/helpers'
|
1
2
|
require 'assert/view/default_view'
|
2
3
|
|
3
4
|
module Assert
|
@@ -8,9 +9,31 @@ module Assert
|
|
8
9
|
default_view View::DefaultView.new($stdout)
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def self.view; self.options.view; end
|
13
|
+
|
14
|
+
module View
|
15
|
+
|
16
|
+
# this method is used to bring in custom user-specific views
|
17
|
+
# require views by passing either a full path to the view ruby file
|
18
|
+
# or passing the name of a view installed in ~/.assert/views
|
19
|
+
|
20
|
+
def self.require_user_view(view)
|
21
|
+
user_test_root = File.expand_path(Assert::Helpers::USER_TEST_DIR, ENV['HOME'])
|
22
|
+
views_file = File.join(user_test_root, 'views', view, 'lib', view)
|
23
|
+
|
24
|
+
if File.exists?(view) || File.exists?(view+'.rb')
|
25
|
+
require view
|
26
|
+
elsif ENV['HOME'] && File.exists?(views_file+'.rb')
|
27
|
+
require views_file
|
28
|
+
else
|
29
|
+
msg = "[WARN] Can't find or require #{view.inspect} view."
|
30
|
+
if !view.match(/\A\//)
|
31
|
+
msg << " Did you install it in `~/.assert/views`?"
|
32
|
+
end
|
33
|
+
warn msg
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
14
37
|
end
|
15
38
|
|
16
39
|
end
|
data/lib/assert/test.rb
CHANGED
@@ -34,44 +34,29 @@ module Assert
|
|
34
34
|
self.context_info.klass
|
35
35
|
end
|
36
36
|
|
37
|
-
def run(
|
38
|
-
|
37
|
+
def run(&result_callback)
|
38
|
+
# setup the a new test run
|
39
|
+
@results = ResultSet.new(result_callback)
|
39
40
|
run_scope = self.context_class.new(self)
|
40
|
-
|
41
|
+
|
42
|
+
# run the test, capturing its output
|
43
|
+
begin
|
44
|
+
run_test_setup(run_scope)
|
45
|
+
run_test_code(run_scope)
|
46
|
+
rescue Result::TestFailure => err
|
47
|
+
@results << Result::Fail.new(self, err)
|
48
|
+
rescue Result::TestSkipped => err
|
49
|
+
@results << Result::Skip.new(self, err)
|
50
|
+
rescue Exception => err
|
51
|
+
@results << Result::Error.new(self, err)
|
52
|
+
ensure
|
41
53
|
begin
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
if run_scope.respond_to?(:setup)
|
46
|
-
run_scope.setup
|
47
|
-
end
|
48
|
-
|
49
|
-
# run the actual test code
|
50
|
-
if @code.kind_of?(::Proc)
|
51
|
-
run_scope.instance_eval(&@code)
|
52
|
-
elsif run_scope.respond_to?(@code.to_s)
|
53
|
-
run_scope.send(@code.to_s)
|
54
|
-
end
|
55
|
-
rescue Result::TestFailure => err
|
56
|
-
@results << Result::Fail.new(self, err)
|
57
|
-
rescue Result::TestSkipped => err
|
58
|
-
@results << Result::Skip.new(self, err)
|
59
|
-
rescue Exception => err
|
60
|
-
@results << Result::Error.new(self, err)
|
61
|
-
ensure
|
62
|
-
begin
|
63
|
-
# run any classic test/unit style 'def teardown' teardowns
|
64
|
-
if run_scope.respond_to?(:teardown)
|
65
|
-
run_scope.teardown
|
66
|
-
end
|
67
|
-
# run any assert style 'teardown do' teardowns
|
68
|
-
self.context_class.teardown(run_scope)
|
69
|
-
rescue Exception => teardown_err
|
70
|
-
@results << Result::Error.new(self, teardown_err)
|
71
|
-
end
|
54
|
+
run_test_teardown(run_scope)
|
55
|
+
rescue Exception => teardown_err
|
56
|
+
@results << Result::Error.new(self, teardown_err)
|
72
57
|
end
|
73
58
|
end
|
74
|
-
|
59
|
+
# return the results of the test run
|
75
60
|
@results
|
76
61
|
end
|
77
62
|
|
@@ -102,10 +87,40 @@ module Assert
|
|
102
87
|
|
103
88
|
protected
|
104
89
|
|
105
|
-
def
|
106
|
-
|
90
|
+
def run_test_setup(scope)
|
91
|
+
capture_output do
|
92
|
+
# run any assert style 'setup do' setups
|
93
|
+
self.context_class.setup(scope)
|
94
|
+
|
95
|
+
# run any classic test/unit style 'def setup' setups
|
96
|
+
scope.setup if scope.respond_to?(:setup)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def run_test_code(scope)
|
101
|
+
capture_output do
|
102
|
+
if @code.kind_of?(::Proc)
|
103
|
+
scope.instance_eval(&@code)
|
104
|
+
elsif scope.respond_to?(@code.to_s)
|
105
|
+
scope.send(@code.to_s)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def run_test_teardown(scope)
|
111
|
+
capture_output do
|
112
|
+
# run any classic test/unit style 'def teardown' teardowns
|
113
|
+
scope.teardown if scope.respond_to?(:teardown)
|
114
|
+
|
115
|
+
# run any assert style 'teardown do' teardowns
|
116
|
+
self.context_class.teardown(scope)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def capture_output(&block)
|
121
|
+
if self.class.options.capture_output
|
107
122
|
orig_stdout = $stdout.clone
|
108
|
-
$stdout =
|
123
|
+
$stdout = capture_io
|
109
124
|
block.call
|
110
125
|
$stdout = orig_stdout
|
111
126
|
else
|
@@ -113,6 +128,10 @@ module Assert
|
|
113
128
|
end
|
114
129
|
end
|
115
130
|
|
131
|
+
def capture_io
|
132
|
+
StringIO.new(@output, "a+")
|
133
|
+
end
|
134
|
+
|
116
135
|
def name_from_context(name)
|
117
136
|
[ self.context_class.description,
|
118
137
|
name
|