Skip to content

Add canonical interface checker#2

Merged
thiagoa merged 2 commits into
mainfrom
add-canonical-interface-checker
May 15, 2026
Merged

Add canonical interface checker#2
thiagoa merged 2 commits into
mainfrom
add-canonical-interface-checker

Conversation

@thiagoa
Copy link
Copy Markdown
Contributor

@thiagoa thiagoa commented Apr 24, 2026

Pairwise comparison verifies that every adjacent pair of classes in a list agree with each other, which works well when all classes are peers with no single authoritative definition. Canonical interface comparison takes a different approach: one class is designated as the reference, and every other class is checked against it directly. This is useful when the interface already has a clear owner — an abstract base, a well-established implementation, or a purpose-built interface class — and you want to confirm that all other implementations conform to that definition. Because all comparisons share the same right-hand side, failures from multiple classes are aggregated into a single result, making it easier to see the full picture at a glance.

  • Adds CanonicalInterfaceChecker, which compares every class in a list against a single canonical reference rather than in consecutive pairs. All failures are aggregated into one result, so a single assertion reports every non-conforming class at once.

  • Exposes assert_canonical_interface_match(canonical, objects, **opts) in the Minitest integration and implement_canonical_interface(canonical, **opts) in the RSpec integration. All existing options (type:, methods:, strict:, name:, namespace:) are supported.

  • Extracts shared checker initialization (argument validation, object resolution, name inference, checker construction) into InterfaceSetup, eliminating duplication between BulkInterfaceChecker and CanonicalInterfaceChecker.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “canonical interface” comparison mode to DuckTyper, enabling N implementations to be checked directly against a single authoritative reference, with aggregated failures for easier diagnosis. This also refactors shared checker setup logic to reduce duplication between checkers.

Changes:

  • Introduces DuckTyper::CanonicalInterfaceChecker (+ aggregated Result) and wires it into the main gem entrypoint.
  • Adds Minitest (assert_canonical_interface_match) and RSpec (implement_canonical_interface) integrations for canonical checks.
  • Extracts shared initialization logic into InterfaceSetup and factors common result-message helpers into ResultFormatting.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/duck_typer/canonical_interface_checker_test.rb Adds unit tests for canonical checker behavior and messaging.
test/duck_typer/bulk_interface_checker_test.rb Updates expected argument-validation error messages after refactor.
lib/duck_typer/rspec.rb Adds implement_canonical_interface matcher.
lib/duck_typer/result_formatting.rb Extracts shared failure-message helpers (interface_label, strict_note).
lib/duck_typer/objects_resolver.rb Adds an objects/namespace resolution helper module.
lib/duck_typer/minitest.rb Adds assert_canonical_interface_match helper.
lib/duck_typer/interface_setup.rb Centralizes checker argument validation, object resolution, name inference, checker construction.
lib/duck_typer/interface_checker/result.rb Reuses ResultFormatting and exposes diff_message for aggregation.
lib/duck_typer/canonical_interface_checker/result.rb Implements aggregated failure message for canonical comparisons.
lib/duck_typer/canonical_interface_checker.rb Implements canonical comparison loop against a reference class/module.
lib/duck_typer/bulk_interface_checker.rb Refactors to use InterfaceSetup.
lib/duck_typer.rb Requires canonical checker so it’s available when requiring duck_typer.
README.md Documents canonical interface usage for Minitest and RSpec.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/duck_typer/minitest.rb
Comment thread lib/duck_typer/rspec.rb
Comment thread lib/duck_typer/objects_resolver.rb Outdated
Comment thread lib/duck_typer/interface_setup.rb
Comment thread lib/duck_typer/canonical_interface_checker/result.rb
@thiagoa thiagoa force-pushed the add-canonical-interface-checker branch from 122c1ad to 48389ac Compare April 24, 2026 16:36
@thiagoa thiagoa requested a review from Copilot April 24, 2026 16:39
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@thiagoa thiagoa force-pushed the add-canonical-interface-checker branch 2 times, most recently from a31e411 to d49d839 Compare April 24, 2026 19:01
Pairwise comparison verifies that every adjacent pair of classes in a
list agree with each other, which works well when all classes are peers
with no single authoritative definition. Canonical interface comparison
takes a different approach: one class is designated as the reference,
and every other class is checked against it directly. This is useful
when the interface already has a clear owner — an abstract base, a
well-established implementation, or a purpose-built interface class —
and you want to confirm that all other implementations conform to that
definition. Because all comparisons share the same right-hand side,
failures from multiple classes are aggregated into a single result,
making it easier to see the full picture at a glance.

- Adds `CanonicalInterfaceChecker`, which compares every class in a list
  against a single canonical reference rather than in consecutive pairs.
  All failures are aggregated into one result, so a single assertion
  reports every non-conforming class at once.

- Exposes `assert_canonical_interface_match(canonical, objects, **opts)`
  in the Minitest integration and
  `implement_canonical_interface(canonical, **opts)` in the RSpec
  integration. All existing options (`type:`, `methods:`, `strict:`,
  `name:`, `namespace:`) are supported.

- Extracts shared checker initialization (argument validation, object
  resolution, name inference, checker construction) into
  `InterfaceSetup`, eliminating duplication between
  `BulkInterfaceChecker` and `CanonicalInterfaceChecker`.
@thiagoa thiagoa force-pushed the add-canonical-interface-checker branch from d49d839 to 096fd49 Compare April 24, 2026 19:08
@thiagoa thiagoa merged commit 251ee4d into main May 15, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants