On Oct 23, 2017, at 05:50, "Prof. Andrew P. Black" <black@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