shoulda-context 1.2.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -1
  3. data/.hound.yml +3 -0
  4. data/.rubocop.yml +190 -0
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +36 -2
  7. data/Appraisals +100 -29
  8. data/CHANGELOG.md +29 -0
  9. data/Gemfile +15 -1
  10. data/Gemfile.lock +70 -0
  11. data/MIT-LICENSE +1 -1
  12. data/README.md +140 -29
  13. data/Rakefile +20 -15
  14. data/bin/install_gems_in_all_appraisals +16 -0
  15. data/bin/run_all_tests +16 -0
  16. data/bin/setup +190 -0
  17. data/bin/supported_ruby_versions +7 -0
  18. data/bin/update_gem_in_all_appraisals +17 -0
  19. data/bin/update_gems_in_all_appraisals +16 -0
  20. data/{bin → exe}/convert_to_should_syntax +0 -0
  21. data/gemfiles/rails_4_2.gemfile +35 -0
  22. data/gemfiles/rails_4_2.gemfile.lock +234 -0
  23. data/gemfiles/rails_5_0.gemfile +33 -0
  24. data/gemfiles/rails_5_0.gemfile.lock +226 -0
  25. data/gemfiles/rails_5_1.gemfile +34 -0
  26. data/gemfiles/rails_5_1.gemfile.lock +242 -0
  27. data/gemfiles/rails_5_2.gemfile +36 -0
  28. data/gemfiles/rails_5_2.gemfile.lock +261 -0
  29. data/gemfiles/rails_6_0.gemfile +38 -0
  30. data/gemfiles/rails_6_0.gemfile.lock +286 -0
  31. data/lib/shoulda/context.rb +13 -16
  32. data/lib/shoulda/context/assertions.rb +16 -13
  33. data/lib/shoulda/context/configuration.rb +19 -0
  34. data/lib/shoulda/context/context.rb +33 -307
  35. data/lib/shoulda/context/dsl.rb +279 -0
  36. data/lib/shoulda/context/rails_test_unit_reporter_patch.rb +21 -0
  37. data/lib/shoulda/context/railtie.rb +14 -0
  38. data/lib/shoulda/context/test_framework_detection.rb +4 -5
  39. data/lib/shoulda/context/version.rb +1 -1
  40. data/lib/shoulda/context/world.rb +22 -0
  41. data/shoulda-context.gemspec +11 -18
  42. data/test/fake_rails_root/test/shoulda_macros/custom_macro.rb +1 -1
  43. data/test/fake_rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +1 -2
  44. data/test/fake_rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +1 -2
  45. data/test/shoulda/autoload_macro_test.rb +1 -1
  46. data/test/shoulda/context_test.rb +92 -53
  47. data/test/shoulda/convert_to_should_syntax_test.rb +5 -7
  48. data/test/shoulda/helpers_test.rb +24 -59
  49. data/test/shoulda/railtie_test.rb +43 -0
  50. data/test/shoulda/rerun_snippet_test.rb +45 -0
  51. data/test/shoulda/should_test.rb +163 -24
  52. data/test/shoulda/test_framework_detection_test.rb +64 -71
  53. data/test/support/current_bundle.rb +61 -0
  54. data/test/support/rails_application_with_shoulda_context.rb +46 -0
  55. data/test/support/snowglobe.rb +5 -0
  56. data/test/test_helper.rb +43 -11
  57. metadata +46 -142
  58. data/gemfiles/minitest_4_x.gemfile +0 -7
  59. data/gemfiles/minitest_4_x.gemfile.lock +0 -96
  60. data/gemfiles/minitest_5_x.gemfile +0 -7
  61. data/gemfiles/minitest_5_x.gemfile.lock +0 -102
  62. data/gemfiles/rails_3_0.gemfile +0 -8
  63. data/gemfiles/rails_3_0.gemfile.lock +0 -93
  64. data/gemfiles/rails_3_1.gemfile +0 -10
  65. data/gemfiles/rails_3_1.gemfile.lock +0 -114
  66. data/gemfiles/rails_3_2.gemfile +0 -10
  67. data/gemfiles/rails_3_2.gemfile.lock +0 -112
  68. data/gemfiles/rails_4_0.gemfile +0 -10
  69. data/gemfiles/rails_4_0.gemfile.lock +0 -107
  70. data/gemfiles/rails_4_1.gemfile +0 -10
  71. data/gemfiles/rails_4_1.gemfile.lock +0 -119
  72. data/gemfiles/test_unit.gemfile +0 -7
  73. data/gemfiles/test_unit.gemfile.lock +0 -95
  74. data/init.rb +0 -1
  75. data/rails/init.rb +0 -4
