smartest 0.2.0.alpha3 → 0.2.0.alpha4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17a325d82883047881ac13538f95b3af038e361668869860034acc530ce2e398
4
- data.tar.gz: 19c6a1a345e7e0fd02a12ae007a48f38c1be264debd3b23b0b6085d687a867bf
3
+ metadata.gz: 944d35bc0a1be2293c8e276d16436693ff7dd6a2d37218f9f65af3b7a47f90f5
4
+ data.tar.gz: edd55fb6442a92e74146eaffc76a3b881463a16b4ce3c72a877734e0f6e36f52
5
5
  SHA512:
6
- metadata.gz: 5b4aeb31472fca3b0911dfb29d4034405f493ac37e3019888a67f1c13c0b1f4aac99dc33b87c7e79a8d363b7bf12f7682b97bea396ebc56b558b592a7658eee9
7
- data.tar.gz: 4e1c0cc3b739b62af8c4eeef394662f8115e35f890cdde87ce32117eca26c4064b627a08a2ca204c856276d2a603de8c4c55e2f9c71d2f68c44fd864e13c2ecc
6
+ metadata.gz: 5406cfcb57b56c71140c98565da884a184b8d14dcd41f8d6f65f218010d5ef7672eee6c3ad874dcc22a2d415097c9f9926f3a22c31ea3f5dafcf6dd00c2c795d
7
+ data.tar.gz: '0666928711e5ec22a5f9d671714597eb9e0a7e98edcf11d334bf72301c42739a8ae71104dff5784fa4728c10c186188e9f5278137ebbf7d22f6e14e745964927'
data/README.md CHANGED
@@ -179,6 +179,8 @@ Smartest uses an expectation style:
179
179
  expect(actual).to eq(expected)
180
180
  expect(actual).not_to eq(expected)
181
181
  expect { action }.to raise_error(ErrorClass)
182
+ expect { action }.to raise_error(/message/)
183
+ expect { action }.to raise_error(ErrorClass, /message/)
182
184
  expect { action }.to change { value }
183
185
  ```
184
186
 
@@ -200,6 +202,18 @@ end
200
202
  test("download") do
201
203
  expect("screenshot.png").to end_with(".png")
202
204
  end
205
+
206
+ test("type") do
207
+ expect("smartest").to be_a(String)
208
+ end
209
+
210
+ test("URL pattern") do
211
+ expect("https://example.test").to match(%r{\Ahttps://})
212
+ end
213
+
214
+ test("events") do
215
+ expect(%i[request close open]).to contain_exactly(:open, :request, :close)
216
+ end
203
217
  ```
204
218
 
205
219
  Supported matchers include:
@@ -209,13 +223,29 @@ eq(expected)
209
223
  include(expected)
210
224
  start_with(prefix, ...)
211
225
  end_with(suffix, ...)
226
+ be_a(ClassOrModule)
227
+ be_an(ClassOrModule)
212
228
  be_nil
229
+ match(regexp)
230
+ contain_exactly(item, ...)
231
+ match_array(items)
213
232
  raise_error(ErrorClass)
233
+ raise_error(/message/)
234
+ raise_error(ErrorClass, /message/)
214
235
  change { value }
215
236
  change { value }.from(before).to(after)
216
237
  change { value }.by(delta)
217
238
  ```
218
239
 
240
+ `raise_error` accepts an error class, a message regexp, or both. Use an error
241
+ class to check the raised exception class, a regexp to check the raised
242
+ exception message, or both to require both conditions. No-argument and exact
243
+ string message forms are not supported.
244
+
245
+ `contain_exactly` and `match_array` compare collections without requiring a
246
+ specific order, preserve duplicate counts, and can use matcher objects such as
247
+ `match(/foo/)` or `eq(42)` as expected items.
248
+
219
249
  `change` is only supported with `expect { ... }` block expectations and must be
220
250
  written with a value block.
221
251
 
data/SMARTEST_DESIGN.md CHANGED
@@ -727,8 +727,15 @@ eq(expected)
727
727
  include(expected)
728
728
  start_with(prefix, ...)
729
729
  end_with(suffix, ...)
730
+ be_a(ClassOrModule)
731
+ be_an(ClassOrModule)
730
732
  be_nil
733
+ match(regexp)
734
+ contain_exactly(item, ...)
735
+ match_array(items)
731
736
  raise_error(ErrorClass)
737
+ raise_error(/message/)
738
+ raise_error(ErrorClass, /message/)
732
739
  change { value }
733
740
  ```
