test-belt 0.2.1 → 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.
Files changed (41) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile.lock +23 -0
  3. data/lib/test_belt/callbacks.rb +22 -0
  4. data/lib/test_belt/callbacks/case.rb +86 -0
  5. data/lib/test_belt/callbacks/suite.rb +106 -0
  6. data/lib/test_belt/callbacks/test.rb +58 -0
  7. data/lib/test_belt/context.rb +40 -0
  8. data/lib/test_belt/default_test.rb +18 -0
  9. data/lib/test_belt/helper.rb +24 -3
  10. data/lib/test_belt/matchers.rb +29 -0
  11. data/lib/test_belt/matchers/base.rb +21 -0
  12. data/lib/test_belt/matchers/have_accessors.rb +23 -0
  13. data/lib/test_belt/matchers/have_class_methods.rb +40 -0
  14. data/lib/test_belt/matchers/have_files.rb +38 -0
  15. data/lib/test_belt/matchers/have_instance_methods.rb +44 -0
  16. data/lib/test_belt/matchers/have_readers.rb +26 -0
  17. data/lib/test_belt/matchers/have_writers.rb +30 -0
  18. data/lib/test_belt/should.rb +76 -0
  19. data/lib/test_belt/skip.rb +41 -0
  20. data/lib/test_belt/subject.rb +47 -0
  21. data/lib/test_belt/version.rb +1 -1
  22. data/test/callbacks_test.rb +172 -0
  23. data/test/fixtures/{shoulda_macros/thing.rb → thing.rb} +0 -0
  24. data/test/helpers_test.rb +175 -0
  25. data/test/matchers_test.rb +135 -0
  26. data/test/rake_tasks_test.rb +8 -17
  27. metadata +33 -31
  28. data/lib/test_belt/shoulda_macros.rb +0 -9
  29. data/lib/test_belt/shoulda_macros/classes.rb +0 -105
  30. data/lib/test_belt/shoulda_macros/context.rb +0 -25
  31. data/lib/test_belt/shoulda_macros/files.rb +0 -49
  32. data/lib/test_belt/test_unit.rb +0 -8
  33. data/lib/test_belt/test_unit/context.rb +0 -71
  34. data/lib/test_belt/test_unit/runner.rb +0 -48
  35. data/lib/test_belt/test_unit/test_case.rb +0 -26
  36. data/test/shoulda_macros/classes_test.rb +0 -58
  37. data/test/shoulda_macros/context_test.rb +0 -28
  38. data/test/shoulda_macros/files_test.rb +0 -36
  39. data/test/test_unit/context_test.rb +0 -65
  40. data/test/test_unit/runner_test.rb +0 -31
  41. data/test/test_unit/test_case_test.rb +0 -30