@@ -0,0 +1,279 @@
1
+ require "shoulda/context/assertions"
2
+
3
+ module Shoulda
4
+ module Context
5
+ module DSL
6
+ def self.included(base)
7
+ base.class_eval do
8
+ include Assertions
9
+ include InstanceMethods
10
+ end
11
+ base.extend(ClassMethods)
12
+ end
13
+
14
+ module ClassMethods
15
+ # == Should statements
16
+ #
17
+ # Should statements are just syntactic sugar over normal Test::Unit test
18
+ # methods. A should block contains all the normal code and assertions
19
+ # you're used to seeing, with the added benefit that they can be wrapped
20
+ # inside context blocks (see below).
21
+ #
22
+ # === Example:
23
+ #
24
+ # class UserTest < Test::Unit::TestCase
25
+ #
26
+ # def setup
27
+ # @user = User.new("John", "Doe")
28
+ # end
29
+ #
30
+ # should "return its full name"
31
+ # assert_equal 'John Doe', @user.full_name
32
+ # end
33
+ #
34
+ # end
35
+ #
36
+ # ...will produce the following test:
37
+ # * <tt>"test: User should return its full name. "</tt>
38
+ #
39
+ # Note: The part before <tt>should</tt> in the test name is gleamed from the name of the Test::Unit class.
40
+ #
41
+ # Should statements can also take a Proc as a <tt>:before </tt>option. This proc runs after any
42
+ # parent context's setups but before the current context's setup.
43
+ #
44
+ # === Example:
45
+ #
46
+ # context "Some context" do
47
+ # setup { puts("I run after the :before proc") }
48
+ #
49
+ # should "run a :before proc", :before => lambda { puts("I run before the setup") } do
50
+ # assert true
51
+ # end
52
+ # end
53
+ #
54
+ # Should statements can also wrap matchers, making virtually any matcher
55
+ # usable in a macro style. The matcher's description is used to generate a
56
+ # test name and failure message, and the test will pass if the matcher
57
+ # matches the subject.
58
+ #
59
+ # === Example:
60
+ #
61
+ # should validate_presence_of(:first_name).with_message(/gotta be there/)
62
+ #
63
+
64
+ def should(name_or_matcher, options = {}, &blk)
65
+ if Shoulda::Context.current_context
66
+ Shoulda::Context.current_context.should(name_or_matcher, options, &blk)
67
+ else
68
+ context_name = self.name.gsub(/Test$/, "") if name
69
+ context = Shoulda::Context::Context.new(context_name, self) do
70
+ should(name_or_matcher, options, &blk)
71
+ end
72
+ context.build
73
+ end
74
+ end
75
+
76
+ # Allows negative tests using matchers. The matcher's description is used
77
+ # to generate a test name and negative failure message, and the test will
78
+ # pass unless the matcher matches the subject.
79
+ #
80
+ # === Example:
81
+ #
82
+ # should_not set_the_flash
83
+ def should_not(matcher)
84
+ if Shoulda::Context.current_context
85
+ Shoulda::Context.current_context.should_not(matcher)
86
+ else
87
+ context_name = self.name.gsub(/Test$/, "") if name
88
+ context = Shoulda::Context::Context.new(context_name, self) do
89
+ should_not(matcher)
90
+ end
91
+ context.build
92
+ end
93
+ end
94
+
95
+ # == Before statements
96
+ #
97
+ # Before statements are should statements that run before the current
98
+ # context's setup. These are especially useful when setting expectations.
99
+ #
100
+ # === Example:
101
+ #
102
+ # class UserControllerTest < Test::Unit::TestCase
103
+ # context "the index action" do
104
+ # setup do
105
+ # @users = [Factory(:user)]
106
+ # User.stubs(:find).returns(@users)
107
+ # end
108
+ #
109
+ # context "on GET" do
110
+ # setup { get :index }
111
+ #
112
+ # should respond_with(:success)
113
+ #
114
+ # # runs before "get :index"
115
+ # before_should "find all users" do
116
+ # User.expects(:find).with(:all).returns(@users)
117
+ # end
118
+ # end
119
+ # end
120
+ # end
121
+ def before_should(name, &blk)
122
+ should(name, :before => blk) { assert true }
123
+ end
124
+
125
+ # Just like should, but never runs, and instead prints an 'X' in the Test::Unit output.
126
+ def should_eventually(name, options = {}, &blk)
127
+ context_name = self.name.gsub(/Test$/, "")
128
+ context = Shoulda::Context::Context.new(context_name, self) do
129
+ should_eventually(name, &blk)
130
+ end
131
+ context.build
132
+ end
133
+
134
+ # == Contexts
135
+ #
136
+ # A context block groups should statements under a common set of setup/teardown methods.
137
+ # Context blocks can be arbitrarily nested, and can do wonders for improving the maintainability
138
+ # and readability of your test code.
139
+ #
140
+ # A context block can contain setup, should, should_eventually, and teardown blocks.
141
+ #
142
+ # class UserTest < Test::Unit::TestCase
143
+ # context "A User instance" do
144
+ # setup do
145
+ # @user = User.find(:first)
146
+ # end
147
+ #
148
+ # should "return its full name"
149
+ # assert_equal 'John Doe', @user.full_name
150
+ # end
151
+ # end
152
+ # end
153
+ #
154
+ # This code will produce the method <tt>"test: A User instance should return its full name. "</tt>.
155
+ #
156
+ # Contexts may be nested. Nested contexts run their setup blocks from out to in before each
157
+ # should statement. They then run their teardown blocks from in to out after each should statement.
158
+ #
159
+ # class UserTest < Test::Unit::TestCase
160
+ # context "A User instance" do
161
+ # setup do
162
+ # @user = User.find(:first)
163
+ # end
164
+ #
165
+ # should "return its full name"
166
+ # assert_equal 'John Doe', @user.full_name
167
+ # end
168
+ #
169
+ # context "with a profile" do
170
+ # setup do
171
+ # @user.profile = Profile.find(:first)
172
+ # end
173
+ #
174
+ # should "return true when sent :has_profile?"
175
+ # assert @user.has_profile?
176
+ # end
177
+ # end
178
+ # end
179
+ # end
180
+ #
181
+ # This code will produce the following methods
182
+ # * <tt>"test: A User instance should return its full name. "</tt>
183
+ # * <tt>"test: A User instance with a profile should return true when sent :has_profile?. "</tt>
184
+ #
185
+ # <b>Just like should statements, a context block can exist next to normal <tt>def test_the_old_way; end</tt>
186
+ # tests</b>. This means you do not have to fully commit to the context/should syntax in a test file.
187
+
188
+ def context(name, &blk)
189
+ if Shoulda::Context.current_context
190
+ Shoulda::Context.current_context.context(name, &blk)
191
+ else
192
+ context = Shoulda::Context::Context.new(name, self, &blk)
193
+ context.build
194
+ end
195
+ end
196
+
197
+ # Returns the class being tested, as determined by the test class name.
198
+ #
199
+ # class UserTest; described_type; end
200
+ # # => User
201
+ def described_type
202
+ @described_type ||= self.name.
203
+ gsub(/Test$/, '').
204
+ split('::').
205
+ inject(Object) do |parent, local_name|
206
+ parent.const_get(local_name, false)
207
+ end
208
+ end
209
+
210
+ # Sets the return value of the subject instance method:
211
+ #
212
+ # class UserTest < Test::Unit::TestCase
213
+ # subject { User.first }
214
+ #
215
+ # # uses the existing user
216
+ # should validate_uniqueness_of(:email)
217
+ # end
218
+ def subject(&block)
219
+ @subject_block = block
220
+ end
221
+
222
+ def subject_block # :nodoc:
223
+ @subject_block ||= nil
224
+ end
225
+ end
226
+
227
+ module InstanceMethods
228
+ # Returns an instance of the class under test.
229
+ #
230
+ # class UserTest
231
+ # should "be a user" do
232
+ # assert_kind_of User, subject # passes
233
+ # end
234
+ # end
235
+ #
236
+ # The subject can be explicitly set using the subject class method:
237
+ #
238
+ # class UserTest
239
+ # subject { User.first }
240
+ # should "be an existing user" do
241
+ # assert !subject.new_record? # uses the first user
242
+ # end
243
+ # end
244
+ #
245
+ # The subject is used by all macros that require an instance of the class
246
+ # being tested.
247
+ def subject
248
+ @shoulda_subject ||= construct_subject
249
+ end
250
+
251
+ def subject_block # :nodoc:
252
+ (@shoulda_context && @shoulda_context.subject_block) || self.class.subject_block
253
+ end
254
+
255
+ def get_instance_of(object_or_klass) # :nodoc:
256
+ if object_or_klass.is_a?(Class)
257
+ object_or_klass.new
258
+ else
259
+ object_or_klass
260
+ end
261
+ end
262
+
263
+ def instance_variable_name_for(klass) # :nodoc:
264
+ klass.to_s.split('::').last.underscore
265
+ end
266
+
267
+ private
268
+
269
+ def construct_subject
270
+ if subject_block
271
+ instance_eval(&subject_block)
272
+ else
273
+ get_instance_of(self.class.described_type)
274
+ end
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,21 @@
1
+ begin
2
+ require "rails/test_unit/reporter"
3
+
4
+ Rails::TestUnitReporter.class_eval do
5
+ # Fix #format_rerun_snippet so that it works with recent versions of Minitest.
6
+ # This was cribbed from:
7
+ # <https://github.com/rails/rails/commit/ff0d5f14504f1aa29ad908ab15bab66b101427b7#diff-a071a1c8f51ce3b8bcb17ca59c79fc70>
8
+ def format_rerun_snippet(result)
9
+ location, line =
10
+ if result.respond_to?(:source_location)
11
+ result.source_location
12
+ else
13
+ result.method(result.name).source_location
14
+ end
15
+
16
+ "#{executable} #{relative_path_for(location)}:#{line}"
17
+ end
18
+ end
19
+ rescue LoadError
20
+ # Rails::TestUnitReporter was introduced in Rails 5
21
+ end
@@ -0,0 +1,14 @@
1
+ module Shoulda
2
+ module Context
3
+ class Railtie < Rails::Railtie
4
+ initializer "shoulda_context.autoload_macros" do
5
+ if Rails.env.test?
6
+ Shoulda.autoload_macros(
7
+ Rails.root,
8
+ File.join("vendor", "{plugins,gems}", "*")
9
+ )
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -3,10 +3,9 @@ module Shoulda
3
3
  module TestFrameworkDetection
