assert 2.4.0 → 2.5.0
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/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
|