734
741
 
@@ -18,12 +18,32 @@ module Smartest
18
18
  EndWithMatcher.new(*suffixes)
19
19
  end
20
20
 
21
+ def be_a(expected_class)
22
+ BeAKindOfMatcher.new(expected_class)
23
+ end
24
+
25
+ def be_an(expected_class)
26
+ BeAKindOfMatcher.new(expected_class)
27
+ end
28
+
21
29
  def be_nil
22
30
  BeNilMatcher.new
23
31
  end
24
32
 
25
- def raise_error(expected_error = StandardError)
26
- RaiseErrorMatcher.new(expected_error)
33
+ def match(regexp)
34
+ MatchMatcher.new(regexp)
35
+ end
36
+
37
+ def contain_exactly(*expected_items)
38
+ ContainExactlyMatcher.new(expected_items, matcher_name: "contain exactly")
39
+ end
40
+
41
+ def match_array(expected_items)
42
+ ContainExactlyMatcher.new(expected_items, matcher_name: "match array")
43
+ end
44
+
45
+ def raise_error(*expected_error)
46
+ RaiseErrorMatcher.new(*expected_error)
27
47
  end
28
48
 
29
49
  def change(*args, &block)
@@ -51,6 +71,10 @@ module Smartest
51
71
  def negated_failure_message
52
72
  "expected #{@actual.inspect} not to eq #{@expected.inspect}"
53
73
  end
74
+
75
+ def description
76
+ "eq #{@expected.inspect}"
77
+ end
54
78
  end
55
79
 
56
80
  class IncludeMatcher
@@ -72,6 +96,10 @@ module Smartest
72
96
  def negated_failure_message
73
97
  "expected #{@actual.inspect} not to include #{@expected.inspect}"
74
98
  end
99
+
100
+ def description
101
+ "include #{@expected.inspect}"
102
+ end
75
103
  end
76
104
 
77
105
  class StartWithMatcher
@@ -94,6 +122,10 @@ module Smartest
94
122
  "expected #{@actual.inspect} not to start with #{expected_description}"
95
123
  end
96
124
 
125
+ def description
126
+ "start with #{expected_description}"
127
+ end
128
+
97
129
  private
98
130
 
99
131
  def expected_description
@@ -123,6 +155,10 @@ module Smartest
123
155
  "expected #{@actual.inspect} not to end with #{expected_description}"
124
156
  end
125
157
 
158
+ def description
159
+ "end with #{expected_description}"
160
+ end
161
+
126
162
  private
127
163
 
128
164
  def expected_description
@@ -132,6 +168,41 @@ module Smartest
132
168
  end
133
169
  end
134
170
 
171
+ class BeAKindOfMatcher
172
+ def initialize(expected_class)
173
+ @expected_class = expected_class
174
+ end
175
+
176
+ def matches?(actual)
177
+ @actual = actual
178
+ actual.is_a?(@expected_class)
179
+ rescue TypeError
180
+ false
181
+ end
182
+
183
+ def failure_message
184
+ "expected #{@actual.inspect} to be a kind of #{expected_description}, but was #{actual_class_description}"
185
+ end
186
+
187
+ def negated_failure_message
188
+ "expected #{@actual.inspect} not to be a kind of #{expected_description}, but was #{actual_class_description}"
189
+ end
190
+
191
+ def description
192
+ "be a kind of #{expected_description}"
193
+ end
194
+
195
+ private
196
+
197
+ def expected_description
198
+ @expected_class.to_s
199
+ end
200
+
201
+ def actual_class_description
202
+ @actual.class.to_s
203
+ end
204
+ end
205
+
135
206
  class BeNilMatcher
136
207
  def matches?(actual)
137
208
  @actual = actual
@@ -145,11 +216,164 @@ module Smartest
145
216
  def negated_failure_message
146
217
  "expected #{@actual.inspect} not to be nil"
147
218
  end