@@ -0,0 +1,23 @@
1
+ require 'test_belt/matchers/have_readers'
2
+ require 'test_belt/matchers/have_writers'
3
+
4
+ module TestBelt::Matchers
5
+ module HaveAccessors
6
+
7
+ def self.included(receiver)
8
+ receiver.send(:extend, ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ def have_accessors(*meths)
13
+ meths.collect do |meth|
14
+ [ ::TestBelt::Matchers::HaveReaders::Matcher.new(meth),
15
+ ::TestBelt::Matchers::HaveWriters::Matcher.new(meth)
16
+ ]
17
+ end.flatten
18
+ end
19
+ alias_method :have_accessor, :have_accessors
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module TestBelt::Matchers
2
+ module HaveClassMethods
3
+
4
+ def self.included(receiver)
5
+ receiver.send(:extend, ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def have_class_methods(*meths)
10
+ meths.collect do |meth|
11
+ Matcher.new(meth)
12
+ end
13
+ end
14
+ alias_method :have_class_method, :have_class_methods
15
+ end
16
+
17
+ class Matcher < ::TestBelt::Matchers::Base
18
+ def initialize(method)
19
+ unless method.kind_of?(::String) || method.kind_of?(::Symbol)
20
+ raise ArgumentError, "please specify the method name using a string or symbol"
21
+ end
22
+ @method = method
23
+ end
24
+
25
+ def desc
26
+ "respond to class method ##{@method}"
27
+ end
28
+
29
+ def matches?(subject)
30
+ @subject = subject
31
+ subject.class.respond_to?(@method)
32
+ end
33
+
34
+ def fail_message
35
+ "#{@subject.class.name} does not have the class method ##{@method}"
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ module TestBelt::Matchers
2
+ module HaveFiles
3
+
4
+ def self.included(receiver)
5
+ receiver.send(:extend, ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def have_files(*files)
10
+ files.collect do |file|
11
+ Matcher.new(file)
12
+ end
13
+ end
14
+ alias_method :have_file, :have_files
15
+ alias_method :have_directories, :have_files
16
+ alias_method :have_directory, :have_files
17
+ end
18
+
19
+ class Matcher < ::TestBelt::Matchers::Base
20
+ def initialize(file_path)
21
+ @file_path = file_path
22
+ end
23
+
24
+ def desc
25
+ "have the file path '#{@file_path}'"
26
+ end
27
+
28
+ def matches?(subject)
29
+ File.exists?(@file_path)
30
+ end
31
+
32
+ def fail_message
33
+ "'#{@file}' does not exist"
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,44 @@
1
+ module TestBelt::Matchers
2
+ module HaveInstanceMethods
3
+
4
+ def self.included(receiver)
5
+ receiver.send(:extend, ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def have_instance_methods(*meths)
10
+ meths.collect do |meth|
11
+ Matcher.new(meth)
12
+ end
13
+ end
14
+ alias_method :have_instance_method, :have_instance_methods
15
+ end
16
+
17
+ class Matcher < ::TestBelt::Matchers::Base
18
+ def initialize(method)
19
+ unless method.kind_of?(::String) || method.kind_of?(::Symbol)
20
+ raise ArgumentError, "please specify the method name using a string or symbol"
21
+ end
22
+ @method = method
23
+ end
24
+
25
+ def method_type
26
+ "instance method"
27
+ end
28
+
29
+ def desc
30
+ "respond to #{method_type} ##{@method}"
31
+ end
32
+
33
+ def matches?(subject)
34
+ @subject = subject
35
+ subject.respond_to?(@method)
36
+ end
37
+
38
+ def fail_message
39
+ "#{@subject.class.name} does not have instance method ##{@method}"
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_belt/matchers/have_instance_methods'
2
+
3
+ module TestBelt::Matchers
4
+ module HaveReaders
5
+
6
+ def self.included(receiver)
7
+ receiver.send(:extend, ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def have_readers(*meths)
12
+ meths.collect do |meth|
13
+ Matcher.new(meth)
14
+ end
15
+ end
16
+ alias_method :have_reader, :have_readers
17
+ end
18
+
19
+ class Matcher < ::TestBelt::Matchers::HaveInstanceMethods::Matcher
20
+ def method_type
21
+ "reader"
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_belt/matchers/have_instance_methods'
2
+
3
+ module TestBelt::Matchers
4
+ module HaveWriters
5
+
6
+ def self.included(receiver)
7
+ receiver.send(:extend, ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def have_writers(*meths)
12
+ meths.collect do |meth|
13
+ Matcher.new(meth)
14
+ end
15
+ end
16
+ alias_method :have_writer, :have_writers
17
+ end
18
+
19
+ class Matcher < ::TestBelt::Matchers::HaveInstanceMethods::Matcher
20
+ def initialize(method)
21
+ super("#{method}=")
22
+ end
23
+
24
+ def method_type
25
+ "writer"
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,76 @@
1
+ module TestBelt
2
+ module Should
3
+
4
+ # This defines a class method 'should' that takes a string
5
+ # describing the test and a block that executes the test. The
6
+ # test will be named:
7
+ # "test: #{context} should #{description}."
8
+
9
+ # Usage:
10
+ # class SomeTest < Test::Unit::TestCase
11
+ # extend TestBelt::Should
12
+ # end
13
+
14
+ def should(matchers_or_desc, &block)
15
+ tests = should_tests(matchers_or_desc, &block)
16
+ context = should_context
17
+
18
+ each_should(context, tests) do |name, code|
19
+ define_method(name) do
20
+ begin
21
+ self.class._testbelt_setups.each {|sb| instance_eval(&sb)}
22
+ instance_eval(&code)
23
+ ensure
24
+ self.class._testbelt_teardowns.reverse.each {|tb| instance_eval(&tb)}
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ # This method is identical to the should version, however this one does
31
+ # nothing but skip any tests described or matched on
32
+ def should_eventually(matchers_or_desc, &block)
33
+ tests = should_tests(matchers_or_desc, &block)
34
+ context = should_context
35
+
36
+ each_should(context, tests) do |name, code|
37
+ define_method(name) { skip }
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def each_should(context, tests)
44
+ tests.each do |t|
45
+ yield should_test_name(context, t[0]), t[1]
46
+ end
47
+ end
48
+
49
+ def should_tests(matchers_or_desc, &block)
50
+ unless matchers_or_desc.kind_of?(::Array) || block_given?
51
+ raise ArgumentError, "either specify a test block and description or a set of matchers"
52
+ end
53
+
54
+ if matchers_or_desc.kind_of?(::Array)
55
+ matchers_or_desc.collect do |matcher|
56
+ [matcher.desc, Proc.new {assert_matcher(matcher)}]
57
+ end
58
+ else
59
+ [[matchers_or_desc.to_s, block]]
60
+ end
61
+ end
62
+
63
+ def should_context
64
+ '' # TODO: context stuff needs to be added to test name
65
+ end
66
+
67
+ def should_test_name(context, name)
68
+ test_name = ["test:", "should", "#{name}. "].flatten.join(' ').to_sym
69
+ if instance_methods.include?(test_name.to_s)
70
+ warn " * WARNING: '#{test_name}' is already defined"
71
+ end
72
+ test_name
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,41 @@
1
+ module Test::Unit
2
+ class TestCase
3
+
4
+ alias_method(:orig_add_error, :add_error)
5
+ def add_error(*args, &block)
6
+ unless args.first.kind_of?(::TestBelt::TestSkipped)
7
+ orig_add_error *args, &block
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+
14
+ module TestBelt
15
+ class TestSkipped < Exception; end
16
+
17
+ module Skip
18
+
19
+ # Sometimes while testing, you may wish to define some tests but not run
20
+ # them just yet. LeftRight provides some nice UI for dealing with skipped
21
+ # tests. Test Belt provides a handy 'skip' method for test cases. Use
22
+ # this method to skip individual tests. If you wish to skip a whole
23
+ # context of tests, add the skip method to a before [[Callback]] and all
24
+ # the tests will be skipped for the class. Since callbacks inherit, any
25
+ # subclassed tests will be skipped as well.
26
+
27
+ # Usage:
28
+ # class SomeTest < Test::Unit::TestCase
29
+ # include TestBelt::Skip
30
+ # end
31
+
32
+ def skip(halt_test=true)
33
+ if defined? ::LeftRight
34
+ ::LeftRight.state.skip = true
35
+ ::LeftRight.state.skipped_count += 1
36
+ end
37
+ raise ::TestBelt::TestSkipped if halt_test
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ module TestBelt
2
+ module Subject
3
+
4
+ # This provides a class method 'subject' on a TestCase. Use this method
5
+ # to initialize the subject of the TestCase. This may be a model, class,
6
+ # or whatever. The subject method takes a block and the result of the
7
+ # block is used as the subject value. Note, the block is for every test
8
+ # withing the scope of the TestCase instance, and after any setup/before
9
+ # callbacks. The subject value is available using the 'subject instance
10
+ # method on the TestCase. Any sub-classed TestCase that does not define
11
+ # it's own subject will inherite the subject of it's super class.
12
+
13
+ # Usage:
14
+ # class SomeTest < Test::Unit::TestCase
15
+ # include TestBelt::Subject
16
+ # end
17
+
18
+ def self.included(receiver)
19
+ receiver.send(:extend, ClassMethods)
20
+ receiver.send(:include, InstanceMethods)
21
+ end
22
+
23
+ module ClassMethods
24
+ def subject(&block)
25
+ raise ArgumentError, "please provide a subject block" unless block_given?
26
+ @_testbelt_subject = block
27
+ end
28
+
29
+ def _testbelt_subject
30
+ @_testbelt_subject || begin
31
+ superclass._testbelt_subject
32
+ rescue NoMethodError
33
+ nil
34
+ end
35
+ end
36
+ end
37
+
38
+ module InstanceMethods
39
+ def subject
40
+ @_testbelt_subject ||= if (sb = self.class._testbelt_subject)
41
+ instance_eval(&sb)
42
+ end
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -1,3 +1,3 @@
1
1
  module TestBelt
2
- VERSION = "0.2.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,172 @@
1
+ require "test/helper"
2
+
3
+ module TestBelt
4
+
5
+ class TestCallbacksTest < Test::Unit::TestCase
6
+ include TestBelt
7
+
8
+ context "A test with callbacks"
9
+ subject { 'subject' }
10
+ before {
11
+ @before = 'before'
12
+ @before_subject = subject
13
+ @expected_after = 'after'
14
+ }
15
+ setup {
16
+ @setup = 'setup'
17
+ @setup_subject = subject
18
+ @expected_teardown = 'teardown'
19
+ }
20
+
21
+ should "run the it's callbacks appropriately" do
22
+ assert_equal 'before', @before
23
+ assert_equal 'setup', @setup
24
+ assert_equal 'subject', @before_subject
25
+ assert_equal 'subject', @setup_subject
26
+ end
27
+
28
+ after {
29
+ assert_equal 'after', @expected_after
30
+ }
31
+ teardown {
32
+ assert_equal 'teardown', @expected_teardown
33
+ }
34
+ end
35
+ class RootCallbacksTest < Test::Unit::TestCase
36
+ include TestBelt
37
+
38
+ before {
39
+ @before = ['root']
40
+ }
41
+ after {
42
+ assert_equal ['nested nested', 'nested'], @after
43
+ }
44
+ end
45
+ class NestedCallbacksTest < RootCallbacksTest
46
+ before {
47
+ @before << 'nested'
48
+ }
49
+ after {
50
+ @after << 'nested'
51
+ }
52
+ end
53
+ class NestedNestedCallbacksTest < NestedCallbacksTest
54
+ should "call it's nested callbacks in order" do
55
+ assert_equal ['root', 'nested'], @before
56
+ end
57
+
58
+ after {
59
+ @after = ['nested nested']
60
+ }
61
+ end
62
+
63
+
64
+
65
+
66
+ class CaseCallbacksTest < Test::Unit::TestCase
67
+ include TestBelt
68
+
69
+ context "A test with case callbacks"
70
+
71
+ before_once {
72
+ @expected_after = 'after'
73
+ if (@@before_once rescue nil)
74
+ @before_once_fail = true
75
+ end
76
+ @@before_once = true
77
+ }
78
+ setup_once {
79
+ @expected_teardown = 'teardown'
80
+ if (@@setup_once rescue nil)
81
+ @setup_once_fail = true
82
+ end
83
+ @@setup_once = true
84
+ }
85
+
86
+ should "run the case callbacks just once" do
87
+ assert true
88
+ end
89
+ should "not run the case callbacks more than once" do
90
+ assert true
91
+ end
92
+
93
+ after_once {
94
+ if (@@after_once rescue nil)
95
+ @after_once_fail = true
96
+ end
97
+ @@after_once = true
98
+ raise 'looks like before_once did not run' unless @expected_after == 'after'
99
+ raise "before_once did not run once" unless (@@before_once rescue nil)
100
+ raise "before_once ran more than once" unless @before_once_fail.nil?
101
+ raise "after_once did not run once" unless (@@after_once rescue nil)
102
+ raise "after_once ran more than once" unless @after_once_fail.nil?
103
+ }
104
+ teardown_once {
105
+ if (@@teardown_once rescue nil)
106
+ @teardown_once_fail = true
107
+ end
108
+ @@teardown_once = true
109
+ raise 'looks like setup_once did not run' unless @expected_teardown == 'teardown'
110
+ raise "setup_once did not run once" unless (@@setup_once rescue nil)
111
+ raise "setup_once ran more than once" unless @setup_once_fail.nil?
112
+ raise "teardown_once did not run once" unless (@@teardown_once rescue nil)
113
+ raise "teardown_once ran more than once" unless @teardown_once_fail.nil?
114
+ }
115
+ end
116
+
117
+
118
+
119
+
120
+ class SuiteCallbacksTest < Test::Unit::TestCase
121
+ include TestBelt
122
+
123
+ context "A test with suite callbacks"
124
+
125
+ suite_started {
126
+ @started_assert = true
127
+ @expected_finished = 'finished'
128
+ if (@@started rescue nil)
129
+ @started_fail = true
130
+ end
131
+ @@started = true
132
+ }
133
+ on_suite_started {
134
+ @on_started_assert = true
135
+ @expected_on_finished = 'on finished'
136
+ if (@@on_started rescue nil)
137
+ @on_started_fail = true
138
+ end
139
+ @@on_started = true
140
+ }
141
+
142
+ should "run the suite callbacks just once" do
143
+ assert true
144
+ end
145
+ should "not run the suite callbacks more than once" do
146
+ assert true
147
+ end
148
+
149
+ suite_finished {
150
+ if (@@finished rescue nil)
151
+ @finished_fail = true
152
+ end
153
+ @@finished = true
154
+ raise 'looks like suite_started did not run' unless @expected_finished == 'finished'
155
+ raise "suite_started did not run once" unless (@@started rescue nil)
156
+ raise "suite_started ran more than once" unless @started_fail.nil?
157
+ raise "suite_finished did not run once" unless (@@finished rescue nil)
158
+ raise "suite_finished ran more than once" unless @finished_fail.nil?
159
+ }
160
+ on_suite_finished {
161
+ if (@@on_finished rescue nil)
162
+ @on_finished_fail = true
163
+ end
164
+ @@on_finished = true
165
+ raise 'looks like on_suite_started did not run' unless @expected_on_finished == 'on finished'
166
+ raise "on_suite_started did not run once" unless (@@on_started rescue nil)
167
+ raise "on_suite_started ran more than once" unless @on_started_fail.nil?
168
+ raise "on_suite_finished did not run once" unless (@@on_finished rescue nil)
169
+ raise "on_suite_finished ran more than once" unless @on_finished_fail.nil?
170
+ }
171
+ end
172
+ end