test-belt 0.2.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/Gemfile.lock +23 -0
- data/lib/test_belt/callbacks.rb +22 -0
- data/lib/test_belt/callbacks/case.rb +86 -0
- data/lib/test_belt/callbacks/suite.rb +106 -0
- data/lib/test_belt/callbacks/test.rb +58 -0
- data/lib/test_belt/context.rb +40 -0
- data/lib/test_belt/default_test.rb +18 -0
- data/lib/test_belt/helper.rb +24 -3
- data/lib/test_belt/matchers.rb +29 -0
- data/lib/test_belt/matchers/base.rb +21 -0
- data/lib/test_belt/matchers/have_accessors.rb +23 -0
- data/lib/test_belt/matchers/have_class_methods.rb +40 -0
- data/lib/test_belt/matchers/have_files.rb +38 -0
- data/lib/test_belt/matchers/have_instance_methods.rb +44 -0
- data/lib/test_belt/matchers/have_readers.rb +26 -0
- data/lib/test_belt/matchers/have_writers.rb +30 -0
- data/lib/test_belt/should.rb +76 -0
- data/lib/test_belt/skip.rb +41 -0
- data/lib/test_belt/subject.rb +47 -0
- data/lib/test_belt/version.rb +1 -1
- data/test/callbacks_test.rb +172 -0
- data/test/fixtures/{shoulda_macros/thing.rb → thing.rb} +0 -0
- data/test/helpers_test.rb +175 -0
- data/test/matchers_test.rb +135 -0
- data/test/rake_tasks_test.rb +8 -17
- metadata +33 -31
- data/lib/test_belt/shoulda_macros.rb +0 -9
- data/lib/test_belt/shoulda_macros/classes.rb +0 -105
- data/lib/test_belt/shoulda_macros/context.rb +0 -25
- data/lib/test_belt/shoulda_macros/files.rb +0 -49
- data/lib/test_belt/test_unit.rb +0 -8
- data/lib/test_belt/test_unit/context.rb +0 -71
- data/lib/test_belt/test_unit/runner.rb +0 -48
- data/lib/test_belt/test_unit/test_case.rb +0 -26
- data/test/shoulda_macros/classes_test.rb +0 -58
- data/test/shoulda_macros/context_test.rb +0 -28
- data/test/shoulda_macros/files_test.rb +0 -36
- data/test/test_unit/context_test.rb +0 -65
- data/test/test_unit/runner_test.rb +0 -31
- data/test/test_unit/test_case_test.rb +0 -30
data/.gitignore
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
test-belt (1.0.0)
|
5
|
+
kelredd-useful (~> 0.4.0)
|
6
|
+
leftright (~> 0.9.0)
|
7
|
+
shoulda (~> 2.11)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
json (1.5.1)
|
13
|
+
kelredd-useful (0.4.1)
|
14
|
+
json
|
15
|
+
leftright (0.9.1)
|
16
|
+
shoulda (2.11.3)
|
17
|
+
|
18
|
+
PLATFORMS
|
19
|
+
ruby
|
20
|
+
|
21
|
+
DEPENDENCIES
|
22
|
+
bundler (~> 1.0)
|
23
|
+
test-belt!
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test_belt/callbacks/test'
|
2
|
+
require 'test_belt/callbacks/case'
|
3
|
+
require 'test_belt/callbacks/suite'
|
4
|
+
|
5
|
+
module TestBelt::Callbacks
|
6
|
+
|
7
|
+
# Test Belt adds callbacks for test cases, test case classes, and overall
|
8
|
+
# test suites. Use these callbacks to help setup/teardown your tests. All
|
9
|
+
# callbacks inherit to subclasses and are run in inheritance order. So, a
|
10
|
+
# superclass's callbacks run before and subclass callbacks. Test
|
11
|
+
# callbacks are run in the scope of the test case. Other callbacks are run
|
12
|
+
# outside the test case scope.
|
13
|
+
|
14
|
+
def self.included(receiving_test_class)
|
15
|
+
if receiving_test_class.ancestors.include?(::Test::Unit::TestCase)
|
16
|
+
receiving_test_class.send(:include, Test)
|
17
|
+
receiving_test_class.send(:include, Case)
|
18
|
+
receiving_test_class.send(:include, Suite)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module TestBelt::Callbacks
|
2
|
+
module Case
|
3
|
+
|
4
|
+
# Like their before/after brothers above, the _once callbacks run
|
5
|
+
# before/after tests respectively. The difference is that they only run
|
6
|
+
# once for the entire case. The before/setup callback will run before the
|
7
|
+
# first test for the class while the after/teardown callback will run after
|
8
|
+
# the last test for the class.
|
9
|
+
|
10
|
+
# Usage:
|
11
|
+
# class SomeTest < Test::Unit::TestCase
|
12
|
+
# include TestBelt::Callbacks::Case
|
13
|
+
#
|
14
|
+
# before_once {
|
15
|
+
# # anything here runs before the first test for this class
|
16
|
+
# }
|
17
|
+
# after_once {
|
18
|
+
# # anything here runs after the last test for this class
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# should 'do stuff' do
|
22
|
+
# assert true
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
|
26
|
+
|
27
|
+
def self.included(receiver)
|
28
|
+
receiver.send(:extend, ClassMethods)
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def setup_once(&block)
|
33
|
+
raise ArgumentError, "please provide a setup block" unless block_given?
|
34
|
+
@_testbelt_once_setups ||= []
|
35
|
+
@_testbelt_once_setups << block
|
36
|
+
end
|
37
|
+
alias_method :before_once, :setup_once
|
38
|
+
|
39
|
+
def _testbelt_once_setups
|
40
|
+
((begin; superclass._testbelt_once_setups; rescue NoMethodError; []; end) || []) +
|
41
|
+
(@_testbelt_once_setups || [])
|
42
|
+
end
|
43
|
+
|
44
|
+
def teardown_once(&block)
|
45
|
+
raise ArgumentError, "please provide a teardown block" unless block_given?
|
46
|
+
@_testbelt_once_teardowns ||= []
|
47
|
+
@_testbelt_once_teardowns << block
|
48
|
+
end
|
49
|
+
alias_method :after_once, :teardown_once
|
50
|
+
|
51
|
+
def _testbelt_once_teardowns
|
52
|
+
((begin; superclass._testbelt_once_teardowns; rescue NoMethodError; []; end) || []) +
|
53
|
+
(@_testbelt_once_teardowns || [])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module Test::Unit
|
61
|
+
class TestSuite
|
62
|
+
# override the TestSuite with TestCase callbacks
|
63
|
+
alias_method :run_without_testbelt_callbacks, :run
|
64
|
+
|
65
|
+
def run(*args, &block) # :nodoc:
|
66
|
+
if( !tests.empty? &&
|
67
|
+
(testclass = tests.first).kind_of?(::Test::Unit::TestCase) &&
|
68
|
+
testclass.class.ancestors.include?(::TestBelt::Callbacks::Case)
|
69
|
+
)
|
70
|
+
tests.first.class._testbelt_once_setups.each do |callback|
|
71
|
+
callback.call
|
72
|
+
end
|
73
|
+
end
|
74
|
+
run_without_testbelt_callbacks *args, &block
|
75
|
+
if( !tests.empty? &&
|
76
|
+
(testclass = tests.first).kind_of?(::Test::Unit::TestCase) &&
|
77
|
+
testclass.class.ancestors.include?(::TestBelt::Callbacks::Case)
|
78
|
+
)
|
79
|
+
tests.first.class._testbelt_once_teardowns.reverse.each do |callback|
|
80
|
+
callback.call
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module TestBelt::Callbacks
|
2
|
+
module Suite
|
3
|
+
|
4
|
+
# Again, similar to the before/after callbacks above, the started/finished
|
5
|
+
# callbacks run before/after tests respectively. The difference is that
|
6
|
+
# these callbacks run only once for the entire suite of tests (across all
|
7
|
+
# test cases). The suite_started/on_suite_started callbacks run before the
|
8
|
+
# first test run in the suite of tests. The suite_finished/on_suite_finished
|
9
|
+
# callbacks run after the last test run in the suite of tests.
|
10
|
+
|
11
|
+
# Usage:
|
12
|
+
# class SomeTest < Test::Unit::TestCase
|
13
|
+
# include TestBelt::Callbacks::Suite
|
14
|
+
#
|
15
|
+
# suite_started {
|
16
|
+
# # anything here runs before the first test for the suite of tests
|
17
|
+
# }
|
18
|
+
# suite_finished {
|
19
|
+
# # anything here runs after the last test for the suite of tests
|
20
|
+
# }
|
21
|
+
#
|
22
|
+
# should 'do stuff' do
|
23
|
+
# assert true
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
|
27
|
+
|
28
|
+
def self.included(receiver)
|
29
|
+
if !::Test::Unit::TestCase.respond_to?(:suite_started)
|
30
|
+
::Test::Unit::TestCase.send(:extend, ClassMethods)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
def suite_started(&block)
|
36
|
+
raise ArgumentError, "please provide a started block" unless block_given?
|
37
|
+
::Test::Unit::TestCase._testbelt_started_callbacks ||= []
|
38
|
+
::Test::Unit::TestCase._testbelt_started_callbacks << block
|
39
|
+
end
|
40
|
+
alias_method :on_suite_started, :suite_started
|
41
|
+
|
42
|
+
def _testbelt_started_callbacks
|
43
|
+
@_testbelt_started_callbacks ||= []
|
44
|
+
end
|
45
|
+
|
46
|
+
def suite_finished(&block)
|
47
|
+
raise ArgumentError, "please provide a finished block" unless block_given?
|
48
|
+
::Test::Unit::TestCase._testbelt_finished_callbacks ||= []
|
49
|
+
::Test::Unit::TestCase._testbelt_finished_callbacks << block
|
50
|
+
end
|
51
|
+
alias_method :on_suite_finished, :suite_finished
|
52
|
+
|
53
|
+
def _testbelt_finished_callbacks
|
54
|
+
@_testbelt_finished_callbacks ||= []
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
require 'test/unit/ui/console/testrunner'
|
62
|
+
|
63
|
+
module TestBelt::Callbacks
|
64
|
+
|
65
|
+
if defined? ::LeftRight::Runner
|
66
|
+
class Runner < ::LeftRight::Runner; end
|
67
|
+
else
|
68
|
+
class Runner < ::Test::Unit::UI::Console::TestRunner; end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Runner
|
72
|
+
def started(*args)
|
73
|
+
super
|
74
|
+
if ::Test::Unit::TestCase.respond_to?(:suite_started)
|
75
|
+
::Test::Unit::TestCase._testbelt_started_callbacks.each do |callback|
|
76
|
+
callback.call
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def finished(*args)
|
82
|
+
if ::Test::Unit::TestCase.respond_to?(:suite_finished)
|
83
|
+
::Test::Unit::TestCase._testbelt_finished_callbacks.reverse.each do |callback|
|
84
|
+
callback.call
|
85
|
+
end
|
86
|
+
end
|
87
|
+
super
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
module Test::Unit
|
94
|
+
|
95
|
+
# override the AutoRunner's runner to use TestBelt's
|
96
|
+
# with callback for suite started/finished
|
97
|
+
class AutoRunner
|
98
|
+
alias_method :initialize_without_testbelt_runner, :initialize
|
99
|
+
|
100
|
+
def initialize(*args)
|
101
|
+
initialize_without_testbelt_runner *args
|
102
|
+
@runner = lambda { |r| ::TestBelt::Callbacks::Runner }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module TestBelt::Callbacks
|
2
|
+
module Test
|
3
|
+
|
4
|
+
# Test before/setup callbacks run before each test in the test case class.
|
5
|
+
# The after/teardown callbacks run after each test in the test case class.
|
6
|
+
# Each pair does identical logic - they are just an alias of each other so
|
7
|
+
# use what reads better to you.
|
8
|
+
|
9
|
+
# Usage:
|
10
|
+
# <pre>
|
11
|
+
# class SomeTest < Test::Unit::TestCase
|
12
|
+
# include TestBelt::Callbacks::Test
|
13
|
+
#
|
14
|
+
# before {
|
15
|
+
# # anything here runs before each test
|
16
|
+
# }
|
17
|
+
# after {
|
18
|
+
# # anything here runs after each test
|
19
|
+
# }
|
20
|
+
#
|
21
|
+
# should 'do stuff' do
|
22
|
+
# assert true
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# </pre>
|
26
|
+
|
27
|
+
def self.included(receiver)
|
28
|
+
receiver.send(:extend, ClassMethods)
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def setup(&block)
|
33
|
+
raise ArgumentError, "please provide a setup block" unless block_given?
|
34
|
+
@_testbelt_setups ||= []
|
35
|
+
@_testbelt_setups << block
|
36
|
+
end
|
37
|
+
alias_method :before, :setup
|
38
|
+
|
39
|
+
def _testbelt_setups
|
40
|
+
((begin; superclass._testbelt_setups; rescue NoMethodError; []; end) || []) +
|
41
|
+
(@_testbelt_setups || [])
|
42
|
+
end
|
43
|
+
|
44
|
+
def teardown(&block)
|
45
|
+
raise ArgumentError, "please provide a teardown block" unless block_given?
|
46
|
+
@_testbelt_teardowns ||= []
|
47
|
+
@_testbelt_teardowns << block
|
48
|
+
end
|
49
|
+
alias_method :after, :teardown
|
50
|
+
|
51
|
+
def _testbelt_teardowns
|
52
|
+
((begin; superclass._testbelt_teardowns; rescue NoMethodError; []; end) || []) +
|
53
|
+
(@_testbelt_teardowns || [])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module TestBelt
|
2
|
+
module Context
|
3
|
+
|
4
|
+
# This provides a 'context' method on a TestCase. Use this method
|
5
|
+
# to describe the context the TestCase is running in. This may be
|
6
|
+
# a description of the subject or whatever you want. The context
|
7
|
+
# value will be added to the test name of any tests defined using
|
8
|
+
# the 'should' method provided by should.rb. Context descriptions
|
9
|
+
# are nested as TestCases are sub-classed.
|
10
|
+
|
11
|
+
# Usage:
|
12
|
+
# class SomeTest < Test::Unit::TestCase
|
13
|
+
# include TestBelt::Context
|
14
|
+
# end
|
15
|
+
|
16
|
+
def self.included(receiver)
|
17
|
+
receiver.send(:extend, ClassMethods)
|
18
|
+
receiver.send(:include, InstanceMethods)
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def context(desc)
|
23
|
+
raise ArgumentError, "no context description provided" if desc.nil?
|
24
|
+
@_testbelt_contexts = [desc]
|
25
|
+
end
|
26
|
+
|
27
|
+
def _testbelt_contexts
|
28
|
+
((begin; superclass._testbelt_contexts; rescue NoMethodError; []; end) || []) +
|
29
|
+
(@_testbelt_contexts || [])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module InstanceMethods
|
34
|
+
def context
|
35
|
+
self.class._testbelt_contexts.join(' ')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module TestBelt
|
2
|
+
module DefaultTest
|
3
|
+
|
4
|
+
# This overrides the TestCase default_test behavior. When running
|
5
|
+
# a TestCase, the 'default_test' method is called if no 'test_*'
|
6
|
+
# methods are defined. The standard method always flunks saying
|
7
|
+
# 'no tests defined' or whatever. This overrides the standard
|
8
|
+
# method so it won't flunk and you can inherit TestCases freely.
|
9
|
+
|
10
|
+
# Usage:
|
11
|
+
# class SomeTest < Test::Unit::TestCase
|
12
|
+
# include TestBelt::DefaultTest
|
13
|
+
# end
|
14
|
+
|
15
|
+
def default_test; end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/test_belt/helper.rb
CHANGED
@@ -1,6 +1,27 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'test/unit'
|
3
3
|
require 'leftright'
|
4
|
-
|
5
|
-
require 'test_belt/
|
6
|
-
require 'test_belt/
|
4
|
+
|
5
|
+
require 'test_belt/default_test'
|
6
|
+
require 'test_belt/should'
|
7
|
+
require 'test_belt/context'
|
8
|
+
require 'test_belt/subject'
|
9
|
+
require 'test_belt/skip'
|
10
|
+
require 'test_belt/callbacks'
|
11
|
+
require 'test_belt/matchers'
|
12
|
+
|
13
|
+
module TestBelt
|
14
|
+
|
15
|
+
def self.included(receiving_test_class)
|
16
|
+
if receiving_test_class.ancestors.include?(::Test::Unit::TestCase)
|
17
|
+
receiving_test_class.send(:include, DefaultTest)
|
18
|
+
receiving_test_class.send(:extend, Should)
|
19
|
+
receiving_test_class.send(:include, Context)
|
20
|
+
receiving_test_class.send(:include, Subject)
|
21
|
+
receiving_test_class.send(:include, Skip)
|
22
|
+
receiving_test_class.send(:include, Callbacks)
|
23
|
+
receiving_test_class.send(:include, Matchers)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test_belt/matchers/base'
|
2
|
+
require 'test_belt/matchers/have_instance_methods'
|
3
|
+
require 'test_belt/matchers/have_class_methods'
|
4
|
+
require 'test_belt/matchers/have_readers'
|
5
|
+
require 'test_belt/matchers/have_writers'
|
6
|
+
require 'test_belt/matchers/have_accessors'
|
7
|
+
require 'test_belt/matchers/have_files'
|
8
|
+
|
9
|
+
module TestBelt::Matchers
|
10
|
+
|
11
|
+
# Test Belt provides matchers to test common scenarios. Use these matchers
|
12
|
+
# in combination with the 'should' method to run common test cases.
|
13
|
+
|
14
|
+
def self.included(receiving_test_class)
|
15
|
+
if receiving_test_class.ancestors.include?(::Test::Unit::TestCase)
|
16
|
+
receiving_test_class.send(:include, HaveInstanceMethods)
|
17
|
+
receiving_test_class.send(:include, HaveClassMethods)
|
18
|
+
receiving_test_class.send(:include, HaveReaders)
|
19
|
+
receiving_test_class.send(:include, HaveWriters)
|
20
|
+
receiving_test_class.send(:include, HaveAccessors)
|
21
|
+
receiving_test_class.send(:include, HaveFiles)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def assert_matcher(matcher)
|
26
|
+
assert_block(matcher.fail_message) { matcher.matches?(subject) }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TestBelt::Matchers
|
2
|
+
|
3
|
+
# Test Belt provides matchers to test common scenarios. Use these matchers
|
4
|
+
# in combination with the 'should' method to run common test cases. All
|
5
|
+
# matchers should subclass this base class.
|
6
|
+
|
7
|
+
class Base
|
8
|
+
def desc
|
9
|
+
raise NotImplementedError, "no description provided for the matcher"
|
10
|
+
end
|
11
|
+
|
12
|
+
def matches?(*args)
|
13
|
+
raise NotImplementedError, "no matches? test logic provided for the matcher"
|
14
|
+
end
|
15
|
+
|
16
|
+
def fail_message
|
17
|
+
raise NotImplementedError, "no fail message provided for the matcher"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|