Hi—I’m a beginner in Pharo and am working my way through Pharo by Example 5.0 (PbE) and Learning OOP and TDD with Pharo (LOTWP).
I’m currently going through 7.4 Designing a test, in LOTWP, which covers testing whether a string has no repeated characters, adding the method String >> isIsogramSet. GramCheckerTest, a class for testing, has the following methods: — isograms "list of isograms; used for testing" ^ #('pharo' 'pathfinder' 'xavier' 'lumberjacks’) testAllIsogramSet "using each word in list named 'isograms'" self isograms do: [ :word | self assert: word isIsogramSet ] — Here are my questions: 1) These two methods are defined on the instance side (the Class button is *not* selected). If so, what is the receiver when they are used? 2) In testAllIsogramSet, why do you need ‘self’? After all ‘isograms’ is a data structure, and its message is ‘do:’ 3) As an add-on to 2), what does ‘self’ refer to? The class GramCheckerTest? If so, wouldn’t that make testAllIsogramSet a class method? But testAllIsogramSet doesn’t appear in the class browser when I click the Class button when the Class pane shows GramCheckerTest. Thanks for any help you might give/point me to regarding this. |
On 04/21/2018 08:25 PM, Gregg Williams wrote:
> Hi—I’m a beginner in Pharo Hi Gregg, welcome! > and am working my way through Pharo by Example 5.0 (PbE) and Learning OOP and TDD with Pharo (LOTWP). > > I’m currently going through 7.4 Designing a test, in LOTWP, which covers testing whether a string has no repeated characters, adding the method String >> isIsogramSet. > > GramCheckerTest, a class for testing, has the following methods: > > — > isograms > "list of isograms; used for testing" > > ^ #('pharo' 'pathfinder' 'xavier' 'lumberjacks’) > > > testAllIsogramSet > "using each word in list named 'isograms'" > > self isograms do: [ :word | self assert: word isIsogramSet ] > — > > Here are my questions: > > 1) These two methods are defined on the instance side (the Class button is *not* selected). If so, what is the receiver when they are used? subclass of TestCase. > > 2) In testAllIsogramSet, why do you need ‘self’? After all ‘isograms’ is a data structure, and its message is ‘do:’ "isograms" is not, strictly speaking, the name of a data structure. It's the name (formally, "selector") of a message. The method for responding to that message is defined by the source code you list above. That method answers an object of class Array. So in order to get a reference to that array in the actual test case method, it has to send the message #isograms (the # indicates a Symbol -- all message selectors are Symbols), to self. Since the class of the receiver understands messages with that selector, it evaluates the method, and the method answers the reference to the Array. > > 3) As an add-on to 2), what does ‘self’ refer to? The class GramCheckerTest? If so, wouldn’t that make testAllIsogramSet a class method? But testAllIsogramSet doesn’t appear in the class browser when I click the Class button when the Class pane shows GramCheckerTest. When these methods are evaluated, self will be bound to the receiver. The receiver will be an instance of GramCheckerTest. (or possibly a subclass of GramCheckerTest, if any subclasses exist -- they would inherit the method unless overridden.) The test framework creates an instance of the test class to actually run the test. Let's take a look at the code involved. One way to run your test would be to evaluate GramCheckerTest run: #testAllIsogramSet. GramCheckerTest most likely inherits the method for #run: from TestCase, and you can see it on the class side of TestCase. It looks like this: run: aSymbol "Execute a testcase name, aSymbol, and return a test result." ^(self selector: aSymbol) run So it sends the message #selector: to self. Note a potentially confusing point here -- #selector: is a selector. Kind of like if my name were "Name." Self here is the class GramCheckerTest. As long as GramCheckerTest doesn't define its own version of #selector:, it inherits that method from TestCase (class side, still), and that method looks like this: selector: aSymbol "Return a test case with aSymbol as selector but does not execute it." ^self new setTestSelector: aSymbol This sends #new to self. Self is, once again, the class GramCheckerTest. A class responds to the message #new by creating a new instance of itself. So now you've got an *instance* of GramCheckerTest, and any messages you send to that will be responded to by methods on the instance side. Well, I would not be surprised if this explanation has confused you, but I hope it's enlightened you a bit as well. Please ask more questions until you understand what's going on here -- if you understand this you will be well positioned to understand the entire language. Regards, -Martin |
In reply to this post by GreggInCA
Le 22/04/2018 à 05:25, Gregg Williams a écrit :
> 2) In testAllIsogramSet, why do you need ‘self’? After all ‘isograms’ is a data structure, and its message is ‘do:’ You defined isograms as a method of the class. Therefore only this method returns the data structure you defined there. It is not an instance variable declared in your GramCheckerTest class. In that case you may want to initialize it in your initialize GramCheckerTest class (or for a test case it is better to do it it in the setUp method as it will be called before each test method call): initialize super initialize. isograms := #('pharo' 'pathfinder' 'xavier' 'lumberjacks’) Then your test method can access it directly (without self): isograms do: [ :word | self assert: word isIsogramSet ] Hilaire -- Dr. Geo http://drgeo.eu |
tx guys for your help.
cleaning the garden (was a junggle -well still). On Sun, Apr 22, 2018 at 12:18 PM, Hilaire <[hidden email]> wrote: > Le 22/04/2018 à 05:25, Gregg Williams a écrit : >> >> 2) In testAllIsogramSet, why do you need ‘self’? After all ‘isograms’ is a >> data structure, and its message is ‘do:’ > > > You defined isograms as a method of the class. Therefore only this method > returns the data structure you defined there. > It is not an instance variable declared in your GramCheckerTest class. In > that case you may want to initialize it in your initialize GramCheckerTest > class (or for a test case it is better to do it it in the setUp method as it > will be called before each test method call): > > initialize > super initialize. > isograms := #('pharo' 'pathfinder' 'xavier' 'lumberjacks’) > > > Then your test method can access it directly (without self): > > > isograms do: [ :word | self assert: word isIsogramSet ] > > > Hilaire > > -- > Dr. Geo > http://drgeo.eu > > > |
Administrator
|
In reply to this post by GreggInCA
Gregg Williams wrote
> Hi—I’m a beginner in Pharo and am working my way through Pharo by Example > 5.0 (PbE) and Learning OOP and TDD with Pharo (LOTWP). Welcome! That's a great way to start :) Gregg Williams wrote > 1) These two methods are defined on the instance side (the Class button is > *not* selected). If so, what is the receiver when they are used? I think the other two replies covered this and your other questions technically, but I just want to mention that the TestCase class can be a bit confusing. It represents a convenient way to deal with tests in a class browser, at the expense of being the most understandable OOP design. Suffice it to say that whenever a test is run, SUnit, the testing system, will do the magic to create an instance of your TestCase subclass. This is what happens when you click the test bubble in the browser, and this instance is what `self` refers to in tests. HTH ----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Cheers,
Sean |
Indeed TestCase is a really a special class and it can be really
looking strange at first. On Sun, Apr 22, 2018 at 2:20 PM, Sean P. DeNigris <[hidden email]> wrote: > Gregg Williams wrote >> Hi—I’m a beginner in Pharo and am working my way through Pharo by Example >> 5.0 (PbE) and Learning OOP and TDD with Pharo (LOTWP). > > Welcome! That's a great way to start :) > > > Gregg Williams wrote >> 1) These two methods are defined on the instance side (the Class button is >> *not* selected). If so, what is the receiver when they are used? > > I think the other two replies covered this and your other questions > technically, but I just want to mention that the TestCase class can be a bit > confusing. It represents a convenient way to deal with tests in a class > browser, at the expense of being the most understandable OOP design. Suffice > it to say that whenever a test is run, SUnit, the testing system, will do > the magic to create an instance of your TestCase subclass. This is what > happens when you click the test bubble in the browser, and this instance is > what `self` refers to in tests. HTH > > > > ----- > Cheers, > Sean > -- > Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html > |
Free forum by Nabble | Edit this page |