question re. meaning of 'self' in a method used for testing

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

question re. meaning of 'self' in a method used for testing

GreggInCA
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.




Reply | Threaded
Open this post in threaded view
|

Re: question re. meaning of 'self' in a method used for testing

Martin McClure-2
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?
The receiver is an instance of the test class, which is most likely a
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


Reply | Threaded
Open this post in threaded view
|

Re: question re. meaning of 'self' in a method used for testing

HilaireFernandes
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



Reply | Threaded
Open this post in threaded view
|

Re: question re. meaning of 'self' in a method used for testing

Stephane Ducasse-3
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
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: question re. meaning of 'self' in a method used for testing

Sean P. DeNigris
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
Reply | Threaded
Open this post in threaded view
|

Re: question re. meaning of 'self' in a method used for testing

Stephane Ducasse-3
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
>