4
4
  def self.possible_test_frameworks
5
5
  [
6
- lambda { ActiveSupport::TestCase },
7
- lambda { Minitest::Test },
8
- lambda { MiniTest::Unit::TestCase },
9
- lambda { Test::Unit::TestCase }
6
+ -> { ActiveSupport::TestCase },
7
+ -> { Minitest::Test },
8
+ -> { Test::Unit::TestCase }
10
9
  ]
11
10
  end
12
11
 
@@ -23,7 +22,7 @@ module Shoulda
23
22
  end
24
23
 
25
24
  def self.test_framework_test_cases
26
- @_test_framework_test_case ||= detected_test_framework_test_cases
25
+ @_test_framework_test_cases ||= detected_test_framework_test_cases
27
26
  end
28
27
  end
29
28
 
@@ -1,5 +1,5 @@
1
1
  module Shoulda
2
2
  module Context
3
- VERSION = '1.2.2'.freeze
3
+ VERSION = "2.0.0".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,22 @@
1
+ module Shoulda
2
+ module Context
3
+ class << self
4
+ def contexts # :nodoc:
5
+ @contexts ||= []
6
+ end
7
+ attr_writer :contexts
8
+
9
+ def current_context # :nodoc:
10
+ self.contexts.last
11
+ end
12
+
13
+ def add_context(context) # :nodoc:
14
+ self.contexts.push(context)
15
+ end
16
+
17
+ def remove_context # :nodoc:
18
+ self.contexts.pop
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,30 +1,23 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
3
- require 'shoulda/context/version'
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "lib")
4
+ require "shoulda/context/version"
4
5
 
