> > > On Oct 23, 2017, at 05:50, "Prof. Andrew P. Black" <bl...@cs.pdx.edu> > wrote: >> >> If you have a String (or a Symbol), and you sent it the message #asSet, what >> do you expect to get as an answer? >> >> A set of characters, one would think. But do you care what class is used to >> implement that set of characters? >> >> -- One argument says that it should be a Set, because that’s what asSet >> answers when it is sent to other collections. It’s conceivable that you >> might initially populate the set with Characters, but then add other kinds >> of object. >> >> -- Another argument says that it should be a CharacterSet (or a >> WideCharacterSet), because you know that the receiver contains characters. >> The expression 'abcd' asSet is a convenient way to create a CharacterSet >> with: $a with: $b with: $c with: $d >> >> -- A third argument says that you shouldn’t care. If you really want a >> specific class, then you should use (aString as: Set) rather than aString >> asSet. >> >> Right now, in Pharo 7, there is a test in TConvertAsSetForMultiplinessTest >> that insists that the class of the result of asSet is actually Set. >> >> Hard coding a particular return class does seems to break the generality that make traits a good duck typing approach to testing. Instead you want to check it conforms to a series of tests like this... result := #(1 2 3 4) asSet. startSize := result size. result add: s anyOne. self assert: result size equals: startSize.
but you don't want to repeat yourself reproduce similar tests by hand everywhere. One approach to reuse might be to refactor SetTest so it can be called like ... TConvertAsSetForMultiplinessTest>>testInQuestion result := self getResult. SetTest runDuckTestsFor: result where #runDuckTestsFor: would exclude Set instance creation tests and suchlike. Duck tests might all take a single argument, so SetTest could call them with a series of concrete cases. The leads me to a philosophical quesition... should methods providing concrete test samples be stored on the class-side. That is, its simple to use... MyClassTest >> someTest sample := self sample. etc... but would it be more correct to do... MyClassTest >> someTest sample := self class sample. etc... since #sample is unrelated to the state of any particularMyClass. And maybe its better to drive it all from the class side... SetTest>>runcase self samples do: [ :duck | self runDuckTestsFor: duck]. self runCreationTests. Now I'm not sure if the following is the RightThing(tm), but for discussion... SetTest>>runDuckTestsFor: duck self testsTakingOneArgument do: [ :method | self perform: method with: duck ]. cheers -ben