<div dir="ltr">I share Jakob's sentiments on this, and would wonder whether this particular kind of domain-specific matching is an appropriate responsibility for SUnit.  Currently, it's 100% client responsibility to calculate assertions for SUnit.  Blending this responsibility into SUnit means it could drift over time, causing tests that once passed to no longer passed (if they depended on these methods).</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Apr 10, 2020 at 4:30 AM Jakob Reschke <<a href="mailto:forums.jakob@resfarm.de">forums.jakob@resfarm.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Please be aware that the basic SUnit is not specific to Squeak and<br>
enlarging its interface makes it even more unlikely that the written<br>
test cases will be portable.<br>
<br>
<a href="http://sunit.sourceforge.net/" rel="noreferrer" target="_blank">http://sunit.sourceforge.net/</a><br>
<br>
Although I am afraid that compatibility might not maintained any more already.<br>
Nevertheless one could at least put the additional methods in an<br>
extensions package, which could as well be in Squeak Trunk.<br>
<br>
Am Do., 9. Apr. 2020 um 14:23 Uhr schrieb <<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>>:<br>
><br>
> Christoph Thiede uploaded a new version of SUnit to project The Inbox:<br>
> <a href="http://source.squeak.org/inbox/SUnit-ct.127.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/inbox/SUnit-ct.127.mcz</a><br>
><br>
> ==================== Summary ====================<br>
><br>
> Name: SUnit-ct.127<br>
> Author: ct<br>
> Time: 9 April 2020, 2:22:49.769949 pm<br>
> UUID: bf5be456-fbd7-e343-9158-da59c75fa05d<br>
> Ancestors: SUnit-ct.126<br>
><br>
> Adds support for string pattern assertions (#assert:matches:[description:] and #deny:matches:[description:]). Also tests these selectors in SUnitTest.<br>
><br>
> TestCase new assert: 'Sq*k' matches: 'Squeak'.<br>
> TestCase new assert: 'Sq\w+k' asRegex matches: 'Squeak'.<br>
> TestCase new deny: '.*\d' asRegex matches: 'Squeak123' description: 'This one will fail'.<br>
><br>
> Depends indeed on SUnit-ct.126.<br>
><br>
> =============== Diff against SUnit-ct.126 ===============<br>
><br>
> Item was added:<br>
> + ----- Method: SUnitTest>>testAssertMatches (in category 'tests') -----<br>
> + testAssertMatches<br>
> +<br>
> +       | pattern positive negative notAString |<br>
> +       pattern := 'f*'.<br>
> +       positive := 'foo'.<br>
> +       negative := 'bar'.<br>
> +       notAString := Object new.<br>
> +<br>
> +       self shouldnt: [self assert: pattern matches: positive] raise: TestFailure.<br>
> +<br>
> +       self should: [self assert: pattern matches: negative] raise: TestFailure.<br>
> +       [self assert: pattern matches: negative]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern)<br>
> +                               description: 'Error message doesn''t include the expected pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: negative)<br>
> +                               description: 'Error message doesn''t include the actual value'].<br>
> +<br>
> +       self should: [self assert: pattern matches: notAString] raise: TestFailure.<br>
> +       [self assert: pattern matches: notAString]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'string')<br>
> +                               description: 'Error message doesn''t say that we''re passing a non-string object here'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern)<br>
> +                               description: 'Error message doesn''t include the expected pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: notAString asString)<br>
> +                               description: 'Error message doesn''t include the actual value'].!<br>
><br>
> Item was added:<br>
> + ----- Method: SUnitTest>>testAssertMatchesDescription (in category 'tests') -----<br>
> + testAssertMatchesDescription<br>
> +<br>
> +       | pattern positive negative notAString |<br>
> +       pattern := 'f*'.<br>
> +       positive := 'foo'.<br>
> +       negative := 'bar'.<br>
> +       notAString := Object new.<br>
> +<br>
> +       self shouldnt: [self assert: pattern matches: positive description: ['A description' , 42]] raise: TestFailure.<br>
> +<br>
> +       self should: [self assert: pattern matches: negative description: ['A description' , 42]] raise: TestFailure.<br>
> +       [self assert: pattern matches: negative description: ['A description' , 42]]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'A description' , 42)<br>
> +                               description: 'Error message doesn''t give you the description'].<br>
> +<br>
> +       self should: [self assert: pattern matches: notAString description: ['A description' , 42]] raise: TestFailure.<br>
> +       [self assert: pattern matches: notAString description: ['A description' , 42]]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'string')<br>
> +                               description: 'Error message doesn''t say that we''re passing a non-string object here'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'A description' , 42)<br>
> +                               description: 'Error message doesn''t give you the description'].!<br>
><br>
> Item was added:<br>
> + ----- Method: SUnitTest>>testAssertMatchesRegex (in category 'tests') -----<br>
> + testAssertMatchesRegex<br>
> +<br>
> +       | pattern positive negative notAString |<br>
> +       pattern := 'fo+' asRegex.<br>
> +       positive := 'foo'.<br>
> +       negative := 'f'.<br>
> +       notAString := Object new.<br>
> +<br>
> +       self shouldnt: [self assert: pattern matches: positive] raise: TestFailure.<br>
> +<br>
> +       self should: [self assert: pattern matches: negative] raise: TestFailure.<br>
> +       [self assert: pattern matches: negative]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern asString)<br>
> +                               description: 'Error message doesn''t include the expected regex pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: negative)<br>
> +                               description: 'Error message doesn''t include the actual value'].<br>
> +<br>
> +       self should: [self assert: pattern matches: notAString] raise: TestFailure.<br>
> +       [self assert: pattern matches: notAString]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'string')<br>
> +                               description: 'Error message doesn''t say that we''re passing a non-string object here'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern asString)<br>
> +                               description: 'Error message doesn''t include the expected regex pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: notAString asString)<br>
> +                               description: 'Error message doesn''t include the actual value'].!<br>
><br>
> Item was added:<br>
> + ----- Method: SUnitTest>>testDenyMatches (in category 'tests') -----<br>
> + testDenyMatches<br>
> +<br>
> +       | pattern positive negative notAString |<br>
> +       pattern := 'f*'.<br>
> +       positive := 'foo'.<br>
> +       negative := 'bar'.<br>
> +       notAString := Object new.<br>
> +<br>
> +       self shouldnt: [self deny: pattern matches: negative] raise: TestFailure.<br>
> +<br>
> +       self should: [self deny: pattern matches: positive] raise: TestFailure.<br>
> +       [self deny: pattern matches: positive]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern)<br>
> +                               description: 'Error message doesn''t include the expected pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: positive)<br>
> +                               description: 'Error message doesn''t include the actual value'].<br>
> +<br>
> +       self should: [self deny: pattern matches: notAString] raise: TestFailure.<br>
> +       [self deny: pattern matches: notAString]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'string')<br>
> +                               description: 'Error message doesn''t say that we''re passing a non-string object here'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern)<br>
> +                               description: 'Error message doesn''t include the expected pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: notAString asString)<br>
> +                               description: 'Error message doesn''t include the actual value'].!<br>
><br>
> Item was added:<br>
> + ----- Method: SUnitTest>>testDenyMatchesDescription (in category 'tests') -----<br>
> + testDenyMatchesDescription<br>
> +<br>
> +       | pattern positive negative notAString |<br>
> +       pattern := 'f*'.<br>
> +       positive := 'foo'.<br>
> +       negative := 'bar'.<br>
> +       notAString := Object new.<br>
> +<br>
> +       self shouldnt: [self deny: pattern matches: negative description: ['A description' , 42]] raise: TestFailure.<br>
> +<br>
> +       self should: [self deny: pattern matches: positive description: ['A description' , 42]] raise: TestFailure.<br>
> +       [self deny: pattern matches: positive description: ['A description' , 42]]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'A description' , 42)<br>
> +                               description: 'Error message doesn''t give you the description'].<br>
> +<br>
> +       self should: [self deny: pattern matches: notAString description: ['A description' , 42]] raise: TestFailure.<br>
> +       [self deny: pattern matches: notAString description: ['A description' , 42]]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'string')<br>
> +                               description: 'Error message doesn''t say that we''re passing a non-string object here'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'A description' , 42)<br>
> +                               description: 'Error message doesn''t give you the description'].!<br>
><br>
> Item was added:<br>
> + ----- Method: SUnitTest>>testDenyMatchesRegex (in category 'tests') -----<br>
> + testDenyMatchesRegex<br>
> +<br>
> +       | pattern positive negative notAString |<br>
> +       pattern := 'fo+' asRegex.<br>
> +       positive := 'foo'.<br>
> +       negative := 'f'.<br>
> +       notAString := Object new.<br>
> +<br>
> +       self shouldnt: [self deny: pattern matches: negative] raise: TestFailure.<br>
> +<br>
> +       self should: [self deny: pattern matches: positive] raise: TestFailure.<br>
> +       [self deny: pattern matches: positive]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern asString)<br>
> +                               description: 'Error message doesn''t include the expected regex pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: negative)<br>
> +                               description: 'Error message doesn''t include the actual value'].<br>
> +<br>
> +       self should: [self deny: pattern matches: notAString] raise: TestFailure.<br>
> +       [self deny: pattern matches: notAString]<br>
> +               on: TestFailure do: [:ex |<br>
> +                       | error |<br>
> +                       error := ex messageText.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: 'string')<br>
> +                               description: 'Error message doesn''t say that we''re passing a non-string object here'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: pattern asString)<br>
> +                               description: 'Error message doesn''t include the expected regex pattern'.<br>
> +                       self<br>
> +                               assert: (error includesSubstring: notAString asString)<br>
> +                               description: 'Error message doesn''t include the actual value'].!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>assert:matches: (in category 'accessing') -----<br>
> + assert: pattern matches: actual<br>
> +<br>
> +       ^ self<br>
> +               assert: pattern<br>
> +               matches: actual<br>
> +               description: nil!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>assert:matches:description: (in category 'accessing') -----<br>
> + assert: pattern matches: actual description: aStringOrBlock<br>
> +<br>
> +       self<br>
> +               assert: [actual isString or: [actual isText]]<br>
> +               description: [self<br>
> +                       description: aStringOrBlock<br>
> +                       with: (self comparingStringBetweenPattern: pattern andNonTextual: actual)].<br>
> +       self<br>
> +               assert: [self doesPattern: pattern match: actual]<br>
> +               description: [self<br>
> +                       description: aStringOrBlock<br>
> +                       with: (self comparingStringBetweenPattern: pattern and: actual)].!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>comparingStringBetweenPattern:and: (in category 'private') -----<br>
> + comparingStringBetweenPattern: pattern and: actual<br>
> +<br>
> +       ^ 'Expected pattern {1} does not match actual {2}.' translated<br>
> +               format: {<br>
> +                       pattern.<br>
> +                       actual }!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>comparingStringBetweenPattern:andNonTextual: (in category 'private') -----<br>
> + comparingStringBetweenPattern: pattern andNonTextual: actual<br>
> +<br>
> +       ^ 'Expected something that matches {1} but actual {2} is neither string nor text.' translated<br>
> +               format: {<br>
> +                       pattern.<br>
> +                       actual }!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>comparingStringBetweenUnexpectedPattern:and: (in category 'private') -----<br>
> + comparingStringBetweenUnexpectedPattern: pattern and: actual<br>
> +<br>
> +       ^ 'Unexpected pattern {1} does match actual {2}.' translated<br>
> +               format: {<br>
> +                       pattern.<br>
> +                       actual }!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>comparingStringBetweenUnexpectedPattern:andNonTextual: (in category 'private') -----<br>
> + comparingStringBetweenUnexpectedPattern: pattern andNonTextual: actual<br>
> +<br>
> +       ^ 'Expected something that does not match {1} but actual {2} is neither string nor text.' translated<br>
> +               format: {<br>
> +                       pattern.<br>
> +                       actual }!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>deny:matches: (in category 'accessing') -----<br>
> + deny: pattern matches: actual<br>
> +<br>
> +       ^ self<br>
> +               deny: pattern<br>
> +               matches: actual<br>
> +               description: nil!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>deny:matches:description: (in category 'accessing') -----<br>
> + deny: pattern matches: actual description: aStringOrBlock<br>
> +<br>
> +       self<br>
> +               assert: [actual isString or: [actual isText]]<br>
> +               description: [self<br>
> +                       description: aStringOrBlock<br>
> +                       with: (self comparingStringBetweenUnexpectedPattern: pattern andNonTextual: actual)].<br>
> +       self<br>
> +               deny: [self doesPattern: pattern match: actual]<br>
> +               description: [self<br>
> +                       description: aStringOrBlock<br>
> +                       with: (self comparingStringBetweenUnexpectedPattern: pattern and: actual)].!<br>
><br>
> Item was added:<br>
> + ----- Method: TestCase>>doesPattern:match: (in category 'private') -----<br>
> + doesPattern: pattern match: stringOrText<br>
> +<br>
> +       ^ (pattern respondsTo: #matches:)<br>
> +               ifTrue: [pattern matches: stringOrText]<br>
> +               ifFalse: [pattern match: stringOrText]!<br>
><br>
><br>
<br>
<br>
</blockquote></div>