219
+
220
+ def description
221
+ "be nil"
222
+ end
223
+ end
224
+
225
+ class MatchMatcher
226
+ def initialize(regexp)
227
+ @regexp = regexp
228
+ end
229
+
230
+ def matches?(actual)
231
+ @actual = actual
232
+ @regexp.match?(actual)
233
+ rescue NoMethodError, TypeError
234
+ false
235
+ end
236
+
237
+ def failure_message
238
+ "expected #{@actual.inspect} to match #{@regexp.inspect}"
239
+ end
240
+
241
+ def negated_failure_message
242
+ "expected #{@actual.inspect} not to match #{@regexp.inspect}"
243
+ end
244
+
245
+ def description
246
+ "match #{@regexp.inspect}"
247
+ end
248
+ end
249
+
250
+ class ContainExactlyMatcher
251
+ def initialize(expected_items, matcher_name:)
252
+ @expected_items = expected_items
253
+ @matcher_name = matcher_name
254
+ reset_result
255
+ end
256
+
257
+ def matches?(actual)
258
+ @actual = actual
259
+ reset_result
260
+ return false unless actual_items?
261
+
262
+ match_items
263
+ @missing_items.empty? && @extra_items.empty?
264
+ end
265
+
266
+ def failure_message
267
+ details = failure_details
268
+ message = "expected #{@actual.inspect} to #{@matcher_name} #{format_expected_items(@expected_items)}"
269
+ details.empty? ? message : "#{message}; #{details.join('; ')}"
270
+ end
271
+
272
+ def negated_failure_message
273
+ "expected #{@actual.inspect} not to #{@matcher_name} #{format_expected_items(@expected_items)}"
274
+ end
275
+
276
+ def description
277
+ "#{@matcher_name} #{format_expected_items(@expected_items)}"
278
+ end
279
+
280
+ private
281
+
282
+ def reset_result
283
+ @actual_items = nil
284
+ @missing_items = @expected_items.dup
285
+ @extra_items = []
286
+ end
287
+
288
+ def actual_items?
289
+ return false unless @actual.respond_to?(:to_a)
290
+
291
+ @actual_items = @actual.to_a
292
+ true
293
+ end
294
+
295
+ def match_items
296
+ adjacency = build_adjacency
297
+ actual_matches = Array.new(@actual_items.length)
298
+ expected_order(adjacency).each do |expected_index|
299
+ assign_expected_item(expected_index, adjacency, actual_matches, [])
300
+ end
301
+
302
+ matched_expected_indexes = actual_matches.compact
303
+ @missing_items = []
304
+ @expected_items.each_with_index do |item, index|
305
+ @missing_items << item unless matched_expected_indexes.include?(index)
306
+ end
307
+ @extra_items = []
308
+ @actual_items.each_with_index do |item, index|
309
+ @extra_items << item if actual_matches[index].nil?
310
+ end
311
+ end
312
+
313
+ def build_adjacency
314
+ @expected_items.map do |expected_item|
315
+ @actual_items.each_index.select do |actual_index|
316
+ expected_item_matches_actual_item?(expected_item, @actual_items[actual_index])
317
+ end
318
+ end
319
+ end
320
+
321
+ def expected_order(adjacency)
322
+ (0...@expected_items.length).sort_by { |index| [adjacency[index].length, index] }
323
+ end
324
+
325
+ def assign_expected_item(expected_index, adjacency, actual_matches, seen_actual_indexes)
326
+ adjacency[expected_index].each do |actual_index|
327
+ next if seen_actual_indexes.include?(actual_index)
328
+
329
+ seen_actual_indexes << actual_index
330
+ if actual_matches[actual_index].nil? ||
331
+ assign_expected_item(actual_matches[actual_index], adjacency, actual_matches, seen_actual_indexes)
332
+ actual_matches[actual_index] = expected_index
333
+ return true
334
+ end
335
+ end
336
+
337
+ false
338
+ end
339
+
340
+ def expected_item_matches_actual_item?(expected_item, actual_item)
341
+ if expected_item.respond_to?(:matches?)
342
+ expected_item.matches?(actual_item)
343
+ else
344
+ actual_item == expected_item
345
+ end
346
+ end
347
+
348
+ def failure_details
349
+ return ["actual did not provide items"] unless @actual_items
350
+
351
+ details = []
352
+ details << "missing: #{format_expected_items(@missing_items)}" unless @missing_items.empty?
353
+ details << "extra: #{format_actual_items(@extra_items)}" unless @extra_items.empty?
354
+ details
355
+ end
356
+
357
+ def format_expected_items(items)
358
+ "[#{items.map { |item| format_expected_item(item) }.join(', ')}]"
359
+ end
360
+
361
+ def format_actual_items(items)
362
+ "[#{items.map(&:inspect).join(', ')}]"
363
+ end
364
+
365
+ def format_expected_item(item)
366
+ return item.description if item.respond_to?(:description)
367
+
368
+ item.inspect
369
+ end
148
370
  end
