spec-unit 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|