Skip to main content
Engineering LibreTexts

2.13: Defining a New Method

  • Page ID
    40044
    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    The advent of Test Driven Development (TDD) has changed the way we write code. The idea behind TDD is that we write a test that defines the desired behaviour of our code before we write the code itself. Only then do we write the code that satisfies the test.

    Suppose that our assignment is to write a method that ”says something loudly and with emphasis”. What exactly could that mean? What would be a good name for such a method? How can we make sure that programmers who may have to maintain our method in the future have an unambiguous description of what it should do? We can answer all of these questions by giving an example.

    Our goal is to define a new method named shout in the class String. The idea is that this message should turn a string into its uppercase version as shown in the example below:

    'No panic' shout
    >>> 'NO PANIC!'
    

    However, before creating the shout method itself, we must first create a test method! In the next section, we can use the ”No Panic” example to create our test method.

    Defining a test method.
    Figure \(\PageIndex{1}\): Defining a test method in the class StringTest.

    Defining a new test method

    How do we create a new method in Pharo? First, we have to decide which class the method should belong to. In this case, the shout method that we are testing will go in class String, so the corresponding test will, by convention, go in a class called StringTest.

    First, open a browser on the class StringTest, and select an appropriate protocol for our method, in this case 'tests - converting'. The highlighted text in the bottom pane is a template that reminds you what a Pharo method looks like. Delete this template code (remember, you can either click on the beginning or the end of the text, or press CMD-a, to ”Select All”), and start typing your method. We can turn our ”No Panic” code example into the test method itself:

    testShout
        self assert: ('No panic' shout = 'NO PANIC!')
    

    Once you have typed the text into the browser, notice that the corner is orange. This is a reminder that the pane contains unsaved changes. So, select Accept (s) by right clicking in the bottom pane, or just type CMD-s, to compile and save your method. You should see a situation similar to the one depicted in Figure \(\PageIndex{1}\).

    If this is the first time you have accepted any code in your image, you will likely be prompted to enter your name. Since many people have contributed code to the image, it is important to keep track of everyone who creates or modifies methods. Simply enter your first and last names, without any spaces.

    Because there is as yet no method called shout, the automatic code checker (Quality Assitance) in the lower browser pane will inform you, that the message shout is sent but not implemented. This can be quite useful if you have merely made a typing mistake, but in this case, we really do mean shout, since that is the method we are about to create. We confirm this by selecting the first option from the menu of choices.

    Running your test method

    Run your newly created test: open the Test Runner from the World Menu (or press on the circle icon in front of the method name this is faster and cooler).

    In the Test Runner the leftmost two panes are a bit like the top panes in the System Browser. The left pane contains a list of packages, but it’s restricted to those packages that contain test classes.

    Select CollectionsTests-Strings package, and the pane to the right will show all of the test classes in it, which includes the class StringTest. Class names are already selected, so click Run Selected to run all these tests.

    You should see the upper right pane turn red, which indicates that there was an error in running the tests. The list of tests that gave rise to errors is shown in the bottom right pane. As you can see, the method StringTest>>testShout is the culprit. (Note that StringTest>>testShout is the Pharo way of identifying the testShout method of the StringTest class.) If you click on that method in the bottom right pane, the erroneous test will run again, this time in such a way that you see the error happen: MessageNotUnderstood: ByteString>>shout (see Figure \(\PageIndex{2}\)).

    The debugger.
    Figure \(\PageIndex{2}\): Looking at the error in the debugger.

    The window that opens with the error message is the Pharo debugger. We will look at the debugger and how to use it in Chapter: The Pharo Environment.

    Implementing the tested method

    The error is, of course, exactly what we expected: running the test generates an error because we haven’t yet written a method that tells strings how to shout. Nevertheless, it’s good practice to make sure that the test fails because this confirms that we have set up the testing machinery correctly and that the new test is actually being run. Once you have seen the error, you can Abandon the running test, which will close the debugger window.

    Coding in the debugger

    Instead of pressing Abandon, you can define the missing method using the Create button right in the debugger. This will prompt you to select a class in which to define the new method (see Figure \(\PageIndex{3}\)), then prompt you to select a protocol for that method, and finally take you to a code editor window in the debugger, in which you can edit the code for this new method. Note that since the system cannot implement the method for you, it creates a generic method that is tagged as to be implemented (see Figure \(\PageIndex{4}\)).

    Debugger prompt to select in which class to create the new method.
    Figure \(\PageIndex{3}\): Pressing the Create button in the debugger prompts you to select in which class to create the new method.
    The automatically created method waiting for a real definition.
    Figure \(\PageIndex{4}\): The automatically created shout method waiting for a real definition.

    Now let’s define the method that will make the test succeed! Right inside the debugger edit the shout method with this definition:

    shout
        ^ self asUppercase,'!'
    

    The comma is the string concatenation operation, so the body of this method appends an exclamation mark to an upper-case version of whatever String object the shout message was sent to. The ^ tells Pharo that the expression that follows is the answer to be returned from the method, in this case the new concatenated string.

    When you’ve finished implementing the method, do not forget to compile it using CMD-s and you can press Proceed and continue with the tests. Note that Proceed simply continues on running the test suite, and does not re-run the failed method.

    Does this method work? Let’s run the tests and see. Click on Run Selected again in the Test Runner, and this time you should see a green bar and text indicating that all of the tests ran with no failures and no errors. When you get to a green bar, it’s a good idea to save your work by saving the image (World Menu > Save), and take a break. So, do that right now!


    This page titled 2.13: Defining a New Method is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.