5
6
  Gem::Specification.new do |s|
6
- s.name = %q{shoulda-context}
7
+ s.name = "shoulda-context"
7
8
  s.version = Shoulda::Context::VERSION.dup
8
9
  s.platform = Gem::Platform::RUBY
9
10
  s.authors = ["thoughtbot, inc.", "Tammer Saleh", "Joe Ferris",
10
11
  "Ryan McGeary", "Dan Croak", "Matt Jankowski"]
11
- s.email = %q{support@thoughtbot.com}
12
- s.homepage = %q{http://thoughtbot.com/community/}
13
- s.summary = %q{Context framework extracted from Shoulda}
14
- s.description = %q{Context framework extracted from Shoulda}
15
- s.license = %q{MIT}
12
+ s.email = "support@thoughtbot.com"
13
+ s.homepage = "http://thoughtbot.com/community/"
14
+ s.summary = "Context framework extracted from Shoulda"
15
+ s.description = "Context framework extracted from Shoulda"
16
+ s.license = "MIT"
16
17
 
17
18
  s.files = `git ls-files`.split("\n")
18
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.executables = `git ls-files -- exe/*`.split("\n").map { |f| File.basename(f) }
21
+ s.bindir = "exe"
20
22
  s.require_paths = ["lib"]
21
-
22
- s.add_development_dependency("appraisal", "~> 0.5")
23
- s.add_development_dependency("rails", ">= 3.0")
24
- s.add_development_dependency("mocha", "~> 0.9.10")
25
- s.add_development_dependency("rake")
26
- s.add_development_dependency("test-unit", "~> 2.1.0")
27
- s.add_development_dependency("pry")
28
- s.add_development_dependency("byebug")
29
- s.add_development_dependency("pry-byebug")
30
23
  end
@@ -2,5 +2,5 @@ module CustomMacro
2
2
  def custom_macro
3
3
  end
4
4
  end
5
- Test::Unit::TestCase.extend(CustomMacro)
5
+ PARENT_TEST_CASE.extend(CustomMacro)
6
6
 
@@ -2,5 +2,4 @@ module GemMacro
2
2
  def gem_macro
3
3
  end
4
4
  end
5
- Test::Unit::TestCase.extend(GemMacro)
6
-
5
+ PARENT_TEST_CASE.extend(GemMacro)
@@ -2,5 +2,4 @@ module PluginMacro
2
2
  def plugin_macro
3
3
  end
4
4
  end
5
- Test::Unit::TestCase.extend(PluginMacro)
6
-
5
+ PARENT_TEST_CASE.extend(PluginMacro)
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class AutoloadMacroTest < Test::Unit::TestCase # :nodoc:
3
+ class AutoloadMacroTest < PARENT_TEST_CASE
4
4
  context "The macro auto-loader" do
5
5
  should "load macros from the plugins" do
6
6
  assert self.class.respond_to?('plugin_macro')
@@ -1,7 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class ContextTest < Test::Unit::TestCase # :nodoc:
4
-
3
+ class ContextTest < PARENT_TEST_CASE
5
4
  def self.context_macro(&blk)
6
5
  context "with a subcontext made by a macro" do
7
6
  setup { @context_macro = :foo }
@@ -20,7 +19,7 @@ class ContextTest < Test::Unit::TestCase # :nodoc:
20
19
  end
21
20
 
22
21
  should "have name set right" do
23
- assert_match(/^test: context with setup block/, self.to_s)
22
+ assert_match(/^test: context with setup block/, normalized_name)
24
23
  end
25
24
 
26
25
  context "and a subcontext" do
@@ -29,7 +28,7 @@ class ContextTest < Test::Unit::TestCase # :nodoc:
29
28
  end
30
29
 
31
30
  should "be named correctly" do
32
- assert_match(/^test: context with setup block and a subcontext should be named correctly/, self.to_s)
31
+ assert_match(/^test: context with setup block and a subcontext should be named correctly/, normalized_name)
33
32
  end
34
33
 
35
34
  should "run the setup blocks in order" do
@@ -39,7 +38,7 @@ class ContextTest < Test::Unit::TestCase # :nodoc:
39
38
 
40
39
  context_macro do
41
40
  should "have name set right" do
42
- assert_match(/^test: context with setup block with a subcontext made by a macro should have name set right/, self.to_s)
41
+ assert_match(/^test: context with setup block with a subcontext made by a macro should have name set right/, normalized_name)
43
42
  end
44
43
 
45
44
  should "run the setup block of that context macro" do
@@ -63,7 +62,7 @@ class ContextTest < Test::Unit::TestCase # :nodoc:
63
62
  end
64
63
 
65
64
  should "have name set right" do
66
- assert_match(/^test: another context with setup block/, self.to_s)
65
+ assert_match(/^test: another context with setup block/, normalized_name)
67
66
  end
68
67
  end
69
68
 
@@ -77,7 +76,7 @@ class ContextTest < Test::Unit::TestCase # :nodoc:
77
76
  end
78
77
 
79
78
  should "have name set right" do
80
- assert_match(/^test: context with method definition/, self.to_s)
79
+ assert_match(/^test: context with method definition/, normalized_name)
81
80
  end
82
81
  end
83
82
 
@@ -166,19 +165,22 @@ class ContextTest < Test::Unit::TestCase # :nodoc:
166
165
  end
167
166
  end
168
167
 
168
+ def normalized_name
169
+ name.sub("test_:", "test:")
170
+ end
169
171
  end
170
172
 
171
173
  class ::Some
172
174
  class NestedModel; end
173
175
  end
174
176
 
175
- class Some::NestedModelTest < Test::Unit::TestCase
177
+ class Some::NestedModelTest < PARENT_TEST_CASE
176
178
  should "determine the described type for a nested model" do
177
179
  assert_equal Some::NestedModel, self.class.described_type
178
180
  end
179
181
  end
180
182
 
181
- class Some::SomeTest < Test::Unit::TestCase
183
+ class Some::SomeTest < PARENT_TEST_CASE
182
184
  should "not fallback to higher-level constants with same name" do
183
185
  assert_raises(NameError) do
184
186
  assert_equal nil, self.class.described_type
@@ -186,13 +188,13 @@ class Some::SomeTest < Test::Unit::TestCase
186
188
  end
187
189
  end
188
190
 
189
- class ShouldMatcherTest < Test::Unit::TestCase
191
+ class ShouldMatcherTest < PARENT_TEST_CASE
190
192
  class FakeMatcher
191
193
  attr_reader :subject
192
194
  attr_accessor :fail
193
195
 
194
196
  def description
195
- "do something"
197
+ "be a fake matcher"
196
198
  end
197
199
 
198
200
  def matches?(subject)
@@ -200,46 +202,33 @@ class ShouldMatcherTest < Test::Unit::TestCase
200
202
  !@fail
201
203
  end
202
204
 
203
- def failure_message_for_should
204
- "failure message for should"
205
+ def failure_message
206
+ "positive failure message"
205
207
  end
206
208
 
207
- def failure_message_for_should_not
208
- "failure message for should not"
209
+ def failure_message_when_negated
210
+ "negative failure message"
209
211
  end
210
212
  end
211
213
 
212
- def run_test_suite
213
- @test_suite.run(@test_result) { |event, name| }
214
- end
215
-
216
214
  def setup
217
215
  @matcher = FakeMatcher.new
218
- @test_result = Test::Unit::TestResult.new
219
- class << @test_result
220
- def failure_messages
221
- @failures.map { |failure| failure.message }
222
- end
223
- end
224
- end
225
-
226
- def create_test_suite(&definition)
227
- test_class = Class.new(Test::Unit::TestCase, &definition)
228
- test_class.suite
229
216
  end
230
217
 
231
- def assert_failed_with(message, test_result)
232
- assert_equal 1, test_result.failure_count
233
- assert_equal [message], test_result.failure_messages
218
+ def assert_failed_with(message, test_suite)
219
+ assert_equal [message], test_suite.failure_messages
234
220
  end
235
221
 
236
- def assert_passed(test_result)
237
- assert_equal 0, test_result.failure_count
222
+ def assert_passed(test_suite)
223
+ assert_equal [], test_suite.failure_messages
238
224
  end
239
225
 
240
226
  def assert_test_named(expected_name, test_suite)
241
- name = test_suite.tests.map { |test| test.method_name }.first
242
- assert name.include?(expected_name), "Expected #{name} to include #{expected_name}"
227
+ name = test_suite.test_names.first
228
+ assert(
229
+ name.include?(expected_name),
230
+ "Expected #{name} to include #{expected_name}"
231
+ )
243
232
  end
244
233
 
245
234
  def self.should_use_positive_matcher
@@ -249,19 +238,19 @@ class ShouldMatcherTest < Test::Unit::TestCase
249
238
 
250
239
  should "pass with a passing matcher" do
251
240
  @matcher.fail = false
252
- run_test_suite
253
- assert_passed @test_result
241
+ @test_suite.run
242
+ assert_passed @test_suite
254
243
  end
255
244
 
256
245
  should "fail with a failing matcher" do
257
246
  @matcher.fail = true
258
- run_test_suite
259
- assert_failed_with "failure message for should", @test_result
247
+ @test_suite.run
248
+ assert_failed_with "positive failure message", @test_suite
260
249
  end
261
250
 
262
251
  should "provide the subject" do
263
252
  @matcher.fail = false
264
- run_test_suite
253
+ @test_suite.run
265
254
  assert_equal 'a subject', @matcher.subject
266
255
  end
267
256
  end
@@ -273,19 +262,19 @@ class ShouldMatcherTest < Test::Unit::TestCase
273
262
 
274
263
  should "pass with a failing matcher" do
275
264
  @matcher.fail = true
276
- run_test_suite
277
- assert_passed @test_result
265
+ @test_suite.run
266
+ assert_passed @test_suite
278
267
  end
279
268
 
280
269
  should "fail with a passing matcher" do
281
270
  @matcher.fail = false
282
- run_test_suite
283
- assert_failed_with "failure message for should not", @test_result
271
+ @test_suite.run
272
+ assert_failed_with "negative failure message", @test_suite
284
273
  end
285
274
 
286
275
  should "provide the subject" do
287
276
  @matcher.fail = false
288
- run_test_suite
277
+ @test_suite.run
289
278
  assert_equal 'a subject', @matcher.subject
290
279
  end
291
280
  end
@@ -293,7 +282,7 @@ class ShouldMatcherTest < Test::Unit::TestCase
293
282
  context "a should block with a matcher" do
294
283
  setup do
295
284
  matcher = @matcher
296
- @test_suite = create_test_suite do
285
+ @test_suite = TestSuite.create do
297
286
  subject { 'a subject' }
298
287
  should matcher
299
288
  end
@@ -305,7 +294,7 @@ class ShouldMatcherTest < Test::Unit::TestCase
305
294
  context "a should block with a matcher within a context" do
306
295
  setup do
307
296
  matcher = @matcher
308
- @test_suite = create_test_suite do
297
+ @test_suite = TestSuite.create do
309
298
  context "in context" do
310
299
  subject { 'a subject' }
311
300
  should matcher
@@ -319,7 +308,7 @@ class ShouldMatcherTest < Test::Unit::TestCase
319
308
  context "a should_not block with a matcher" do
320
309
  setup do
321
310
  matcher = @matcher
322
- @test_suite = create_test_suite do
311
+ @test_suite = TestSuite.create do
323
312
  subject { 'a subject' }
324
313
  should_not matcher
325
314
  end
@@ -331,7 +320,7 @@ class ShouldMatcherTest < Test::Unit::TestCase
331
320
  context "a should_not block with a matcher within a context" do
332
321
  setup do
333
322
  matcher = @matcher
334
- @test_suite = create_test_suite do
323
+ @test_suite = TestSuite.create do
335
324
  context "in context" do
336
325
  subject { 'a subject' }
337
326
  should_not matcher
@@ -341,11 +330,61 @@ class ShouldMatcherTest < Test::Unit::TestCase
341
330
 
342
331
  should_use_negative_matcher
343
332
  end
333
+
334
+ class TestSuite
335
+ def self.create(&definition)
336
+ if defined?(Test::Unit)
337
+ TestUnitSuite.new(&definition)
338
+ else
339
+ MinitestSuite.new(&definition)
340
+ end
341
+ end
342
+ end
343
+
344
+ class TestUnitSuite
345
+ def initialize(&definition)
346
+ @suite = Class.new(Test::Unit::TestCase, &definition).suite
347
+ @result = Test::Unit::TestResult.new
348
+ end
349
+
350
+ def run
351
+ @suite.run(@result) do |event, name|
352
+ # do nothing
353
+ end
354
+ end
355
+
356
+ def failure_messages
357
+ @result.failures.map(&:message)
358
+ end
359
+
360
+ def test_names
361
+ @suite.tests.map(&:method_name)
362
+ end
363
+ end
364
+
365
+ class MinitestSuite
366
+ def initialize(&definition)
367
+ @test_case_class = Class.new(Minitest::Test, &definition)
368
+ @reporter = Minitest::StatisticsReporter.new(StringIO.new)
369
+ end
370
+
371
+ def run
372
+ @test_case_class.run(@reporter)
373
+ end
374
+
375
+ def failure_messages
376
+ @reporter.results.flat_map(&:failures).map(&:message)
377
+ end
378
+
379
+ def test_names
380
+ @test_case_class.runnable_methods
381
+ end
382
+ end
344
383
  end
345
384
 
346
385
  class Subject; end
347
386
 
348
- class SubjectTest < Test::Unit::TestCase
387
+ class SubjectTest < PARENT_TEST_CASE
349
388
 
350
389
  def setup
351
390
  @expected = Subject.new
@@ -358,7 +397,7 @@ class SubjectTest < Test::Unit::TestCase
358
397
  end
359
398
  end
360
399
 
361
- class SubjectLazinessTest < Test::Unit::TestCase
400
+ class SubjectLazinessTest < PARENT_TEST_CASE
362
401
  subject { Subject.new }
363
402
 
364
403
  should "only build the subject once" do