assert_canonical_duck_type_matchMinitest alias forassert_canonical_interface_matchimplement_canonical_duck_typeRSpec alias forimplement_canonical_interfacecanonical:keyword support in the shared example (it_behaves_like "an interface")
CanonicalInterfaceChecker: compares every class in a list against a single canonical reference rather than in consecutive pairs; all failures are aggregated into one resultassert_canonical_interface_matchMinitest assertionimplement_canonical_interfaceRSpec matcherInterfaceSetup: extracted shared checker initialization (argument validation, object resolution, name inference) fromBulkInterfaceCheckerandCanonicalInterfaceCheckerResultFormatting: extracted shared result formatting logic
- Improved test accuracy and coverage for
BulkInterfaceCheckerandInterfaceChecker
name:option: includes the interface name in failure messages (e.g.compatible "Linkable" interfaces)namespace:option: resolves a module's constants as the list of objects to compare; infers the interface name from the module name whenname:is not given- Strict mode now notes itself in the failure message:
(strict mode: positional argument names must match) BulkInterfaceCheckerandInterfaceCheckerraisePrivateMethodErrorwhen a private method is specified inmethods:
partial_interface_methods:renamed tomethods:acrossBulkInterfaceChecker,InterfaceChecker,assert_interfaces_match, andhave_matching_interfaces(breaking change)- RSpec matcher now accepts a module as the subject via
expect(namespace: MyModule).to have_matching_interfaces - RSpec shared example now accepts
namespace:as a keyword argument
- Numbered block parameters (
_1) replaced with named ones to avoidStyle/ItBlockParameterlint failures on Ruby 3.4
- Strict mode (
strict: true) for interface comparison: positional argument names must match exactly. Available onassert_interfaces_match,have_matching_interfaces, and the RSpec shared example. Keyword argument names always matter regardless of this setting. assert_duck_types_matchas an alias forassert_interfaces_matchhave_matching_duck_typesas an alias forhave_matching_interfacesBulkInterfaceCheckernow raisesArgumentErrorwhen fewer than two classes are given
- RSpec shared example was broken on Ruby 3.1 due to proc argument destructuring differences between Ruby versions
ParamsNormalizerrefactored into a factory (ParamsNormalizer.for(strict:)) with extracted modules:KeywordNormalizer,SequentialNormalizer,DefaultParamsNormalizer,StrictParamsNormalizer, andNullParamsNormalizer— all consolidated in a single file- CI now runs against Ruby 3.1 (minimum) and 3.4 (latest)
- Move type validation and
TYPESconstant toMethodInspector - Refactor
ParamsNormalizer: extractSEQUENTIAL_TYPESconstant andsequentialize_params, reorder methods for natural reading order - Introduce
NullParamsNormalizeras an explicit null object, replacing an implicit identity lambda - Move
MethodInspector,ParamsNormalizer, andNullParamsNormalizerto theDuckTypernamespace; nestClassMethodInspectorandInstanceMethodInspectorinsideMethodInspector - Use
assocto look up method params injoin_signature - Inline
inspectorlocals throughoutInterfaceChecker - Mark
ParamsNormalizer,NullParamsNormalizer, andMethodInspectoras internal (:nodoc:)
ParamsNormalizertest suite- Test that each differing method appears only once in
failure_message - Test that
assert_interfaces_matchpasses for matching pairs even when another class in the list mismatches
- CHANGELOG
- Add
rake citask combining StandardRB, Minitest, and RSpec - Add
check_lockfiletask to catchGemfile.lockdrift - Simplify CI config to a single
rake cistep - Remove empty RBS signature file
- Add MIT license to gemspec
- Keyword argument order is now ignored when comparing interfaces —
m(a:, b:)andm(b:, a:)are treated as equivalent - Support for
:nokeyparameter type (def foo(**nil)) failure_messagenow returnsnilwhen interfaces match- README Limitations section
- Self-referential test verifying
ClassMethodInspectorandInstanceMethodInspectorshare compatible interfaces
- Improved failure message: "implement compatible interfaces" / "method signatures differ"
- Extract
calculate_diffprivate method
- README improvements: Minitest section moved before RSpec, partial interface wording clarified
- Renamed
assert_interface_matchestoassert_interfaces_match(breaking change)
- Initial release