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

Objective: Review

Review the slides for today.

Objective: Set Up

Run runHelpClient

As usual, create a directory for the programs and output you develop in this lab.

Copy all the .py files in /csdept/courses/cs111/handouts/lab4/ into your lab4 directory.

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. Note the change in naming scheme.

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.

  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.

    There will be no saved output for this program.

  2. (15 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.

    Copy your lab3/lab3.5.py file into this directory as lab4_2.py. (Note the change in naming scheme.) Refactor your code such that the code that displays the first 20 Fibonacci numbers is in a function called displayFibonacciSequence. Follow the instructions to refactor your code from the in-class handout.

    Note that the programmatic testing will not work for this function.

    Your main function will likely be quite short.

  3. (20 pts) Now let's try writing a function that returns something and programmatically testing that function.

    Copy your last program and name it lab4_3.py Now, modify the function displayFibonacciSequence so that it takes as a parameter the number of the Fibonacci sequence (which must be greater than 2) to generate and returns that number. Name the modified function generateFibonacciNumber and update the documentation accordingly.

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

    Write a test function that tests that your function works correctly.

    After you have verified that your tests work, comment out the call to your test function.

    Now, modify the main function to prompt a 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. (20) 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.
    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?
    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.

    We are not ready to use this module to do anything interesting, but we will soon. (We could roll a bunch of dice, but we don't have much we can do after that.) Hopefully, it will not be hard to imagine how this module could be used to write other programs.

  5. (25 pts) [From Zelle, Chapter 3, Problem 3] Write a program that determines the total molecular weight of a molecule based on the number of hydrogen, carbon, and oxygen atoms it contains. You should use the following weights:
    AtomWeight
    (g/mol)
    H1.0079
    C12.011
    O15.9994

    Note that your program should use constants for the molecular weights of carbon, hydrogen, and oxygen. (Recall what the conventions are for naming constants. Why does it make sense to make these values constants?)

    Your program should define a function that takes as parameters the number of hydrogen, carbon, and oxygen atoms and returns the weight of the molecule.

    In a function, test the function you just defined, using the testEqual function.

    After verifying that your function works, create a main function. Your program should prompt the user for the number of atoms of each type and display the total weight with the appropriate units, rounded to 3 decimal places.

    A sample run is shown below:

    This program computes the molecular weight for a molecule.
        
    Enter number of Hydrogen atoms: 3
    Enter number of Carbon atoms: 2
    Enter number of Oxygen atoms: 1
    
    Weight of molecule is 43.045 g/mol
    
  6. Finishing up: What to turn in for this lab

    1. Clean up:
      1. IDLE and jEdit may create backup files with the "~" extension. Delete these files from your lab directory.
      2. 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.) Move graphics.py back into your lab4 directory after printing.
      3. If you have a file graphics.pyc (by accidentally running using Python2 instead of Python3), you should delete that file before printing.

      In other words, you should only have the .py files you wrote, test.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. If you haven't already, move graphics.py back into your lab4 directory.
    5. Submit your lab4 directory into your turnin directory.

    Submit the electronic version before the beginning of Friday's class.

    Grading (100 pts)