@@ -45,7 +45,7 @@ aligned as the design changes.
4545Add to your Gemfile:
4646
4747``` ruby
48- gem " duck_typer"
48+ gem " duck_typer" , group: :test
4949```
5050
5151Then run:
@@ -109,7 +109,11 @@ classes share compatible interfaces:
109109
110110``` ruby
111111def test_payment_processors_have_compatible_interfaces
112- assert_interfaces_match [StripeProcessor , PaypalProcessor , BraintreeProcessor ]
112+ assert_interfaces_match [
113+ StripeProcessor ,
114+ PaypalProcessor ,
115+ BraintreeProcessor
116+ ]
113117end
114118```
115119
@@ -131,6 +135,19 @@ assert_interfaces_match [StripeProcessor, PaypalProcessor],
131135This is useful if your class implements multiple interfaces, in
132136which case you can write an assertion for each.
133137
138+ To enforce that positional argument names also match (strict
139+ mode), pass ` strict: true ` :
140+
141+ ``` ruby
142+ assert_interfaces_match [StripeProcessor , PaypalProcessor ],
143+ strict: true
144+ ```
145+
146+ By default, positional argument names are ignored — only their
147+ count and kind (required, optional, rest) are compared. In strict
148+ mode, names must match exactly. Keyword argument names always
149+ matter regardless of this setting.
150+
134151### RSpec
135152
136153Require the RSpec integration in your ` spec_helper.rb ` :
@@ -147,21 +164,32 @@ share compatible interfaces:
147164``` ruby
148165RSpec .describe " payment processors" do
149166 it " have compatible interfaces" do
150- expect([StripeProcessor , PaypalProcessor , BraintreeProcessor ]).to have_matching_interfaces
167+ expect([StripeProcessor , PaypalProcessor , BraintreeProcessor ])
168+ .to have_matching_interfaces
151169 end
152170end
153171```
154172
155173For class-level interfaces, pass ` type: :class_methods ` :
156174
157175``` ruby
158- expect([StripeProcessor , PaypalProcessor ]).to have_matching_interfaces(type: :class_methods )
176+ expect([StripeProcessor , PaypalProcessor ])
177+ .to have_matching_interfaces(type: :class_methods )
159178```
160179
161180To check only a subset of methods, use ` methods: ` :
162181
163182``` ruby
164- expect([StripeProcessor , PaypalProcessor ]).to have_matching_interfaces(methods: %i[charge refund] )
183+ expect([StripeProcessor , PaypalProcessor ])
184+ .to have_matching_interfaces(methods: %i[charge refund] )
185+ ```
186+
187+ To enforce that positional argument names also match, pass
188+ ` strict: true ` :
189+
190+ ``` ruby
191+ expect([StripeProcessor , PaypalProcessor ])
192+ .to have_matching_interfaces(strict: true )
165193```
166194
167195#### Shared example
@@ -184,23 +212,30 @@ Then use it in your specs:
184212
185213``` ruby
186214RSpec .describe " payment processors" do
187- it_behaves_like " an interface" , [StripeProcessor , PaypalProcessor , BraintreeProcessor ]
215+ it_behaves_like " an interface" , [
216+ StripeProcessor ,
217+ PaypalProcessor ,
218+ BraintreeProcessor
219+ ]
188220end
189221```
190222
191- The same ` type: ` and ` methods :` options are supported:
223+ The same ` type: ` , ` methods: ` , and ` strict :` options are supported:
192224
193225``` ruby
194226it_behaves_like " an interface" , [StripeProcessor , PaypalProcessor ],
195227 type: :class_methods ,
196- methods: %i[charge refund]
228+ methods: %i[charge refund] ,
229+ strict: true
197230```
198231
199232## Limitations
200233
201- DuckTyper checks the ** structure** of public method signatures
202- — the number of parameters, their kinds (required, optional,
203- keyword, rest, block), and keyword argument names. It does not
234+ By default, DuckTyper checks the ** structure** of public method
235+ signatures — the number of parameters, their kinds (required,
236+ optional, keyword, rest, block), and keyword argument names. In
237+ strict mode, positional argument names are also compared. It does
238+ not
204239verify the following, which should be covered by your regular
205240test suite:
206241
0 commit comments