assert 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +21 -0
- data/Gemfile.lock +4 -4
- data/README.rdoc +18 -1
- data/assert.gemspec +1 -1
- data/lib/assert/assertions.rb +4 -4
- data/lib/assert/autorun.rb +1 -1
- data/lib/assert/context.rb +50 -38
- data/lib/assert/macros/methods.rb +15 -4
- data/lib/assert/rake_tasks.rb +34 -78
- data/lib/assert/rake_tasks/irb.rb +33 -0
- data/lib/assert/rake_tasks/scope.rb +73 -0
- data/lib/assert/rake_tasks/test_task.rb +63 -0
- data/lib/assert/result.rb +84 -36
- data/lib/assert/setup/helpers.rb +7 -4
- data/lib/assert/suite.rb +45 -61
- data/lib/assert/test.rb +22 -11
- data/lib/assert/version.rb +1 -1
- data/test/assertions_test.rb +1 -1
- data/test/context/class_methods_test.rb +22 -17
- data/test/context_test.rb +64 -12
- data/test/fixtures/test_root/one_test.rb +0 -0
- data/test/fixtures/test_root/parent/area_one/area_test.rb +0 -0
- data/test/fixtures/test_root/shallow/deeply/nested_test.rb +0 -0
- data/test/fixtures/test_root/shallow/nested_test.rb +0 -0
- data/test/fixtures/test_root/shallow_test.rb +0 -0
- data/test/fixtures/test_root/two_test.rb +0 -0
- data/test/helper.rb +24 -5
- data/test/rake_tasks/irb_test.rb +45 -0
- data/test/rake_tasks/scope_test.rb +63 -0
- data/test/rake_tasks/test_task_test.rb +80 -0
- data/test/result_set_test.rb +4 -4
- data/test/result_test.rb +78 -45
- data/test/suite/context_info_test.rb +42 -0
- data/test/suite_test.rb +9 -46
- data/test/test/running_test.rb +2 -3
- data/test/test_test.rb +9 -8
- metadata +31 -7
@@ -0,0 +1,33 @@
|
|
1
|
+
module Assert::RakeTasks
|
2
|
+
class Irb
|
3
|
+
|
4
|
+
def self.file_name
|
5
|
+
"irb.rb"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.task_name
|
9
|
+
:irb
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(test_root)
|
13
|
+
@test_root = test_root
|
14
|
+
end
|
15
|
+
|
16
|
+
def file_path
|
17
|
+
File.join(@test_root.to_s, self.class.file_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def helper_exists?
|
21
|
+
File.exists?(self.file_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def description
|
25
|
+
"Open irb preloaded with #{self.file_path}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def cmd
|
29
|
+
"irb -rubygems -r ./#{self.file_path}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'rake/tasklib'
|
2
|
+
require 'assert/rake_tasks/test_task'
|
3
|
+
|
4
|
+
module Assert::RakeTasks
|
5
|
+
class Scope
|
6
|
+
|
7
|
+
def self.test_file_suffix
|
8
|
+
"_test.rb"
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(path)
|
12
|
+
@path = path
|
13
|
+
end
|
14
|
+
|
15
|
+
def namespace
|
16
|
+
File.basename(@path).to_sym
|
17
|
+
end
|
18
|
+
|
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
|
+
# return a test task covering the scopes nested files plus path file
|
31
|
+
# but only if there are nested files
|
32
|
+
def to_test_task
|
33
|
+
if !self.nested_files.empty?
|
34
|
+
TestTask.new(@path) do |tt|
|
35
|
+
tt.files = self.path_file_list + self.nested_files
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# a collection of test tasks for every standalone child test file
|
41
|
+
def test_tasks
|
42
|
+
# get immediate child test files
|
43
|
+
Dir.glob("#{@path}/*#{self.class.test_file_suffix}").collect do |f|
|
44
|
+
# get just the path name for each file
|
45
|
+
File.join(File.dirname(f), File.basename(f, self.class.test_file_suffix))
|
46
|
+
end.reject do |p|
|
47
|
+
# reject any that have deeply nested test files
|
48
|
+
!Dir.glob("#{p}/**/*#{self.class.test_file_suffix}").empty?
|
49
|
+
end.collect do |p|
|
50
|
+
# build a test task for the standalone test file of the path
|
51
|
+
TestTask.new(p) do |tt|
|
52
|
+
tt.files = Rake::FileList[p+self.class.test_file_suffix]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# a collection of scopes for every child test dir or test dir/file combo
|
58
|
+
def scopes
|
59
|
+
# get immediate child paths
|
60
|
+
Dir.glob("#{@path}/*").collect do |p|
|
61
|
+
# get just the path name for each dir/file and uniq it
|
62
|
+
File.join(File.dirname(p), File.basename(p, self.class.test_file_suffix))
|
63
|
+
end.uniq.select do |p|
|
64
|
+
# select any that have deeply nested test files
|
65
|
+
!Dir.glob("#{p}/**/*#{self.class.test_file_suffix}").empty?
|
66
|
+
end.collect do |p|
|
67
|
+
# build a scope for each path
|
68
|
+
self.class.new(p)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'assert/rake_tasks/scope'
|
2
|
+
|
3
|
+
module Assert::RakeTasks
|
4
|
+
|
5
|
+
class TestTask
|
6
|
+
|
7
|
+
attr_accessor :name, :path, :files
|
8
|
+
|
9
|
+
# Create a testing task
|
10
|
+
def initialize(path)
|
11
|
+
@path = path
|
12
|
+
@files = []
|
13
|
+
yield self if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
def relative_path
|
17
|
+
File.join(@path.to_s.split(File::SEPARATOR)[1..-1])
|
18
|
+
end
|
19
|
+
|
20
|
+
def scope_description
|
21
|
+
relative_path.empty? ? "" : " for #{relative_path}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def description
|
25
|
+
"Run all tests#{scope_description}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def name
|
29
|
+
File.basename(@path, Scope.test_file_suffix).to_sym
|
30
|
+
end
|
31
|
+
|
32
|
+
def file_list # :nodoc:
|
33
|
+
self.files.collect{|f| "\"#{f}\""}.join(' ')
|
34
|
+
end
|
35
|
+
|
36
|
+
def ruby_args
|
37
|
+
[ "-rrubygems",
|
38
|
+
"\"#{self.rake_loader}\"",
|
39
|
+
self.file_list
|
40
|
+
].compact.join(" ")
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_loaded_files?
|
44
|
+
ENV["show_loaded_files"] == 'true'
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def rake_loader
|
50
|
+
find_file('rake/rake_test_loader')
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_file(fn) # :nodoc:
|
54
|
+
$LOAD_PATH.each do |path|
|
55
|
+
file_path = File.join(path, "#{fn}.rb")
|
56
|
+
return file_path if File.exist? file_path
|
57
|
+
end
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/lib/assert/result.rb
CHANGED
@@ -3,11 +3,10 @@ module Assert::Result
|
|
3
3
|
|
4
4
|
class Base; end
|
5
5
|
class Pass < Base; end
|
6
|
-
class Fail < Base; end
|
7
6
|
class Ignore < Base; end
|
8
|
-
class
|
9
|
-
class Error <
|
10
|
-
class Skip <
|
7
|
+
class Fail < Base; end
|
8
|
+
class Error < Base; end
|
9
|
+
class Skip < Base; end
|
11
10
|
|
12
11
|
class << self
|
13
12
|
def types
|
@@ -39,7 +38,6 @@ module Assert::Result
|
|
39
38
|
|
40
39
|
# './lib' in project dir, or '/usr/local/blahblah' if installed
|
41
40
|
ASSERT_DIR = File.dirname(File.dirname(file))
|
42
|
-
MACROS_DIR = File.join(File.dirname(file), 'macros')
|
43
41
|
|
44
42
|
def initialize(value=nil)
|
45
43
|
super(value || ["No backtrace"])
|
@@ -66,7 +64,7 @@ module Assert::Result
|
|
66
64
|
protected
|
67
65
|
|
68
66
|
def filter_out?(line)
|
69
|
-
line.rindex(ASSERT_DIR, 0)
|
67
|
+
line.rindex(ASSERT_DIR, 0)
|
70
68
|
end
|
71
69
|
|
72
70
|
end
|
@@ -76,11 +74,11 @@ module Assert::Result
|
|
76
74
|
|
77
75
|
class Base
|
78
76
|
|
79
|
-
attr_reader :
|
77
|
+
attr_reader :test, :message, :backtrace
|
80
78
|
|
81
|
-
def initialize(
|
79
|
+
def initialize(test, message, backtrace=nil)
|
80
|
+
@test = test
|
82
81
|
@backtrace = Backtrace.new(backtrace)
|
83
|
-
@test_name = test_name
|
84
82
|
@message = message && !message.empty? ? message : nil
|
85
83
|
end
|
86
84
|
|
@@ -88,10 +86,21 @@ module Assert::Result
|
|
88
86
|
define_method("#{meth}?") { false }
|
89
87
|
end
|
90
88
|
|
89
|
+
def test_name
|
90
|
+
@test.name
|
91
|
+
end
|
92
|
+
|
91
93
|
def to_sym; nil; end
|
92
94
|
|
93
95
|
def to_s
|
94
|
-
[
|
96
|
+
[ "#{self.name.upcase}: #{self.test_name}",
|
97
|
+
self.message,
|
98
|
+
self.trace
|
99
|
+
].compact.join("\n")
|
100
|
+
end
|
101
|
+
|
102
|
+
def name
|
103
|
+
""
|
95
104
|
end
|
96
105
|
|
97
106
|
def trace
|
@@ -109,58 +118,97 @@ module Assert::Result
|
|
109
118
|
end
|
110
119
|
|
111
120
|
class Pass < Base
|
121
|
+
|
112
122
|
def pass?; true; end
|
113
|
-
def to_sym; :
|
123
|
+
def to_sym; :pass; end
|
114
124
|
|
115
|
-
def
|
116
|
-
"
|
125
|
+
def name
|
126
|
+
"Pass"
|
117
127
|
end
|
118
|
-
end
|
119
|
-
|
120
|
-
class Fail < Base
|
121
|
-
def fail?; true; end
|
122
|
-
def to_sym; :failed; end
|
123
128
|
|
124
|
-
def to_s
|
125
|
-
"FAIL: #{super}"
|
126
|
-
end
|
127
129
|
end
|
128
130
|
|
129
131
|
class Ignore < Base
|
132
|
+
|
130
133
|
def ignore?; true; end
|
131
|
-
def to_sym; :
|
134
|
+
def to_sym; :ignore; end
|
132
135
|
|
133
|
-
def
|
134
|
-
"
|
136
|
+
def name
|
137
|
+
"Ignore"
|
135
138
|
end
|
139
|
+
|
136
140
|
end
|
137
141
|
|
138
|
-
#
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
+
# raised by the 'fail' context helper to break test execution
|
143
|
+
# (if Test.halt_on_fail?)
|
144
|
+
class TestFailure < RuntimeError; end
|
145
|
+
|
146
|
+
class Fail < Base
|
147
|
+
|
148
|
+
# fail results can be generated manually or by raising Assert::Result::TestFailure
|
149
|
+
def initialize(test, message_or_exception, backtrace=nil)
|
150
|
+
if message_or_exception.kind_of?(TestFailure)
|
151
|
+
super(test, message_or_exception.message, message_or_exception.backtrace || [])
|
152
|
+
elsif message_or_exception.kind_of?(Exception)
|
153
|
+
raise ArgumentError, "generate fail results by raising Assert::Result::TestFailure"
|
154
|
+
else
|
155
|
+
super(test, message_or_exception, backtrace)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def fail?; true; end
|
160
|
+
def to_sym; :fail; end
|
161
|
+
|
162
|
+
def name
|
163
|
+
"Fail"
|
142
164
|
end
|
165
|
+
|
166
|
+
# override of the base, show the test's context info called_from
|
167
|
+
def trace
|
168
|
+
self.test.context_info.called_from
|
169
|
+
end
|
170
|
+
|
143
171
|
end
|
144
172
|
|
145
173
|
# raised by the 'skip' context helper to break test execution
|
146
174
|
class TestSkipped < RuntimeError; end
|
147
175
|
|
148
|
-
class Skip <
|
176
|
+
class Skip < Base
|
177
|
+
|
178
|
+
# skip results are generated by raising Assert::Result::TestSkipped
|
179
|
+
def initialize(test, exception)
|
180
|
+
if exception.kind_of?(TestSkipped)
|
181
|
+
super(test, exception.message, exception.backtrace || [])
|
182
|
+
else
|
183
|
+
raise ArgumentError, "generate skip results by raising Assert::Result::TestSkipped"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
149
187
|
def skip?; true; end
|
150
|
-
def to_sym; :
|
188
|
+
def to_sym; :skip; end
|
151
189
|
|
152
|
-
def
|
153
|
-
"
|
190
|
+
def name
|
191
|
+
"Skip"
|
154
192
|
end
|
193
|
+
|
155
194
|
end
|
156
195
|
|
157
|
-
class Error <
|
196
|
+
class Error < Base
|
197
|
+
|
198
|
+
# error results are generated by raising exceptions in tests
|
199
|
+
def initialize(test, exception)
|
200
|
+
if exception.kind_of?(Exception)
|
201
|
+
super(test, "#{exception.message} (#{exception.class.name})", exception.backtrace || [])
|
202
|
+
else
|
203
|
+
raise ArgumentError, "generate error results by raising an exception"
|
204
|
+
end
|
205
|
+
end
|
158
206
|
|
159
207
|
def error?; true; end
|
160
|
-
def to_sym; :
|
208
|
+
def to_sym; :error; end
|
161
209
|
|
162
|
-
def
|
163
|
-
"
|
210
|
+
def name
|
211
|
+
"Error"
|
164
212
|
end
|
165
213
|
|
166
214
|
# override of the base, always show the full unfiltered backtrace for errors
|
data/lib/assert/setup/helpers.rb
CHANGED
@@ -11,7 +11,7 @@ module Assert
|
|
11
11
|
class << self
|
12
12
|
|
13
13
|
USER_TEST_HELPER = "~/.assert/options"
|
14
|
-
|
14
|
+
|
15
15
|
# assume the test dir path is ./test and look for helpers in ./test/helper.rb
|
16
16
|
def package_test_dir
|
17
17
|
"test"
|
@@ -34,7 +34,9 @@ module Assert
|
|
34
34
|
|
35
35
|
def require_user_test_helper
|
36
36
|
begin
|
37
|
-
|
37
|
+
if ENV['HOME']
|
38
|
+
require File.expand_path(USER_TEST_HELPER)
|
39
|
+
end
|
38
40
|
rescue LoadError => err
|
39
41
|
# do nothing
|
40
42
|
end
|
@@ -45,7 +47,7 @@ module Assert
|
|
45
47
|
begin
|
46
48
|
require package_helper_file(root_path)
|
47
49
|
rescue LoadError => err
|
48
|
-
|
50
|
+
# do nothing
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -57,7 +59,8 @@ module Assert
|
|
57
59
|
# this expects the caller's root path to be the parent dir of the first
|
58
60
|
# parent dir of caller named TEST_DIR
|
59
61
|
def caller_root_path(caller_info)
|
60
|
-
|
62
|
+
non_custom_require_caller_info = caller_info.reject{|i| i =~ /rubygems\/custom_require.rb/}
|
63
|
+
caller_dirname = File.expand_path(File.dirname(non_custom_require_caller_info[0]))
|
61
64
|
test_dir_pos = caller_dirname.index(package_test_helper_regex)
|
62
65
|
if test_dir_pos && (test_dir_pos > 0)
|
63
66
|
caller_dirname[0..(test_dir_pos-1)]
|
data/lib/assert/suite.rb
CHANGED
@@ -1,15 +1,38 @@
|
|
1
1
|
require 'assert/test'
|
2
2
|
|
3
3
|
module Assert
|
4
|
-
class Suite
|
4
|
+
class Suite
|
5
|
+
|
6
|
+
class ContextInfo
|
7
|
+
|
8
|
+
attr_reader :klass, :called_from, :file
|
9
|
+
|
10
|
+
def initialize(klass, called_from=nil)
|
11
|
+
@klass = klass
|
12
|
+
@called_from = called_from
|
13
|
+
@file = if called_from
|
14
|
+
called_from.gsub(/\:[0-9]+.*$/, '')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
TEST_METHOD_REGEX = /^test./
|
5
21
|
|
6
22
|
# A suite is a set of tests to run. When a test class subclasses
|
7
23
|
# the Context class, that test class is pushed to the suite.
|
8
24
|
|
9
|
-
attr_accessor :start_time, :end_time
|
25
|
+
attr_accessor :tests, :test_methods, :start_time, :end_time
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@tests = []
|
29
|
+
@test_methods = []
|
30
|
+
@start_time = 0
|
31
|
+
@end_time = 0
|
32
|
+
end
|
10
33
|
|
11
34
|
def run_time
|
12
|
-
|
35
|
+
@end_time - @start_time
|
13
36
|
end
|
14
37
|
|
15
38
|
def runner_seed
|
@@ -19,42 +42,12 @@ module Assert
|
|
19
42
|
end).to_i
|
20
43
|
end
|
21
44
|
|
22
|
-
|
23
|
-
# gsub off any trailing 'Test'
|
24
|
-
self[context_klass] ||= []
|
25
|
-
end
|
26
|
-
|
27
|
-
def contexts
|
28
|
-
self.keys.sort{|a,b| a.to_s <=> b.to_s}
|
29
|
-
end
|
30
|
-
|
31
|
-
def tests
|
32
|
-
prep
|
33
|
-
self.values.flatten
|
34
|
-
end
|
35
|
-
|
36
|
-
def ordered_tests(klass=nil)
|
37
|
-
prep
|
38
|
-
(klass.nil? ? self.contexts : [klass]).inject([]) do |tests, klass|
|
39
|
-
tests += (self[klass] || [])
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def ordered_results(klass=nil)
|
44
|
-
ordered_tests(klass).inject([]) do |results, test|
|
45
|
-
results += test.results
|
46
|
-
end
|
47
|
-
end
|
45
|
+
alias_method :ordered_tests, :tests
|
48
46
|
|
49
|
-
def
|
50
|
-
|
51
|
-
count_tests(klass.nil? ? self.values : [self[klass]])
|
52
|
-
end
|
53
|
-
|
54
|
-
def result_count(type=nil)
|
55
|
-
prep
|
56
|
-
count_results(self.values, type)
|
47
|
+
def results
|
48
|
+
tests.inject([]) {|results, test| results += test.results}
|
57
49
|
end
|
50
|
+
alias_method :ordered_results, :results
|
58
51
|
|
59
52
|
def count(thing)
|
60
53
|
case thing
|
@@ -77,6 +70,20 @@ module Assert
|
|
77
70
|
end
|
78
71
|
end
|
79
72
|
|
73
|
+
def test_count
|
74
|
+
self.tests.size
|
75
|
+
end
|
76
|
+
|
77
|
+
def result_count(type=nil)
|
78
|
+
if type
|
79
|
+
self.tests.inject(0) do |count, test|
|
80
|
+
count += test.result_count(type)
|
81
|
+
end
|
82
|
+
else
|
83
|
+
self.results.size
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
80
87
|
def setup(&block)
|
81
88
|
if block_given?
|
82
89
|
self.setups << block
|
@@ -119,30 +126,7 @@ module Assert
|
|
119
126
|
methods += local_methods
|
120
127
|
|
121
128
|
# uniq and remove any that don't start with 'test'
|
122
|
-
methods.uniq.delete_if {|method_name| method_name !~
|
123
|
-
end
|
124
|
-
|
125
|
-
private
|
126
|
-
|
127
|
-
def count_tests(test_sets)
|
128
|
-
test_sets.inject(0) {|count, tests| count += tests.size}
|
129
|
-
end
|
130
|
-
|
131
|
-
def count_results(test_sets, type)
|
132
|
-
self.values.flatten.inject(0){|count, test| count += test.result_count(type) }
|
133
|
-
end
|
134
|
-
|
135
|
-
def prep
|
136
|
-
if @prepared != true
|
137
|
-
# look for local public methods starting with 'test_'and add
|
138
|
-
self.each do |context_class, tests|
|
139
|
-
local_public_test_methods(context_class).each do |meth|
|
140
|
-
tests << Test.new(meth.to_s, context_class, meth)
|
141
|
-
end
|
142
|
-
tests.uniq
|
143
|
-
end
|
144
|
-
end
|
145
|
-
@prepared = true
|
129
|
+
methods.uniq.delete_if {|method_name| method_name !~ TEST_METHOD_REGEX }
|
146
130
|
end
|
147
131
|
|
148
132
|
end
|