149
371
 
150
372
  class RaiseErrorMatcher
151
- def initialize(expected_error)
152
- @expected_error = expected_error
373
+ def initialize(*expected_error)
374
+ @expected_type = expected_type_for(expected_error)
375
+ @expected_error_class = expected_error.find { |item| error_class?(item) }
376
+ @expected_message_regexp = expected_error.find { |item| item.is_a?(Regexp) }
153
377
  @actual_error = nil
154
378
  @callable = true
155
379
  end
@@ -165,18 +389,60 @@ module Smartest
165
389
  raise if Smartest.fatal_exception?(error)
166
390
 
167
391
  @actual_error = error
168
- error.is_a?(@expected_error)
392
+ expected_error_matches?(error)
169
393
  end
170
394
 
171
395
  def failure_message
172
- return "expected a block to raise #{@expected_error}" unless @callable
173
- return "expected block to raise #{@expected_error}, but nothing was raised" unless @actual_error
396
+ return "expected a block to raise #{expected_description}" unless @callable
397
+ return "expected block to raise #{expected_description}, but nothing was raised" unless @actual_error
174
398
 
175
- "expected block to raise #{@expected_error}, but raised #{@actual_error.class}: #{@actual_error.message}"
399
+ "expected block to raise #{expected_description}, but raised #{actual_error_description}"
176
400
  end
177
401
 
178
402
  def negated_failure_message
179
- "expected block not to raise #{@expected_error}, but raised #{@actual_error.class}: #{@actual_error.message}"
403
+ "expected block not to raise #{expected_description}, but raised #{actual_error_description}"
404
+ end
405
+
406
+ private
407
+
408
+ def expected_type_for(expected_error)
409
+ return :class if expected_error.length == 1 && error_class?(expected_error.first)
410
+ return :message_regexp if expected_error.length == 1 && expected_error.first.is_a?(Regexp)
411
+ return :class_and_message_regexp if expected_error.length == 2 &&
412
+ error_class?(expected_error[0]) &&
413
+ expected_error[1].is_a?(Regexp)
414
+
415
+ raise ArgumentError, "raise_error supports an error class, message regexp, or error class and message regexp"
416
+ end
417
+
418
+ def error_class?(value)
419
+ value.is_a?(Class) && value <= Exception
420
+ end
421
+
422
+ def expected_error_matches?(error)
423
+ case @expected_type
424
+ when :class
425
+ error.is_a?(@expected_error_class)
426
+ when :message_regexp
427
+ @expected_message_regexp.match?(error.message)
428
+ when :class_and_message_regexp
429
+ error.is_a?(@expected_error_class) && @expected_message_regexp.match?(error.message)
430
+ end
431
+ end
432
+
433
+ def expected_description
434
+ case @expected_type
435
+ when :class
436
+ @expected_error_class.to_s
437
+ when :message_regexp
438
+ "error with message matching #{@expected_message_regexp.inspect}"
439
+ when :class_and_message_regexp
440
+ "#{@expected_error_class} with message matching #{@expected_message_regexp.inspect}"
441
+ end
442
+ end
443
+
444
+ def actual_error_description
445
+ "#{@actual_error.class}: #{@actual_error.message}"
180
446
  end
181
447
  end
182
448
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Smartest
4
- VERSION = "0.2.0.alpha3"
4
+ VERSION = "0.2.0.alpha4"
5
5
  end
@@ -48,6 +48,15 @@ class SelfTestRegisteredFixture < Smartest::Fixture
48
48
  end
49
49
  end
50
50
 
51
+ class SelfTestBaseType; end
52
+ class SelfTestChildType < SelfTestBaseType; end
53
+
54
+ module SelfTestMarkerType; end
55
+
56
+ class SelfTestMarkedType
57
+ include SelfTestMarkerType
58
+ end
59
+
51
60
  around_suite do |suite|
52
61
  use_fixture SelfTestRegisteredFixture
53
62
  suite.run
@@ -181,9 +190,25 @@ test("supports basic matchers") do
181
190
  expect("https://example.test").not_to start_with("about:")
182
191
  expect("report.txt").not_to end_with(".png")
183
192
  expect(Object.new).not_to start_with("prefix")
