Lab 4: Functions, Refactoring, Testing

Goals

After the lab, you should be proficient at

  1. using and defining functions within your program
  2. refactoring your code to use functions
  3. programmatically testing functions

Objective: Review

Review the slides for today.

Objective: Set Up

Objective: Programming in Python

We'll practice writing several Python programs, each in their own text file. Name the files lab4_1.py, lab4_2.py, etc.

Your programs will be graded on correctness, efficiency, style, and how well you tested them. Make sure you adhere to the good development and testing practices we discussed in class. Your code should be readable and your output should be useful and well-formatted.

After you've developed a correct solution to each program, close reopen the IDLE "shell" by running the program again (using F5), demonstrate that the program works using several good test cases, and save the output to a file named lab4_x.out, where x is the problem number.

You can use Python Visualizer to help you see what is happening in your program. This is the visualizer used in the text book.

  1. (20) Let's start by getting you comfortable with calling functions that have been defined within the same file.

    Open lab4_1.py, which you copied earlier. Read through the functions and their documentation. Focus on the function names and their API (what is their input, what do they do, what do they return?). Then, modify the main function such that it implements what is described in its comments, e.g., draws and moves bugs, using functions defined within the program or methods from the Graphics library. (Many of your questions can be answered by reading the function's documentation, so reread the documentation. Don't worry about the code within the functions; just understand how to use the functions.)

    There will be no saved output for this program.

  2. (14 pts) Let's try turning code that you wrote before into a function--Refactoring!, so that we're focused on defining functions rather than writing new code.

    As usual, create a new file in your lab directory named as lab4_2.py. Open your lab3/lab3_5.py file for reference. Refactor your code such that the code that displays the first 20 Fibonacci numbers (and only that code) is in a function called displayFibonacciSequence. This function should not take any parameters and does not return anything.

    Then, from the original file, copy the other code that wasn't part of the function you just created and put into a main function. Your main function will likely be quite short. Confirm that the output of the program when executed is the same as the original program from lab 3.

    Note that the programmatic testing will not work for this function because the function does not return anything.

  3. (17 pts) Now let's try writing a function that takes parameters and returns something and programmatically testing that function.
    1. Open a new file (which will be named lab4_3.py).
    2. Copy your function displayFibonacciSequence into this new file and change its name to generateFibonacciNumber. The function should take as a parameter the number of the Fibonacci sequence (which must be greater than 2) to generate and returns that number. Update the documentation accordingly.
    3. Write a test function that tests that your function works correctly.

      To help make the desired functionality clear, the following test case should pass:
      test.testEqual( generateFibonacciNumber(6), 5 )

    4. After you have verified that your tests work, comment out the call to your test function.
    5. Now, create a main function that prompts the user for which Fibonacci number they want and then display that Fibonacci number.

      A sample run is shown below:

      This program computes Fibonacci numbers.
              
      Which Fibonacci number are you looking for (larger than 2)? 6
      
      The Fibonacci number at position 6 in the sequence is 5
      

      (The output is a little awkward. We don't have a good way of saying the "6th" number vs the "1st" number, etc.)

  4. (15) We haven't been making clear the importance of reusable functions because all of the functions we have defined have been used only within the same program.
    1. Open game.py. This file is the start of our own game module that we will use in subsequent labs.
    2. Implement the function rollDie. You may need to review the random module.

      Note that the function has a default value for the parameter sides. We have used default parameters before (e.g., the range function start is 0 and step is 1), but we haven't seen how they are defined before.

      Remove the statement pass, which is just meant to make the module be able to execute while you're still developing.

    3. Test the function using the testRollDie function.
    4. In comments at the top of the program (below the high-level description), answer the following questions: Why can't we use test.testEqual to test this function? Why can Professor Sprenkle write a function that tests your code without knowing how your function is implemented? (Note, however, that passing the test does not guarantee that your code is correct, although it is likely correct..)
    5. Implement the function rollMultipleDice, using another function that you implemented.
    6. Uncomment the call to the function testRollMultipleDice and test your new function.
    7. When you're sure your program works, save the output from executing both the testRollDie and testRollMultipleDice (in one run). Save it in a file called game.out so that it's with the code in the printable lab.

    If you run yahtzee.py, you should see the output from rolling 5 dice. We can't do a whole lot more than that just yet, but hopefully, you could imagine that happening.

  5. (24 pts) Overview: Write a program that calculates the surface area of a cylinder. We're breaking the code into several pieces:
    • Define a function called calculateCircleArea that takes as a parameter the radius of a circle and returns the area of the circle. (You may want to start with the code you wrote in the last lab.) Test the function in a test function.
    • Define a function called calculateCircleCircumference that takes as a parameter the radius of a circle and returns the circumference of the circle (calculated as 2 π r). Test the function in another test function.
    • Define a function that takes as parameters a cylinder's radius and height and returns the surface area of a cylinder. Name the function appropriately. To calculate the area of a cylinder, find the area of, say, one of the circles and multiply it by two and add that to the circle's circumference, multiplied by the height of the cylinder. Test the function in yet another test function. (Note that, since you made sure that the earlier functions worked correctly, you should feel confident using those functions to solve this problem.)
    • Finally, create a main function that prompts the user for a cylinder's radius and height and displays the surface area of the cylinder, rounded to two decimal places.

      Your final output should show multiple runs of the program, getting user input and displaying the cylinder. There should be no output from the testing. I'll see the test cases you tried in your test functions.

Finishing up: What to turn in for this lab

You have completed several labs. I am not as explicit in the instructions anymore. Refer to the links or previous labs to remind yourself of instructions/commands.

  1. Clean up: Move graphics.py into your cs111 directory. (see mv. Note where the cs111 directory is with respect to where you're running this command from.)
    In other words, you should only have the .py files you wrote, test.py, yahtzee.py, the .out files you created, and a __pycache__ directory in your directory when you print. (The latter is not printed.)
  2. Create your printable lab assignment, using the createPrintableLab command:
    createPrintableLab <labdirname>
  3. View your file using the evince command. It should only be a few pages. If it is longer than that, check if you have graphics.py in the PDF. Go back and follow the steps to move that file out of your lab directory.
  4. Print your file from Evince. If you're in the Advanced Lab, use its printer.
  5. Move graphics.py back into your lab4 directory.
  6. Submit your lab4 directory into your turnin directory.

Print your lab before class. Submit the printed and electronic version before the beginning of Friday's class.

Grading (90 pts)