minicrest 1.0.19 → 1.0.20

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.
data/USAGE.md ADDED
@@ -0,0 +1,670 @@
1
+ # Usage
2
+
3
+ ## Table of Contents
4
+
5
+ - [Basic Usage](#basic-usage)
6
+ - [Core Matchers](#core-matchers)
7
+ - [Value Equality](#value-equality)
8
+ - [Reference Equality](#reference-equality)
9
+ - [Negation](#negation)
10
+ - [Placeholder Matching](#placeholder-matching)
11
+ - [Type and Method Matchers](#type-and-method-matchers)
12
+ - [Value Matchers](#value-matchers)
13
+ - [String Matchers](#string-matchers)
14
+ - [Size and Emptiness Matchers](#size-and-emptiness-matchers)
15
+ - [Numeric Comparison Matchers](#numeric-comparison-matchers)
16
+ - [Collection Content Matchers](#collection-content-matchers)
17
+ - [Collection Item Matchers](#collection-item-matchers)
18
+ - [Membership Matcher](#membership-matcher)
19
+ - [Object Attribute Matcher](#object-attribute-matcher)
20
+ - [Error Assertions](#error-assertions)
21
+ - [Combining Matchers](#combining-matchers)
22
+ - [Collection Combinators](#collection-combinators)
23
+ - [Custom Matchers](#custom-matchers)
24
+ - [Parameterized Matchers](#parameterized-matchers)
25
+ - [Custom Matchers with Combinators](#custom-matchers-with-combinators)
26
+ - [Failure Messages](#failure-messages)
27
+ - [API Reference](#api-reference)
28
+
29
+ ## Basic Usage
30
+
31
+ Include `Minicrest::Assertions` in your test class:
32
+
33
+ ```ruby
34
+ require 'minicrest'
35
+
36
+ class MyTest < Minitest::Test
37
+ include Minicrest::Assertions
38
+
39
+ def test_basic_equality
40
+ assert_that(42).equals(42)
41
+ end
42
+ end
43
+ ```
44
+
45
+ ## Core Matchers
46
+
47
+ ### Value Equality
48
+
49
+ ```ruby
50
+ # Simple values
51
+ assert_that("hello").equals("hello")
52
+
53
+ # Arrays with deep comparison
54
+ assert_that([1, [2, 3]]).equals([1, [2, 3]])
55
+
56
+ # Hashes with deep comparison
57
+ assert_that({ user: { name: "Alice" } }).equals({ user: { name: "Alice" } })
58
+ ```
59
+
60
+ ### Reference Equality
61
+
62
+ Test that two variables point to the same object:
63
+
64
+ ```ruby
65
+ obj = Object.new
66
+ assert_that(obj).is(obj)
67
+ ```
68
+
69
+ ### Negation
70
+
71
+ ```ruby
72
+ assert_that(42).never(equals(0))
73
+ assert_that(nil).never(equals(false))
74
+
75
+ # Aliases for more natural flow
76
+ assert_that(42).is_not(0)
77
+ assert_that("hello").does_not(start_with("bye"))
78
+ ```
79
+
80
+ ### Placeholder Matching
81
+
82
+ Use `anything` when you don't care about a particular value:
83
+
84
+ ```ruby
85
+ assert_that(some_value).is(anything)
86
+ ```
87
+
88
+ Use `truthy` or `falsy` to match any truthy or falsy value in Ruby:
89
+
90
+ ```ruby
91
+ assert_that(some_value).is(truthy)
92
+ assert_that(some_value).is(anything)
93
+ ```
94
+
95
+ ## Type and Method Matchers
96
+
97
+ ### `is_a(type)` / `descends_from(type)`
98
+
99
+ Matches if the value is an instance of the expected type (including inheritance):
100
+
101
+ ```ruby
102
+ assert_that("hello").matches(is_a(String))
103
+ assert_that(42).matches(descends_from(Integer))
104
+ assert_that([]).matches(is_a(Enumerable)) # works with modules
105
+ ```
106
+
107
+ ### `instance_of(type)`
108
+
109
+ Matches if the value is an exact instance of the expected class (no inheritance):
110
+
111
+ ```ruby
112
+ assert_that("hello").matches(instance_of(String))
113
+ assert_that(42).never(instance_of(Numeric)) # Integer is a Numeric, but not exactly InstanceOf Numeric
114
+ ```
115
+
116
+ ### `responds_to(*methods)`
117
+
118
+ Matches if the value responds to all specified methods:
119
+
120
+ ```ruby
121
+ assert_that("hello").matches(responds_to(:upcase))
122
+ assert_that([]).matches(responds_to(:push, :pop))
123
+ ```
124
+
125
+ ## Value Matchers
126
+
127
+ ### `nil_value`
128
+
129
+ Matches if the value is `nil`:
130
+
131
+ ```ruby
132
+ assert_that(nil).matches(nil_value)
133
+ assert_that(42).never(nil_value)
134
+ ```
135
+
136
+ ### `truthy`
137
+
138
+ Matches if the value is considered true (anything except `nil` or `false`):
139
+
140
+ ```ruby
141
+ assert_that(true).matches(truthy)
142
+ assert_that(42).matches(truthy)
143
+ assert_that("hello").matches(truthy)
144
+ ```
145
+
146
+ ### `falsy`
147
+
148
+ Matches if the value is considered false (`nil` or `false`):
149
+
150
+ ```ruby
151
+ assert_that(false).matches(falsy)
152
+ assert_that(nil).matches(falsy)
153
+ ```
154
+
155
+ ## String Matchers
156
+
157
+ ### `starts_with(prefix)`
158
+
159
+ ```ruby
160
+ assert_that("hello world").matches(starts_with("hello"))
161
+ ```
162
+
163
+ ### `ends_with(suffix)`
164
+
165
+ ```ruby
166
+ assert_that("hello world").matches(ends_with("world"))
167
+ ```
168
+
169
+ ### `matches_pattern(regex)`
170
+
171
+ ```ruby
172
+ assert_that("hello123").matches(matches_pattern(/\d+/))
173
+ assert_that("test@example.com").matches(matches_pattern(/\A[\w.]+@[\w.]+\z/))
174
+ ```
175
+
176
+ ### `blank`
177
+
178
+ Matches empty or whitespace-only strings:
179
+
180
+ ```ruby
181
+ assert_that("").matches(blank)
182
+ assert_that(" ").matches(blank)
183
+ assert_that("\t\n").matches(blank)
184
+ ```
185
+
186
+ ## Size and Emptiness Matchers
187
+
188
+ ### `empty`
189
+
190
+ Matches empty strings, arrays, or hashes:
191
+
192
+ ```ruby
193
+ assert_that("").matches(empty)
194
+ assert_that([]).matches(empty)
195
+ assert_that({}).matches(empty)
196
+ ```
197
+
198
+ ### `has_size(expected)`
199
+
200
+ Matches values with a specific size:
201
+
202
+ ```ruby
203
+ assert_that("hello").matches(has_size(5))
204
+ assert_that([1, 2, 3]).matches(has_size(3))
205
+ assert_that({ a: 1, b: 2 }).matches(has_size(2))
206
+
207
+ # Can use matchers for flexible size checks
208
+ assert_that([1, 2, 3]).matches(has_size(is_greater_than(2)))
209
+ ```
210
+
211
+ ## Numeric Comparison Matchers
212
+
213
+ ### `is_greater_than(expected)`
214
+
215
+ ```ruby
216
+ assert_that(5).matches(is_greater_than(3))
217
+ ```
218
+
219
+ ### `is_greater_than_or_equal_to(expected)`
220
+
221
+ ```ruby
222
+ assert_that(5).matches(is_greater_than_or_equal_to(5))
223
+ assert_that(6).matches(is_greater_than_or_equal_to(5))
224
+ ```
225
+
226
+ ### `is_less_than(expected)`
227
+
228
+ ```ruby
229
+ assert_that(3).matches(is_less_than(5))
230
+ ```
231
+
232
+ ### `is_less_than_or_equal_to(expected)`
233
+
234
+ ```ruby
235
+ assert_that(5).matches(is_less_than_or_equal_to(5))
236
+ assert_that(4).matches(is_less_than_or_equal_to(5))
237
+ ```
238
+
239
+ ### `between(min, max, exclusive: false)`
240
+
241
+ Matches if the value is within the range:
242
+
243
+ ```ruby
244
+ assert_that(5).matches(between(1, 10))
245
+ assert_that(10).never(between(1, 10, exclusive: true))
246
+ ```
247
+
248
+ ### `is_close_to(expected, delta)`
249
+
250
+ Floating-point equality with tolerance:
251
+
252
+ ```ruby
253
+ assert_that(3.14159).matches(is_close_to(3.14, 0.01))
254
+ assert_that(10.0).matches(is_close_to(10.5, 0.5))
255
+ ```
256
+
257
+ ## Collection Content Matchers
258
+
259
+ ### `includes(*items)`
260
+
261
+ Matches if the value contains all specified items:
262
+
263
+ ```ruby
264
+ # Strings: contains substrings
265
+ assert_that("hello world").matches(includes("hello", "world"))
266
+
267
+ # Arrays: contains elements
268
+ assert_that([1, 2, 3, 4]).matches(includes(2, 4))
269
+
270
+ # Hashes: contains key-value pairs
271
+ assert_that({ a: 1, b: 2, c: 3 }).matches(includes(a: 1, c: 3))
272
+ ```
273
+
274
+ ### `has_key(*keys)`
275
+
276
+ Matches if the hash contains all specified keys:
277
+
278
+ ```ruby
279
+ assert_that({ a: 1, b: 2 }).matches(has_key(:a))
280
+ assert_that({ a: 1, b: 2 }).matches(has_key(:a, :b))
281
+ ```
282
+
283
+ ### `has_value(*values)`
284
+
285
+ Matches if the hash contains all specified values:
286
+
287
+ ```ruby
288
+ assert_that({ a: 1, b: 2 }).matches(has_value(1))
289
+ assert_that({ a: 1, b: 2 }).matches(has_value(1, 2))
290
+ ```
291
+
292
+ ### `contains(*items)`
293
+
294
+ Matches if the collection contains exactly the specified items in any order:
295
+
296
+ ```ruby
297
+ assert_that([3, 1, 2]).matches(contains(1, 2, 3))
298
+ assert_that({ b: 2, a: 1 }).matches(contains(a: 1, b: 2))
299
+ ```
300
+
301
+ ### `contains_exactly(*items)`
302
+
303
+ Matches if the array contains exactly the specified items in order:
304
+
305
+ ```ruby
306
+ assert_that([1, 2, 3]).matches(contains_exactly(1, 2, 3))
307
+ ```
308
+
309
+ ## Collection Item Matchers
310
+
311
+ ### `all_items(matcher)`
312
+
313
+ Matches if all items in the collection match:
314
+
315
+ ```ruby
316
+ assert_that([2, 4, 6]).matches(all_items(descends_from(Integer)))
317
+ assert_that([2, 4, 6]).matches(all_items(is_greater_than(0)))
318
+ ```
319
+
320
+ ### `some_items(matcher)`
321
+
322
+ Matches if at least one item matches:
323
+
324
+ ```ruby
325
+ assert_that([1, "two", 3]).matches(some_items(descends_from(String)))
326
+ ```
327
+
328
+ ### `no_items(matcher)`
329
+
330
+ Matches if no items match:
331
+
332
+ ```ruby
333
+ assert_that([1, 2, 3]).matches(no_items(descends_from(String)))
334
+ ```
335
+
336
+ ### `all_entries(matcher)` / `some_entry(matcher)` / `no_entry(matcher)`
337
+
338
+ Similar to item matchers, but specifically for hash entries (key-value pairs):
339
+
340
+ ```ruby
341
+ # all_entries expects a matcher that works with [key, value] arrays
342
+ assert_that({ a: 1, b: 2 }).matches(all_entries(includes(:a, :b) | includes(1, 2)))
343
+
344
+ # You can also use a Proc for more complex entry matching
345
+ assert_that({ a: 1, b: 2 }).matches(some_entry(->(entry) { entry[1] > 1 }))
346
+ ```
347
+
348
+ ## Membership Matcher
349
+
350
+ ### `is_in(collection)`
351
+
352
+ Matches if the value is present in the collection:
353
+
354
+ ```ruby
355
+ assert_that(2).matches(is_in([1, 2, 3]))
356
+ assert_that(:a).matches(is_in({ a: 1, b: 2 })) # checks keys
357
+ assert_that("el").matches(is_in("hello")) # substring
358
+ assert_that(5).matches(is_in(1..10)) # ranges
359
+ ```
360
+
361
+ ## Object Attribute Matcher
362
+
363
+ ### `has_attribute(name, matcher = nil)`
364
+
365
+ Matches if the object has the attribute, optionally checking its value:
366
+
367
+ ```ruby
368
+ User = Struct.new(:name, :age)
369
+
370
+ user = User.new("Alice", 30)
371
+
372
+ assert_that(user).matches(has_attribute(:name))
373
+ assert_that(user).matches(has_attribute(:name, equals("Alice")))
374
+ assert_that(user).matches(has_attribute(:age, is_greater_than(18)))
375
+
376
+ # Also works with hashes
377
+ assert_that({ name: "Bob" }).matches(has_attribute(:name, equals("Bob")))
378
+ ```
379
+
380
+ ## Error Assertions
381
+
382
+ ### `raises_error`
383
+
384
+ Assert that a block raises an error:
385
+
386
+ ```ruby
387
+ # Any error
388
+ assert_that { raise "boom" }.raises_error
389
+
390
+ # Specific error class
391
+ assert_that { raise ArgumentError, "bad" }.raises_error(ArgumentError)
392
+
393
+ # Error class with message matcher
394
+ assert_that { raise ArgumentError, "bad input" }.raises_error(ArgumentError, includes("bad"))
395
+ assert_that { raise ArgumentError, "code: 123" }.raises_error(ArgumentError, matches_pattern(/\d+/))
396
+ ```
397
+
398
+ ### `raises_nothing`
399
+
400
+ Assert that a block does not raise:
401
+
402
+ ```ruby
403
+ assert_that { safe_operation }.raises_nothing
404
+ ```
405
+
406
+ ## Combining Matchers
407
+
408
+ Use `|` for OR and `&` for AND:
409
+
410
+ ```ruby
411
+ # Either/or
412
+ assert_that(status).matches(equals(:success) | equals(:pending))
413
+
414
+ # Both conditions
415
+ assert_that(value).matches(is_greater_than(0) & is_less_than(100))
416
+
417
+ # Complex combinations
418
+ assert_that(result).matches(
419
+ (equals(1) | equals(2)) & never(equals(nil))
420
+ )
421
+ ```
422
+
423
+ ### Collection Combinators
424
+
425
+ ```ruby
426
+ # All matchers must pass
427
+ assert_that(5).matches(all_of(is_greater_than(0), is_less_than(10)))
428
+
429
+ # No matchers should pass
430
+ assert_that(10).matches(none_of(equals(5), equals(6)))
431
+
432
+ # At least one matcher must pass
433
+ assert_that(5).matches(some_of(equals(5), equals(999)))
434
+ ```
435
+
436
+ ## Custom Matchers
437
+
438
+ Create your own matchers by subclassing `Minicrest::Matcher`:
439
+
440
+ ```ruby
441
+ class BePositive < Minicrest::Matcher
442
+ def matches?(actual)
443
+ actual.is_a?(Numeric) && actual > 0
444
+ end
445
+
446
+ def description
447
+ "be positive"
448
+ end
449
+
450
+ def failure_message(actual)
451
+ "expected #{actual.inspect} to be a positive number"
452
+ end
453
+ end
454
+
455
+ # Register the matcher
456
+ Minicrest.register_matcher(:be_positive) { BePositive.new }
457
+
458
+ # Use in tests
459
+ assert_that(5).matches(be_positive)
460
+ ```
461
+
462
+ ### Parameterized Matchers
463
+
464
+ Matchers can accept arguments:
465
+
466
+ ```ruby
467
+ class BeDivisibleBy < Minicrest::Matcher
468
+ def initialize(divisor)
469
+ super()
470
+ @divisor = divisor
471
+ end
472
+
473
+ def matches?(actual)
474
+ actual % @divisor == 0
475
+ end
476
+
477
+ def description
478
+ "be divisible by #{@divisor}"
479
+ end
480
+ end
481
+
482
+ Minicrest.register_matcher(:be_divisible_by) { |n| BeDivisibleBy.new(n) }
483
+
484
+ # Use in tests
485
+ assert_that(10).matches(be_divisible_by(5))
486
+ ```
487
+
488
+ ### Custom Matchers with Combinators
489
+
490
+ Registered matchers automatically work with all combinators:
491
+
492
+ ```ruby
493
+ # With AND/OR operators
494
+ assert_that(10).matches(be_divisible_by(5) & be_divisible_by(2))
495
+ assert_that(10).matches(be_divisible_by(3) | be_divisible_by(5))
496
+
497
+ # With never()
498
+ assert_that(7).never(be_divisible_by(2))
499
+
500
+ # With all_of, some_of, none_of
501
+ assert_that(10).matches(all_of(be_positive, be_divisible_by(5)))
502
+ ```
503
+
504
+ ## Failure Messages
505
+
506
+ Minicrest provides detailed failure messages with diffs:
507
+
508
+ ```ruby
509
+ assert_that({ name: "Bob" }).equals({ name: "Alice" })
510
+ ```
511
+
512
+ Output:
513
+
514
+ ```
515
+ expected {:name=>"Bob"}
516
+ to equal {:name=>"Alice"}
517
+
518
+ Diff:
519
+ key :name:
520
+ expected: "Alice"
521
+ actual: "Bob"
522
+ ```
523
+
524
+ Array diffs show the index:
525
+
526
+ ```ruby
527
+ assert_that([1, 2, 4]).equals([1, 2, 3])
528
+ ```
529
+
530
+ Output:
531
+
532
+ ```
533
+ expected [1, 2, 4]
534
+ to equal [1, 2, 3]
535
+
536
+ Diff:
537
+ [2]:
538
+ expected: 3
539
+ actual: 4
540
+ ```
541
+
542
+ String diffs show the first difference:
543
+
544
+ ```ruby
545
+ assert_that("hello").equals("hallo")
546
+ ```
547
+
548
+ Output:
549
+
550
+ ```
551
+ expected "hello"
552
+ to equal "hallo"
553
+
554
+ Diff:
555
+ at index 1:
556
+ expected: "a"
557
+ actual: "e"
558
+ ```
559
+
560
+ ## API Reference
561
+
562
+ ### Assertions Module - Core
563
+
564
+ | Method | Description |
565
+ |--------|-------------|
566
+ | `assert_that(actual, message = nil)` | Entry point for value assertions |
567
+ | `assert_that { block }` | Entry point for block assertions |
568
+ | `equals(expected)` | Value equality matcher |
569
+ | `is(expected)` | Reference equality matcher (supports matchers) |
570
+ | `anything` | Matches any value |
571
+ | `never(matcher)` | Negates a matcher (aliases: `is_not`, `does_not`) |
572
+
573
+ ### Assertions Module - Type & Method
574
+
575
+ | Method | Description |
576
+ |--------|-------------|
577
+ | `is_a(type)` | Type/class matcher (alias of `descends_from`) |
578
+ | `descends_from(type)` | Type/class matcher |
579
+ | `instance_of(type)` | Exact class matcher |
580
+ | `responds_to(*methods)` | Method presence matcher |
581
+
582
+ ### Assertions Module - Values
583
+
584
+ | Method | Description |
585
+ |--------|-------------|
586
+ | `nil_value` | Matches `nil` |
587
+ | `truthy` | Matches non-nil, non-false values |
588
+ | `falsy` | Matches `nil` or `false` |
589
+
590
+ ### Assertions Module - Strings
591
+
592
+ | Method | Description |
593
+ |--------|-------------|
594
+ | `starts_with(prefix)` | String prefix matcher |
595
+ | `ends_with(suffix)` | String suffix matcher |
596
+ | `matches_pattern(regex)` | Regex pattern matcher |
597
+ | `blank` | Blank string matcher |
598
+
599
+ ### Assertions Module - Size & Emptiness
600
+
601
+ | Method | Description |
602
+ |--------|-------------|
603
+ | `empty` | Empty collection matcher |
604
+ | `has_size(expected)` | Size/length matcher |
605
+
606
+ ### Assertions Module - Numeric
607
+
608
+ | Method | Description |
609
+ |--------|-------------|
610
+ | `is_greater_than(n)` | Greater than comparison |
611
+ | `is_greater_than_or_equal_to(n)` | Greater than or equal comparison |
612
+ | `is_less_than(n)` | Less than comparison |
613
+ | `is_less_than_or_equal_to(n)` | Less than or equal comparison |
614
+ | `between(min, max, exclusive: false)` | Range comparison |
615
+ | `is_close_to(n, delta)` | Floating-point tolerance |
616
+
617
+ ### Assertions Module - Collections
618
+
619
+ | Method | Description |
620
+ |--------|-------------|
621
+ | `includes(*items)` | Partial containment |
622
+ | `has_key(*keys)` | Hash key presence |
623
+ | `has_value(*values)` | Hash value presence |
624
+ | `contains(*items)` | Exact items, any order |
625
+ | `contains_exactly(*items)` | Exact items, exact order |
626
+ | `all_items(matcher)` | All items match |
627
+ | `some_items(matcher)` | At least one matches |
628
+ | `no_items(matcher)` | No items match |
629
+ | `all_entries(matcher)` | All hash entries match |
630
+ | `some_entry(matcher)` | At least one entry matches |
631
+ | `no_entry(matcher)` | No entries match |
632
+ | `is_in(collection)` | Membership check |
633
+
634
+ ### Assertions Module - Objects
635
+
636
+ | Method | Description |
637
+ |--------|-------------|
638
+ | `has_attribute(name, matcher = nil)` | Object attribute matcher |
639
+
640
+ ### Assertions Module - Combinators
641
+
642
+ | Method | Description |
643
+ |--------|-------------|
644
+ | `all_of(*matchers)` | All matchers must match |
645
+ | `none_of(*matchers)` | No matcher should match |
646
+ | `some_of(*matchers)` | At least one must match |
647
+
648
+ ### Asserter Methods
649
+
650
+ | Method | Description |
651
+ |--------|-------------|
652
+ | `.equals(expected)` | Assert value equality |
653
+ | `.is(expected)` | Assert reference equality (supports matchers) |
654
+ | `.never(matcher)` | Assert negation (aliases: `is_not`, `does_not`) |
655
+ | `.matches(matcher)` | Use any matcher |
656
+ | `.raises_error(class = nil, message_matcher = nil)` | Assert block raises |
657
+ | `.raises_nothing` | Assert block doesn't raise |
658
+
659
+ ### Matcher Operators
660
+
661
+ | Operator | Description |
662
+ |----------|-------------|
663
+ | `&` | AND - both matchers must succeed |
664
+ | `\|` | OR - at least one matcher must succeed |
665
+
666
+ ### Module Methods
667
+
668
+ | Method | Description |
669
+ |--------|-------------|
670
+ | `Minicrest.register_matcher(name, &block)` | Register custom matcher |
@@ -83,4 +83,65 @@ module Minicrest
83
83
  "expected #{actual.inspect} not to be an instance of #{@expected_type}, but it was"
84
84
  end
85
85
  end
86
+
87
+ # Matcher that checks if a value is an instance of a given type.
88
+ #
89
+ # Uses Ruby's `is_a?` method which checks class hierarchy and module inclusion.
90
+ #
91
+ # @example Basic usage
92
+ # descends_from(String).matches?("hello") # => true
93
+ # descends_from(Integer).matches?(42) # => true
94
+ # descends_from(Enumerable).matches?([]) # => true (module inclusion)
95
+ #
96
+ # @example With inheritance
97
+ # descends_from(Exception).matches?(StandardError.new) # => true (subclass)
98
+ # @see InstanceOf
99
+ class DescendsFrom < Matcher
100
+ # Creates a new type matcher.
101
+ #
102
+ # @param expected_type [Class, Module] the expected type
103
+ def initialize(expected_type)
104
+ super()
105
+ @expected_type = expected_type
106
+ end
107
+
108
+ # Checks if actual is an instance of the expected type.
109
+ #
110
+ # @param actual [Object] the value to check
111
+ # @return [Boolean] true if actual.is_a?(expected_type)
112
+ def matches?(actual)
113
+ actual.is_a?(@expected_type)
114
+ end
115
+
116
+ # Returns a description of what this matcher expects.
117
+ #
118
+ # @return [String] description of expected type
119
+ def description
120
+ "an instance of #{@expected_type}"
121
+ end
122
+
123
+ # Returns the failure message when the match fails.
124
+ #
125
+ # @param actual [Object] the value that was checked
126
+ # @return [String] message showing expected vs actual type
127
+ def failure_message(actual)
128
+ <<~MSG.chomp
129
+ expected #{actual.inspect}
130
+ to be an instance of #{@expected_type}
131
+ but was #{actual.class}
132
+ MSG
133
+ end
134
+
135
+ # Returns the failure message when a negated match fails.
136
+ #
137
+ # @param actual [Object] the value that was checked
138
+ # @return [String] message indicating unexpected type match
139
+ def negated_failure_message(actual)
140
+ <<~MSG.chomp
141
+ expected #{actual.inspect}
142
+ not to be an instance of #{@expected_type}
143
+ but it is
144
+ MSG
145
+ end
146
+ end
86
147
  end