spec-unit 0.1.0 → 1.0.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/lib/spec-unit/assert_helper.rb +66 -0
- data/lib/spec-unit/context_helper.rb +68 -0
- data/lib/spec-unit/should_helper.rb +181 -0
- data/lib/spec-unit.rb +3 -61
- data/test/helper.rb +55 -0
- data/test/test_assert_helper.rb +147 -0
- data/test/test_context_helper.rb +284 -0
- data/test/test_should_helper.rb +575 -0
- metadata +13 -4
- data/test/test_spec_unit.rb +0 -283
@@ -0,0 +1,66 @@
|
|
1
|
+
module SpecUnit
|
2
|
+
module AssertHelper
|
3
|
+
def self.assert_helper(base)
|
4
|
+
base.module_eval do
|
5
|
+
class << self
|
6
|
+
for meth in methods
|
7
|
+
undef_method(meth) if meth.to_s =~ /^assert_/ || meth.to_s =~ /^assert$/
|
8
|
+
end
|
9
|
+
|
10
|
+
alias_method :spec_unit_method_missing, :method_missing
|
11
|
+
def method_missing(sym, *args, &block)
|
12
|
+
if sym.to_s =~ /^assert_/
|
13
|
+
self.send(:define_method, :"test_#{args[0]}") do
|
14
|
+
if block
|
15
|
+
send(sym, *(instance_eval(&block)))
|
16
|
+
else
|
17
|
+
send(sym)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
spec_unit_method_missing sym, *args, &block
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
assert_helper(base)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module SpecUnit
|
35
|
+
module ContextHelper
|
36
|
+
def self.assert_helper(base)
|
37
|
+
base.module_eval do
|
38
|
+
class << self
|
39
|
+
for meth in methods
|
40
|
+
undef_method(meth) if meth.to_s =~ /^assert_/ || meth.to_s =~ /^assert$/
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :spec_unit_method_missing, :method_missing
|
44
|
+
def method_missing(sym, *args, &block)
|
45
|
+
if sym.to_s =~ /^assert_/
|
46
|
+
self.send(:define_method, :"test_#{args[0]}") do
|
47
|
+
if block
|
48
|
+
send(sym, *(instance_eval(&block)))
|
49
|
+
else
|
50
|
+
send(sym)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
spec_unit_method_missing sym, *args, &block
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Test::Unit::TestCase
|
64
|
+
include SpecUnit::AssertHelper
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module SpecUnit
|
2
|
+
module ContextHelper
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
assert_helper(base) if self.respond_to?(:assert_helper)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def context(name, &block)
|
10
|
+
self.send :include, new_context(name, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def new_context(name, &block)
|
14
|
+
context_module = new_context_module
|
15
|
+
|
16
|
+
context_module.module_eval(&block)
|
17
|
+
context_module.convert_specifications_to_tests(name.gsub(' ', '_'))
|
18
|
+
context_module
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_context_module
|
22
|
+
Module.new do
|
23
|
+
include ContextHelper
|
24
|
+
|
25
|
+
def self.convert_specifications_to_tests(name)
|
26
|
+
teardown, setup = unbound_teardown, unbound_setup
|
27
|
+
specifications = self.instance_methods.select {|m| m.to_s =~ /^specify_/ || m.to_s =~ /^test_/}
|
28
|
+
|
29
|
+
specifications.each do |spec|
|
30
|
+
spec_method = unbound_method(spec)
|
31
|
+
spec_name = spec.to_s.split(/^\w+?_/)[1]
|
32
|
+
|
33
|
+
define_method("test_#{name}_#{spec_name}".to_sym) do
|
34
|
+
setup.bind(self).call if setup
|
35
|
+
spec_method.bind(self).call
|
36
|
+
teardown.bind(self).call if teardown
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.unbound_setup
|
42
|
+
unbound_method(:setup)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.unbound_teardown
|
46
|
+
unbound_method(:teardown)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.unbound_method(meth)
|
50
|
+
if self.instance_methods.include? meth.to_s
|
51
|
+
unbound_meth = instance_method(meth)
|
52
|
+
remove_method(meth) rescue module_where_defined(meth).module_eval { remove_method meth }
|
53
|
+
end
|
54
|
+
unbound_meth
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.module_where_defined(meth)
|
58
|
+
included_modules.detect { |mod| mod.method_defined?(meth) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Test::Unit::TestCase
|
67
|
+
include SpecUnit::ContextHelper
|
68
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# Provide object.should testing functionality.
|
2
|
+
|
3
|
+
module SpecUnit
|
4
|
+
class ShouldHelper
|
5
|
+
include Test::Unit::Assertions
|
6
|
+
|
7
|
+
def initialize(object, sym, *args, &block)
|
8
|
+
$spec_unit_test.send(:add_assertion)
|
9
|
+
@object = object
|
10
|
+
@not = !!(sym.to_s =~ /^should_not/)
|
11
|
+
sym = sym.to_s.sub(/_not/, '').to_sym if @not
|
12
|
+
self.send(sym, *args, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def not_wrapper
|
16
|
+
@not ? !yield : yield
|
17
|
+
end
|
18
|
+
|
19
|
+
def should_with_predicate(meth, *args)
|
20
|
+
assert( not_wrapper { @object.send(meth.to_sym, *args) })
|
21
|
+
end
|
22
|
+
|
23
|
+
def should_with_method
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
%w( == < <= > >= ).each do |meth|
|
28
|
+
meth = meth.to_sym
|
29
|
+
self.send(:define_method, meth) do |another_object|
|
30
|
+
assert( not_wrapper { @object.send(meth, another_object) })
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def should_be(another_object = nil)
|
35
|
+
if another_object.nil?
|
36
|
+
should_with_method
|
37
|
+
else
|
38
|
+
if @not
|
39
|
+
assert_not_same another_object, @object
|
40
|
+
else
|
41
|
+
assert_same another_object, @object
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def should_be_a_kind_of(klass)
|
47
|
+
if @not
|
48
|
+
assert_block { !@object.kind_of?(klass) }
|
49
|
+
else
|
50
|
+
assert_kind_of klass, @object
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def should_be_an_instance_of(klass)
|
55
|
+
if @not
|
56
|
+
assert_block { !@object.instance_of?(klass) }
|
57
|
+
else
|
58
|
+
assert_instance_of klass, @object
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def should_be_close(another_object, delta)
|
63
|
+
if @not
|
64
|
+
assert_block { (another_object - delta > @object) || (another_object + delta < @object) }
|
65
|
+
else
|
66
|
+
assert_in_delta another_object, @object, delta
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def should_equal(another_object)
|
71
|
+
if @not
|
72
|
+
assert_not_equal another_object, @object
|
73
|
+
else
|
74
|
+
assert_equal another_object, @object
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def should_have(count)
|
79
|
+
if @not
|
80
|
+
assert_not_equal count, @object.size
|
81
|
+
else
|
82
|
+
assert_equal count, @object.size
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def should_have_at_least(count)
|
87
|
+
assert( not_wrapper { @object.size >= count } )
|
88
|
+
end
|
89
|
+
|
90
|
+
def should_have_at_most(count)
|
91
|
+
assert( not_wrapper { @object.size <= count } )
|
92
|
+
end
|
93
|
+
|
94
|
+
def should_include(another_object)
|
95
|
+
assert( not_wrapper { @object.include?(another_object) } )
|
96
|
+
end
|
97
|
+
|
98
|
+
def should_raise(error=Exception)
|
99
|
+
assert_block do
|
100
|
+
not_wrapper do
|
101
|
+
begin
|
102
|
+
@object.call && false
|
103
|
+
rescue error
|
104
|
+
true
|
105
|
+
rescue Exception
|
106
|
+
false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def should_respond_to(method)
|
113
|
+
if @not
|
114
|
+
assert_block { !@object.respond_to?(method) }
|
115
|
+
else
|
116
|
+
assert_respond_to @object, method
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def should_satisfy(&block)
|
121
|
+
assert( not_wrapper { block.call(@object) } )
|
122
|
+
end
|
123
|
+
|
124
|
+
def should_throw(symbol=nil)
|
125
|
+
if @not
|
126
|
+
assert_block do
|
127
|
+
begin
|
128
|
+
caught = true
|
129
|
+
if symbol
|
130
|
+
catch(symbol) do
|
131
|
+
@object.call
|
132
|
+
caught = false
|
133
|
+
end
|
134
|
+
else
|
135
|
+
@object.call
|
136
|
+
caught = false
|
137
|
+
end
|
138
|
+
rescue NameError, ThreadError => error
|
139
|
+
if UncaughtThrow[error.class] !~ error.message
|
140
|
+
raise error
|
141
|
+
end
|
142
|
+
caught = symbol.nil? ? true : false
|
143
|
+
end
|
144
|
+
!caught
|
145
|
+
end
|
146
|
+
else
|
147
|
+
assert_throws(symbol, &@object)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def method_missing(sym, *args)
|
152
|
+
if sym.to_s =~ /^should_be_/ || sym.to_s =~ /^should_have_/ || sym.to_s =~ /^should_/
|
153
|
+
should_with_predicate($', *args)
|
154
|
+
else
|
155
|
+
self
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Test::Unit::TestCase
|
162
|
+
alias_method :old_run, :run
|
163
|
+
def run(*args, &block)
|
164
|
+
$spec_unit_test = self
|
165
|
+
old_run(*args, &block)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
Object.module_eval do
|
170
|
+
include Test::Unit::Assertions
|
171
|
+
|
172
|
+
alias_method :old_method_missing, :method_missing
|
173
|
+
def method_missing(sym, *args, &block)
|
174
|
+
if sym.to_s =~ /should/
|
175
|
+
SpecUnit::ShouldHelper.new(self, sym, *args, &block)
|
176
|
+
else
|
177
|
+
old_method_missing(sym, *args, &block)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
data/lib/spec-unit.rb
CHANGED
@@ -1,61 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
end
|
5
|
-
|
6
|
-
module ClassMethods
|
7
|
-
def context(name, &block)
|
8
|
-
self.send :include, new_context(name, &block)
|
9
|
-
end
|
10
|
-
|
11
|
-
def new_context(name, &block)
|
12
|
-
context_module = new_context_module
|
13
|
-
|
14
|
-
context_module.module_eval(&block)
|
15
|
-
context_module.convert_specifications_to_tests(name.gsub(' ', '_'))
|
16
|
-
context_module
|
17
|
-
end
|
18
|
-
|
19
|
-
def new_context_module
|
20
|
-
Module.new do
|
21
|
-
include SpecUnit
|
22
|
-
|
23
|
-
def self.convert_specifications_to_tests(name)
|
24
|
-
teardown, setup = unbound_teardown, unbound_setup
|
25
|
-
specifications = self.instance_methods.select {|m| m.to_s =~ /^specify_/ || m.to_s =~ /^test_/}
|
26
|
-
|
27
|
-
specifications.each do |spec|
|
28
|
-
spec_method = unbound_method(spec)
|
29
|
-
spec_name = spec.to_s.split(/^\w+?_/)[1]
|
30
|
-
|
31
|
-
define_method("test_#{name}_#{spec_name}".to_sym) do
|
32
|
-
setup.bind(self).call if setup
|
33
|
-
spec_method.bind(self).call
|
34
|
-
teardown.bind(self).call if teardown
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.unbound_setup
|
40
|
-
unbound_method(:setup)
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.unbound_teardown
|
44
|
-
unbound_method(:teardown)
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.unbound_method(meth)
|
48
|
-
if self.instance_methods.include? meth.to_s
|
49
|
-
unbound_meth = instance_method(meth)
|
50
|
-
remove_method(meth) rescue module_where_defined(meth).module_eval { remove_method meth }
|
51
|
-
end
|
52
|
-
unbound_meth
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.module_where_defined(meth)
|
56
|
-
included_modules.detect { |mod| mod.method_defined?(meth) }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
1
|
+
require 'spec-unit/context_helper'
|
2
|
+
require 'spec-unit/should_helper'
|
3
|
+
require 'spec-unit/assert_helper'
|
data/test/helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class Test::Unit::TestCase
|
6
|
+
def assert_has_one_assertion(test)
|
7
|
+
assert_nothing_raised { @test_class.new(test.to_sym) }
|
8
|
+
assert_has_x_assertions(1, test)
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_has_x_assertions(number_of_assertions, test)
|
12
|
+
@result = Test::Unit::TestResult.new
|
13
|
+
@test_suite = @test_class.suite
|
14
|
+
@test_suite.run(@result) {|m, n|}
|
15
|
+
assert_equal number_of_assertions, @result.assertion_count
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_test_passes(test)
|
19
|
+
assert_test :passes, test
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert_test_passes_with_setup(test, &block)
|
23
|
+
define_setup(&block) if block
|
24
|
+
assert_test_passes test
|
25
|
+
end
|
26
|
+
|
27
|
+
def assert_test_fails(test)
|
28
|
+
assert_test :fails, test
|
29
|
+
end
|
30
|
+
|
31
|
+
def assert_test_fails_with_setup(test, &block)
|
32
|
+
define_setup(&block) if block
|
33
|
+
assert_test_fails test
|
34
|
+
end
|
35
|
+
|
36
|
+
def assert_test(result, test)
|
37
|
+
@result = Test::Unit::TestResult.new
|
38
|
+
assert_nothing_raised { @object = @test_class.new(test.to_sym) }
|
39
|
+
@object.run(@result) {|m,n|}
|
40
|
+
assert_not_equal 0, @result.assertion_count
|
41
|
+
case result
|
42
|
+
when :passes
|
43
|
+
assert @result.passed?
|
44
|
+
when :fails
|
45
|
+
assert_equal 1, @result.failure_count
|
46
|
+
else
|
47
|
+
raise "'#{result}' is not a valid test condition."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def define_setup &block
|
52
|
+
@test_class.send :define_method, :setup, block
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
$: << File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
require 'spec-unit/context_helper'
|
5
|
+
require 'spec-unit/should_helper'
|
6
|
+
require 'spec-unit/assert_helper'
|
7
|
+
|
8
|
+
class TestAssertHelper < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@test_class = Class.new(Test::Unit::TestCase)
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'assert_equal' do
|
14
|
+
def setup
|
15
|
+
@test_class.module_eval { assert_equal(:objects_are_equal) {[ @object, @another_object ]}}
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_is_wrapped
|
19
|
+
assert_has_one_assertion(:test_objects_are_equal)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_passes
|
23
|
+
assert_test_passes_with_setup(:test_objects_are_equal) { @object, @another_object = 'this', 'this' }
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_fails
|
27
|
+
assert_test_fails_with_setup(:test_objects_are_equal) { @object, @another_object = 'this', 'that' }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'assert_not_equal' do
|
32
|
+
def setup
|
33
|
+
@test_class.module_eval { assert_not_equal(:objects_are_not_equal) { next @object, @another_object }}
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_is_wrapped
|
37
|
+
assert_has_one_assertion(:test_objects_are_not_equal)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_passes
|
41
|
+
assert_test_passes_with_setup(:test_objects_are_not_equal) { @object, @another_object = 'this', 'that' }
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_fails
|
45
|
+
assert_test_fails_with_setup(:test_objects_are_not_equal) { @object, @another_object = 'this', 'this' }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'assert_equal in a context' do
|
50
|
+
def setup
|
51
|
+
@test_class.module_eval do
|
52
|
+
context 'in a context' do
|
53
|
+
assert_equal(:objects_are_equal) { next @object, @another_object }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_is_wrapped
|
59
|
+
assert_has_one_assertion(:test_in_a_context_objects_are_equal)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_passes
|
63
|
+
assert_test_passes_with_setup(:test_in_a_context_objects_are_equal) { @object, @another_object = 'this', 'this' }
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_fails
|
67
|
+
assert_test_fails_with_setup(:test_in_a_context_objects_are_equal) { @object, @another_object = 'this', 'that' }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'a custom assertion' do
|
72
|
+
def setup
|
73
|
+
@test_class.module_eval do
|
74
|
+
def assert_my_own_things(object); object.should_equal 1; end
|
75
|
+
assert_my_own_things(:custom_assertion) { next @object }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_is_wrapped
|
80
|
+
assert_has_one_assertion(:test_custom_assertion)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_passes
|
84
|
+
assert_test_passes_with_setup(:test_custom_assertion) { @object = 1 }
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_fails
|
88
|
+
assert_test_fails_with_setup(:test_custom_assertion) { @object = 2 }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'a custom assertion that takes no parameters' do
|
93
|
+
def setup
|
94
|
+
@test_class.module_eval do
|
95
|
+
def assert_custom; @object.should_equal 1; end
|
96
|
+
assert_custom(:custom)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_is_wrapped
|
101
|
+
assert_has_one_assertion(:test_custom)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_passes
|
105
|
+
assert_test_passes_with_setup(:test_custom) { @object = 1 }
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_fails
|
109
|
+
assert_test_fails_with_setup(:test_custom) { @object = 2 }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'a custom assertion in a context that takes no parameters' do
|
114
|
+
def setup
|
115
|
+
@test_class.module_eval do
|
116
|
+
def assert_custom; @object.should_equal 1; end
|
117
|
+
context('a context') { assert_custom(:custom) }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_is_wrapped
|
122
|
+
assert_has_one_assertion(:test_a_context_custom)
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_passes
|
126
|
+
assert_test_passes_with_setup(:test_a_context_custom) { @object = 1 }
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_fails
|
130
|
+
assert_test_fails_with_setup(:test_a_context_custom) { @object = 2 }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'some_other_method' do
|
135
|
+
def test_throws_name_error
|
136
|
+
assert_raise(NameError) { @test_class.module_eval { some_other_method } }
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_throws_name_error_in_context
|
140
|
+
assert_raise(NameError) do
|
141
|
+
@test_class.module_eval do
|
142
|
+
context('a context') { some_other_method }
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|