193
+ expect(SelfTestChildType.new).to be_a(SelfTestBaseType)
194
+ expect(SelfTestMarkedType.new).to be_an(SelfTestMarkerType)
184
195
  expect(nil).to be_nil
185
196
  expect("value").not_to be_nil
197
+ expect("https://example.test").to match(%r{\Ahttps://})
198
+ expect("about:blank").not_to match(%r{\Ahttps://})
199
+ expect(%w[request close request]).to contain_exactly("request", "request", "close")
200
+ expect(%i[request close open]).to match_array(%i[open request close])
201
+ expect(["foo", 42]).to contain_exactly(match(/foo/), eq(42))
202
+ expect(["ab", "ac"]).to contain_exactly(match(/a/), "ab")
203
+ expect([nil, false]).to contain_exactly(false, nil)
204
+ expect([:request]).not_to contain_exactly(:request, :request)
186
205
  expect { raise ArgumentError, "bad" }.to raise_error(ArgumentError)
206
+ expect { raise RuntimeError, "request timed out" }.to raise_error(/timed out/)
207
+ expect { raise ArgumentError, "bad input" }.to raise_error(ArgumentError, /bad/)
208
+ expect { raise ArgumentError, "bad" }.not_to raise_error(RuntimeError)
209
+ expect { raise ArgumentError, "bad" }.not_to raise_error(/timed out/)
210
+ expect { raise ArgumentError, "bad" }.not_to raise_error(ArgumentError, /timed out/)
211
+ expect { :ok }.not_to raise_error(/timed out/)
187
212
  end
188
213
  )
189
214
  )
@@ -193,6 +218,166 @@ test("supports basic matchers") do
193
218
  expect(status).to eq(0)
194
219
  end
195
220
 
221
+ test("reports be_a and match matcher failures") do
222
+ suite = Smartest::Suite.new
223
+ suite.tests.add(
224
+ SmartestSelfTest.test_case(
225
+ "bad type",
226
+ proc { expect(nil).to be_a(String) }
227
+ )
228
+ )
229
+ suite.tests.add(
230
+ SmartestSelfTest.test_case(
231
+ "bad negated type",
232
+ proc { expect(SelfTestChildType.new).not_to be_an(SelfTestBaseType) }
233
+ )
234
+ )
235
+ suite.tests.add(
236
+ SmartestSelfTest.test_case(
237
+ "bad regex",
238
+ proc { expect("about:blank").to match(%r{\Ahttps://}) }
239
+ )
240
+ )
241
+ suite.tests.add(
242
+ SmartestSelfTest.test_case(
243
+ "bad negated regex",
244
+ proc { expect("https://example.test").not_to match(%r{\Ahttps://}) }
245
+ )
246
+ )
247
+
248
+ status, output = SmartestSelfTest.run_suite(suite)
249
+
250
+ expect(status).to eq(1)
251
+ expect(output).to include("expected nil to be a kind of String, but was NilClass")
252
+ expect(output).to include("not to be a kind of SelfTestBaseType, but was SelfTestChildType")
253
+ expect(output).to include('expected "about:blank" to match /\\Ahttps:\\/\\//')
254
+ expect(output).to include('expected "https://example.test" not to match /\\Ahttps:\\/\\//')
255
+ end
256
+
257
+ test("reports contain_exactly and match_array matcher failures") do
258
+ suite = Smartest::Suite.new
259
+ suite.tests.add(
260
+ SmartestSelfTest.test_case(
261
+ "bad collection",
262
+ proc { expect(["foo", "baz", 2]).to contain_exactly(match(/foo/), eq(42), "bar") }
263
+ )
264
+ )
265
+ suite.tests.add(
266
+ SmartestSelfTest.test_case(
267
+ "bad duplicate count",
268
+ proc { expect([:request]).to match_array(%i[request request]) }
269
+ )
270
+ )
271
+ suite.tests.add(
272
+ SmartestSelfTest.test_case(
273
+ "bad negated collection",
274
+ proc { expect(%w[b a]).not_to contain_exactly("a", "b") }
275
+ )
276
+ )
277
+
278
+ status, output = SmartestSelfTest.run_suite(suite)
279
+
280
+ expect(status).to eq(1)
281
+ expect(output).to include('expected ["foo", "baz", 2] to contain exactly [match /foo/, eq 42, "bar"]')
282
+ expect(output).to include('missing: [eq 42, "bar"]')
283
+ expect(output).to include('extra: ["baz", 2]')
284
+ expect(output).to include("expected [:request] to match array [:request, :request]")
285
+ expect(output).to include("missing: [:request]")
286
+ expect(output).to include('expected ["b", "a"] not to contain exactly ["a", "b"]')
287
+ end
288
+
289
+ test("reports raise_error matcher failures") do
290
+ suite = Smartest::Suite.new
291
+ suite.tests.add(
292
+ SmartestSelfTest.test_case(
293
+ "nothing raised",
294
+ proc { expect { :ok }.to raise_error(/timeout/) }
295
+ )
296
+ )
297
+ suite.tests.add(
298
+ SmartestSelfTest.test_case(
299
+ "bad message",
300
+ proc { expect { raise RuntimeError, "permission denied" }.to raise_error(/timeout/) }
301
+ )
302
+ )
303
+ suite.tests.add(
304
+ SmartestSelfTest.test_case(
305
+ "bad negated message",
306
+ proc { expect { raise RuntimeError, "timeout after 1s" }.not_to raise_error(/timeout/) }
307
+ )
308
+ )
309
+ suite.tests.add(
310
+ SmartestSelfTest.test_case(
311
+ "bad class and message class",
312
+ proc { expect { raise RuntimeError, "timeout after 1s" }.to raise_error(ArgumentError, /timeout/) }
313
+ )
314
+ )
315
+ suite.tests.add(
316
+ SmartestSelfTest.test_case(
317
+ "bad class and message message",
318
+ proc { expect { raise ArgumentError, "permission denied" }.to raise_error(ArgumentError, /timeout/) }
319
+ )
320
+ )
321
+ suite.tests.add(
322
+ SmartestSelfTest.test_case(
323
+ "bad negated class and message",
324
+ proc { expect { raise ArgumentError, "timeout after 1s" }.not_to raise_error(ArgumentError, /timeout/) }
325
+ )
326
+ )
327
+
328
+ status, output = SmartestSelfTest.run_suite(suite)
329
+
330
+ expect(status).to eq(1)
331
+ expect(output).to include("expected block to raise error with message matching /timeout/, but nothing was raised")
332
+ expect(output).to include(
333
+ "expected block to raise error with message matching /timeout/, but raised RuntimeError: permission denied"
334
+ )
335
+ expect(output).to include(
336
+ "expected block not to raise error with message matching /timeout/, but raised RuntimeError: timeout after 1s"
337
+ )
338
+ expect(output).to include(
339
+ "expected block to raise ArgumentError with message matching /timeout/, but raised RuntimeError: timeout after 1s"
340
+ )
341
+ expect(output).to include(
342
+ "expected block to raise ArgumentError with message matching /timeout/, but raised ArgumentError: permission denied"
343
+ )
344
+ expect(output).to include(
345
+ "expected block not to raise ArgumentError with message matching /timeout/, but raised ArgumentError: timeout after 1s"
346
+ )
347
+ end
348
+
349
+ test("rejects unsupported raise_error argument forms") do
350
+ error = SmartestSelfTest.capture_error(ArgumentError) do
351
+ raise_error
352
+ end
353
+
354
+ expect(error.message).to eq("raise_error supports an error class, message regexp, or error class and message regexp")
355
+
356
+ error = SmartestSelfTest.capture_error(ArgumentError) do
357
+ raise_error("timeout")
358
+ end
359
+
360
+ expect(error.message).to eq("raise_error supports an error class, message regexp, or error class and message regexp")
361
+
362
+ error = SmartestSelfTest.capture_error(ArgumentError) do
363
+ raise_error(String)
364
+ end
365
+
366
+ expect(error.message).to eq("raise_error supports an error class, message regexp, or error class and message regexp")
367
+
368
+ error = SmartestSelfTest.capture_error(ArgumentError) do
369
+ raise_error(RuntimeError, "timeout")
370
+ end
371
+
372
+ expect(error.message).to eq("raise_error supports an error class, message regexp, or error class and message regexp")
373
+
374
+ error = SmartestSelfTest.capture_error(ArgumentError) do
375
+ raise_error(/timeout/, RuntimeError)
376
+ end
377
+
378
+ expect(error.message).to eq("raise_error supports an error class, message regexp, or error class and message regexp")
379
+ end
380
+
196
381
  test("reports start_with and end_with matcher failures") do
197
382
  suite = Smartest::Suite.new
198
383
  suite.tests.add(
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.alpha3
4
+ version: 0.2.0.alpha4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Iwaki