assert 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -8
- data/lib/assert.rb +9 -62
- data/lib/assert/assert_runner.rb +15 -30
- data/lib/assert/assertions.rb +105 -41
- data/lib/assert/cli.rb +1 -1
- data/lib/assert/config.rb +56 -0
- data/lib/assert/context.rb +44 -150
- data/lib/assert/context/setup_dsl.rb +70 -0
- data/lib/assert/context/subject_dsl.rb +39 -0
- data/lib/assert/context/suite_dsl.rb +20 -0
- data/lib/assert/context/test_dsl.rb +51 -0
- data/lib/assert/runner.rb +8 -2
- data/lib/assert/suite.rb +33 -12
- data/lib/assert/test.rb +11 -8
- data/lib/assert/utils.rb +23 -11
- data/lib/assert/version.rb +1 -1
- data/lib/assert/view.rb +9 -7
- data/lib/assert/view/base.rb +26 -4
- data/lib/assert/view/default_view.rb +1 -1
- data/lib/assert/view/helpers/ansi_styles.rb +1 -1
- data/lib/assert/view/helpers/common.rb +16 -6
- data/test/helper.rb +1 -94
- data/test/support/factory.rb +70 -0
- data/test/system/running_tests.rb +55 -28
- data/test/unit/assert_tests.rb +6 -33
- data/test/unit/assertions/assert_block_tests.rb +3 -3
- data/test/unit/assertions/assert_empty_tests.rb +6 -4
- data/test/unit/assertions/assert_equal_tests.rb +19 -22
- data/test/unit/assertions/assert_file_exists_tests.rb +6 -4
- data/test/unit/assertions/assert_includes_tests.rb +8 -4
- data/test/unit/assertions/assert_instance_of_tests.rb +8 -6
- data/test/unit/assertions/assert_kind_of_tests.rb +8 -5
- data/test/unit/assertions/assert_match_tests.rb +8 -4
- data/test/unit/assertions/assert_nil_tests.rb +6 -4
- data/test/unit/assertions/assert_raises_tests.rb +2 -2
- data/test/unit/assertions/assert_respond_to_tests.rb +7 -5
- data/test/unit/assertions/assert_same_tests.rb +75 -6
- data/test/unit/assertions/assert_true_false_tests.rb +116 -0
- data/test/unit/assertions_tests.rb +7 -5
- data/test/unit/config_tests.rb +58 -0
- data/test/unit/context/{setup_teardown_singleton_tests.rb → setup_dsl_tests.rb} +17 -19
- data/test/unit/context/subject_dsl_tests.rb +78 -0
- data/test/unit/context/suite_dsl_tests.rb +47 -0
- data/test/unit/context/{test_should_singleton_tests.rb → test_dsl_tests.rb} +33 -34
- data/test/unit/context_tests.rb +19 -15
- data/test/unit/runner_tests.rb +9 -3
- data/test/unit/suite_tests.rb +20 -23
- data/test/unit/test_tests.rb +22 -14
- data/test/unit/utils_tests.rb +15 -21
- data/test/unit/view_tests.rb +12 -5
- metadata +23 -10
- data/test/unit/context/basic_singleton_tests.rb +0 -86
data/lib/assert/cli.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Assert
|
2
|
+
|
3
|
+
class Config
|
4
|
+
|
5
|
+
def self.settings(*items)
|
6
|
+
items.each do |item|
|
7
|
+
define_method(item) do |*args|
|
8
|
+
if !(value = args.size > 1 ? args : args.first).nil?
|
9
|
+
instance_variable_set("@#{item}", value)
|
10
|
+
end
|
11
|
+
instance_variable_get("@#{item}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
settings :view, :suite, :runner
|
17
|
+
settings :test_dir, :test_helper, :test_file_suffixes, :runner_seed
|
18
|
+
settings :changed_proc, :pp_proc, :use_diff_proc, :run_diff_proc
|
19
|
+
settings :capture_output, :halt_on_fail, :changed_only, :pp_objects, :debug
|
20
|
+
|
21
|
+
def initialize(settings = nil)
|
22
|
+
@suite = Assert::Suite.new(self)
|
23
|
+
@view = Assert::View::DefaultView.new($stdout, self, @suite)
|
24
|
+
@runner = Assert::Runner.new(self)
|
25
|
+
|
26
|
+
@test_dir = "test"
|
27
|
+
@test_helper = "helper.rb"
|
28
|
+
@test_file_suffixes = ['_tests.rb', '_test.rb']
|
29
|
+
@runner_seed = begin; srand; srand % 0xFFFF; end.to_i
|
30
|
+
|
31
|
+
@changed_proc = Assert::U.git_changed_proc
|
32
|
+
@pp_proc = Assert::U.stdlib_pp_proc
|
33
|
+
@use_diff_proc = Assert::U.default_use_diff_proc
|
34
|
+
@run_diff_proc = Assert::U.syscmd_diff_proc
|
35
|
+
|
36
|
+
# mode flags
|
37
|
+
@capture_output = false
|
38
|
+
@halt_on_fail = true
|
39
|
+
@changed_only = false
|
40
|
+
@pp_objects = false
|
41
|
+
@debug = false
|
42
|
+
|
43
|
+
self.apply(settings || {})
|
44
|
+
end
|
45
|
+
|
46
|
+
def apply(settings)
|
47
|
+
settings.keys.each do |name|
|
48
|
+
if !settings[name].nil? && self.respond_to?(name.to_s)
|
49
|
+
self.send(name.to_s, settings[name])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/lib/assert/context.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
|
-
require 'assert/utils'
|
2
|
-
require 'assert/suite'
|
3
1
|
require 'assert/assertions'
|
4
|
-
require 'assert/
|
2
|
+
require 'assert/context/setup_dsl'
|
3
|
+
require 'assert/context/subject_dsl'
|
4
|
+
require 'assert/context/suite_dsl'
|
5
|
+
require 'assert/context/test_dsl'
|
5
6
|
require 'assert/macros/methods'
|
7
|
+
require 'assert/result'
|
8
|
+
require 'assert/suite'
|
9
|
+
require 'assert/utils'
|
6
10
|
|
7
11
|
module Assert
|
12
|
+
|
8
13
|
class Context
|
14
|
+
# put all logic in DSL methods to keep context instances pure for running tests
|
15
|
+
extend SetupDSL
|
16
|
+
extend SubjectDSL
|
17
|
+
extend SuiteDSL
|
18
|
+
extend TestDSL
|
9
19
|
include Assert::Assertions
|
10
20
|
include Assert::Macros::Methods
|
11
21
|
|
@@ -21,155 +31,21 @@ module Assert
|
|
21
31
|
if method_name.to_s =~ Suite::TEST_METHOD_REGEX
|
22
32
|
klass_method_name = "#{self}##{method_name}"
|
23
33
|
|
24
|
-
if
|
34
|
+
if self.suite.test_methods.include?(klass_method_name)
|
25
35
|
puts "WARNING: redefining '#{klass_method_name}'"
|
26
36
|
puts " from: #{called_from}"
|
27
37
|
else
|
28
|
-
|
38
|
+
self.suite.test_methods << klass_method_name
|
29
39
|
end
|
30
40
|
|
31
41
|
ci = Suite::ContextInfo.new(self, nil, caller.first)
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
# put all logic here to keep context instances pure for running tests
|
37
|
-
class << self
|
38
|
-
|
39
|
-
def setup_once(&block)
|
40
|
-
Assert.suite.setup(&block)
|
41
|
-
end
|
42
|
-
alias_method :before_once, :setup_once
|
43
|
-
alias_method :startup, :setup_once
|
44
|
-
|
45
|
-
def teardown_once(&block)
|
46
|
-
Assert.suite.teardown(&block)
|
47
|
-
end
|
48
|
-
alias_method :after_once, :teardown_once
|
49
|
-
alias_method :shutdown, :teardown_once
|
50
|
-
|
51
|
-
# Add a setup block to run before each test or run the list of teardown blocks in given scope
|
52
|
-
def setup(scope_or_method_name = nil, &block)
|
53
|
-
is_method = scope_or_method_name.kind_of?(String) || scope_or_method_name.kind_of?(Symbol)
|
54
|
-
if block_given? || is_method
|
55
|
-
# arg is a block or method that needs to be stored as a setup
|
56
|
-
self.setups << (block || scope_or_method_name)
|
57
|
-
elsif !is_method
|
58
|
-
# arg is an instance of this class (the scope for a test),
|
59
|
-
# run the setups for this context in the scope
|
60
|
-
scope = scope_or_method_name
|
61
|
-
# setup parent...
|
62
|
-
self.superclass.setup(scope) if self.superclass.respond_to?(:setup)
|
63
|
-
# ... before child
|
64
|
-
self.setups.each do |setup|
|
65
|
-
setup.kind_of?(::Proc) ? scope.instance_eval(&setup) : scope.send(setup)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
alias_method :before, :setup
|
70
|
-
|
71
|
-
# Add a teardown block to run after each test or run the list of teardown blocks in given scope
|
72
|
-
def teardown(scope_or_method_name = nil, &block)
|
73
|
-
is_method = scope_or_method_name.kind_of?(String) || scope_or_method_name.kind_of?(Symbol)
|
74
|
-
if block_given? || is_method
|
75
|
-
# arg is a block or method that needs to be stored as a teardown
|
76
|
-
self.teardowns << (block || scope_or_method_name)
|
77
|
-
elsif !is_method
|
78
|
-
# arg is an instance of this class (the scope for a test),
|
79
|
-
# run the setups for this context in the scope
|
80
|
-
scope = scope_or_method_name
|
81
|
-
# teardown child...
|
82
|
-
self.teardowns.each do |teardown|
|
83
|
-
teardown.kind_of?(::Proc) ? scope.instance_eval(&teardown) : scope.send(teardown)
|
84
|
-
end
|
85
|
-
# ... before parent
|
86
|
-
self.superclass.teardown(scope) if self.superclass.respond_to?(:teardown)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
alias_method :after, :teardown
|
90
|
-
|
91
|
-
# Add a piece of description text or return the full description for the context
|
92
|
-
def description(text=nil)
|
93
|
-
if text
|
94
|
-
self.descriptions << text.to_s
|
95
|
-
else
|
96
|
-
parent = self.superclass.desc if self.superclass.respond_to?(:desc)
|
97
|
-
own = self.descriptions
|
98
|
-
[parent, *own].compact.reject do |p|
|
99
|
-
p.to_s.empty?
|
100
|
-
end.join(" ")
|
101
|
-
end
|
102
|
-
end
|
103
|
-
alias_method :desc, :description
|
104
|
-
alias_method :describe, :description
|
105
|
-
|
106
|
-
def subject(&block)
|
107
|
-
if block_given?
|
108
|
-
@subject = block
|
109
|
-
else
|
110
|
-
@subject || if superclass.respond_to?(:subject)
|
111
|
-
superclass.subject
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def test(desc_or_macro, called_from=nil, first_caller=nil, &block)
|
117
|
-
if desc_or_macro.kind_of?(Macro)
|
118
|
-
instance_eval(&desc_or_macro)
|
119
|
-
elsif block_given?
|
120
|
-
ci = Suite::ContextInfo.new(self, called_from, first_caller || caller.first)
|
121
|
-
test_name = desc_or_macro
|
122
|
-
|
123
|
-
# create a test from the given code block
|
124
|
-
Assert.suite.tests << Test.new(test_name, ci, &block)
|
125
|
-
else
|
126
|
-
test_eventually(desc_or_macro, called_from, first_caller || caller.first, &block)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_eventually(desc_or_macro, called_from=nil, first_caller=nil, &block)
|
131
|
-
ci = Suite::ContextInfo.new(self, called_from, first_caller || caller.first)
|
132
|
-
test_name = desc_or_macro.kind_of?(Macro) ? desc_or_macro.name : desc_or_macro
|
133
|
-
skip_block = block.nil? ? Proc.new { skip 'TODO' } : Proc.new { skip }
|
134
|
-
|
135
|
-
# create a test from a proc that just skips
|
136
|
-
Assert.suite.tests << Test.new(test_name, ci, &skip_block)
|
137
|
-
end
|
138
|
-
alias_method :test_skip, :test_eventually
|
139
|
-
|
140
|
-
def should(desc_or_macro, called_from=nil, first_caller=nil, &block)
|
141
|
-
if !desc_or_macro.kind_of?(Macro)
|
142
|
-
desc_or_macro = "should #{desc_or_macro}"
|
143
|
-
end
|
144
|
-
test(desc_or_macro, called_from, first_caller || caller.first, &block)
|
145
|
-
end
|
146
|
-
|
147
|
-
def should_eventually(desc_or_macro, called_from=nil, first_caller=nil, &block)
|
148
|
-
if !desc_or_macro.kind_of?(Macro)
|
149
|
-
desc_or_macro = "should #{desc_or_macro}"
|
150
|
-
end
|
151
|
-
test_eventually(desc_or_macro, called_from, first_caller || caller.first, &block)
|
152
|
-
end
|
153
|
-
alias_method :should_skip, :should_eventually
|
154
|
-
|
155
|
-
protected
|
156
|
-
|
157
|
-
def descriptions
|
158
|
-
@descriptions ||= []
|
42
|
+
test = Test.new(method_name.to_s, ci, self.suite.config, :code => method_name)
|
43
|
+
self.suite.tests << test
|
159
44
|
end
|
160
|
-
|
161
|
-
def setups
|
162
|
-
@setups ||= []
|
163
|
-
end
|
164
|
-
|
165
|
-
def teardowns
|
166
|
-
@teardowns ||= []
|
167
|
-
end
|
168
|
-
|
169
45
|
end
|
170
46
|
|
171
|
-
def initialize(running_test
|
172
|
-
@__running_test__ = running_test
|
47
|
+
def initialize(running_test, config)
|
48
|
+
@__running_test__, @__assert_config__ = running_test, config
|
173
49
|
end
|
174
50
|
|
175
51
|
# check if the assertion is a truthy value, if so create a new pass result, otherwise
|
@@ -179,7 +55,11 @@ module Assert
|
|
179
55
|
if assertion
|
180
56
|
pass
|
181
57
|
else
|
182
|
-
what = block_given?
|
58
|
+
what = if block_given?
|
59
|
+
yield
|
60
|
+
else
|
61
|
+
"Failed assert: assertion was `#{Assert::U.show(assertion, __assert_config__)}`."
|
62
|
+
end
|
183
63
|
fail(fail_message(desc, what))
|
184
64
|
end
|
185
65
|
end
|
@@ -187,7 +67,9 @@ module Assert
|
|
187
67
|
# the opposite of assert, check if the assertion is a false value, if so create a new pass
|
188
68
|
# result, otherwise create a new fail result with the desc and it's what failed msg
|
189
69
|
def assert_not(assertion, fail_desc = nil)
|
190
|
-
assert(!assertion, fail_desc)
|
70
|
+
assert(!assertion, fail_desc) do
|
71
|
+
"Failed assert_not: assertion was `#{Assert::U.show(assertion, __assert_config__)}`."
|
72
|
+
end
|
191
73
|
end
|
192
74
|
alias_method :refute, :assert_not
|
193
75
|
|
@@ -208,9 +90,9 @@ module Assert
|
|
208
90
|
end
|
209
91
|
|
210
92
|
# adds a Fail result to the end of the test's results
|
211
|
-
# break test execution if
|
93
|
+
# break test execution if assert is configured to halt on failures
|
212
94
|
def fail(message = nil)
|
213
|
-
if
|
95
|
+
if halt_on_fail?
|
214
96
|
raise Result::TestFailure, message || ''
|
215
97
|
else
|
216
98
|
capture_result do |test, backtrace|
|
@@ -258,16 +140,28 @@ module Assert
|
|
258
140
|
|
259
141
|
private
|
260
142
|
|
143
|
+
def halt_on_fail?
|
144
|
+
__assert_config__.halt_on_fail
|
145
|
+
end
|
146
|
+
|
261
147
|
def capture_result
|
262
148
|
if block_given?
|
263
|
-
result = yield
|
264
|
-
|
149
|
+
result = yield __running_test__, caller
|
150
|
+
__running_test__.results << result
|
265
151
|
result
|
266
152
|
end
|
267
153
|
end
|
268
154
|
|
269
155
|
def current_results
|
270
|
-
|
156
|
+
__running_test__.results
|
157
|
+
end
|
158
|
+
|
159
|
+
def __running_test__
|
160
|
+
@__running_test__
|
161
|
+
end
|
162
|
+
|
163
|
+
def __assert_config__
|
164
|
+
@__assert_config__
|
271
165
|
end
|
272
166
|
|
273
167
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Assert; end
|
2
|
+
class Assert::Context
|
3
|
+
|
4
|
+
module SetupDSL
|
5
|
+
|
6
|
+
def setup_once(&block)
|
7
|
+
self.suite.setup(&block)
|
8
|
+
end
|
9
|
+
alias_method :before_once, :setup_once
|
10
|
+
alias_method :startup, :setup_once
|
11
|
+
|
12
|
+
def teardown_once(&block)
|
13
|
+
self.suite.teardown(&block)
|
14
|
+
end
|
15
|
+
alias_method :after_once, :teardown_once
|
16
|
+
alias_method :shutdown, :teardown_once
|
17
|
+
|
18
|
+
# Add a setup block to run before each test or run the list of teardown blocks in given scope
|
19
|
+
def setup(scope_or_method_name = nil, &block)
|
20
|
+
is_method = scope_or_method_name.kind_of?(String) || scope_or_method_name.kind_of?(Symbol)
|
21
|
+
if block_given? || is_method
|
22
|
+
# arg is a block or method that needs to be stored as a setup
|
23
|
+
self.setups << (block || scope_or_method_name)
|
24
|
+
elsif !is_method
|
25
|
+
# arg is an instance of this class (the scope for a test),
|
26
|
+
# run the setups for this context in the scope
|
27
|
+
scope = scope_or_method_name
|
28
|
+
# setup parent...
|
29
|
+
self.superclass.setup(scope) if self.superclass.respond_to?(:setup)
|
30
|
+
# ... before child
|
31
|
+
self.setups.each do |setup|
|
32
|
+
setup.kind_of?(::Proc) ? scope.instance_eval(&setup) : scope.send(setup)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
alias_method :before, :setup
|
37
|
+
|
38
|
+
# Add a teardown block to run after each test or run the list of teardown blocks in given scope
|
39
|
+
def teardown(scope_or_method_name = nil, &block)
|
40
|
+
is_method = scope_or_method_name.kind_of?(String) || scope_or_method_name.kind_of?(Symbol)
|
41
|
+
if block_given? || is_method
|
42
|
+
# arg is a block or method that needs to be stored as a teardown
|
43
|
+
self.teardowns << (block || scope_or_method_name)
|
44
|
+
elsif !is_method
|
45
|
+
# arg is an instance of this class (the scope for a test),
|
46
|
+
# run the setups for this context in the scope
|
47
|
+
scope = scope_or_method_name
|
48
|
+
# teardown child...
|
49
|
+
self.teardowns.each do |teardown|
|
50
|
+
teardown.kind_of?(::Proc) ? scope.instance_eval(&teardown) : scope.send(teardown)
|
51
|
+
end
|
52
|
+
# ... before parent
|
53
|
+
self.superclass.teardown(scope) if self.superclass.respond_to?(:teardown)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
alias_method :after, :teardown
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def setups
|
61
|
+
@setups ||= []
|
62
|
+
end
|
63
|
+
|
64
|
+
def teardowns
|
65
|
+
@teardowns ||= []
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Assert; end
|
2
|
+
class Assert::Context
|
3
|
+
|
4
|
+
module SubjectDSL
|
5
|
+
|
6
|
+
# Add a piece of description text or return the full description for the context
|
7
|
+
def description(text = nil)
|
8
|
+
if text
|
9
|
+
self.descriptions << text.to_s
|
10
|
+
else
|
11
|
+
parent = self.superclass.desc if self.superclass.respond_to?(:desc)
|
12
|
+
own = self.descriptions
|
13
|
+
[parent, *own].compact.reject do |p|
|
14
|
+
p.to_s.empty?
|
15
|
+
end.join(" ")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
alias_method :desc, :description
|
19
|
+
alias_method :describe, :description
|
20
|
+
|
21
|
+
def subject(&block)
|
22
|
+
if block_given?
|
23
|
+
@subject = block
|
24
|
+
else
|
25
|
+
@subject || if superclass.respond_to?(:subject)
|
26
|
+
superclass.subject
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def descriptions
|
34
|
+
@descriptions ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Assert; end
|
2
|
+
class Assert::Context
|
3
|
+
|
4
|
+
module SuiteDSL
|
5
|
+
|
6
|
+
def suite(suite_obj = nil)
|
7
|
+
if suite_obj
|
8
|
+
@suite = suite_obj
|
9
|
+
else
|
10
|
+
@suite || if superclass.respond_to?(:suite)
|
11
|
+
superclass.suite
|
12
|
+
else
|
13
|
+
Assert.suite
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|