Practice: Strong Code

Practice: Strong Code#

This practice section covers the concepts from the Strong Code chapters: code style, documentation, and code testing.

As for all practice sections, most questions will include a handful of assert statements. After you write and execute the code to each question, each assert should “pass silently” (meaning: should give no output upon execution) indicating that you are on the right track. After you’ve written your code and run the asserts, you can always check your answers, as the answers to these questions are included in the “Answers” chapter of this book.

Code Style#

Code Style Q1. The function below works, but its style leaves a lot to be desired. Rewrite it with good code style, naming the function calculate_bmi and its two parameters weight and height (which can be assumed to be in kilograms and meters, respectively). Along the way, fix all of the style issues you can find (naming, spacing, one statement per line, etc.).

Function provided:

def BMI(w,h):
    out=w/h**2;return out

Checks you can use to see if you’re on the right track:

assert callable(calculate_bmi)
assert calculate_bmi(80, 2.0) == 20.0
assert calculate_bmi(100, 2.5) == 16.0

Answer →

Code Style Q2. The three variables below store information about a course: the number of students enrolled, whether or not the course is full, and the average grade in the course (in that order). Unfortunately, whoever wrote them gave them names that describe none of that.

Rewrite the three assignments using well-styled, descriptive snake_case variable names: n_students, course_full, and avg_grade (storing the same three values, with PEP-approved spacing).

Variables provided:

X=25
FLAG    =True
Val2=88.5

Checks you can use to see if you’re on the right track:

assert n_students == 25
assert course_full == True
assert avg_grade == 88.5

Answer →

Documentation#

Documentation Q1. The function below works, but it is completely undocumented. Add (1) a numpy-style docstring - including a short description of what the function does, a Parameters section, and a Returns section - for anyone who wants to use the function, and (2) at least one comment explaining a piece of the implementation for anyone reading the code.

Function provided:

def count_evens(number_list):
    count = 0
    for value in number_list:
        if value % 2 == 0:
            count += 1
    return count

Checks you can use to see if you’re on the right track:

assert count_evens([2, 4, 5]) == 2
assert count_evens([1, 3, 5]) == 0
assert count_evens([]) == 0
assert count_evens.__doc__ is not None

Answer →

Code Testing#

Code Testing Q1 Make a class named Person that has two instance attributes: name and age. Be sure that they are assigned to user-specified values. Then, make a method called birthday() that increments age by 1 and returns the string “Happy Birthday!”

Then, create a unittest test class TestPerson with at least three test methods that, together, check the following:

  • an instance of the class is of type/instance Person

  • the instance’s name attribute is equal to the name you gave it

  • the instance’s age attribute is equal to the age you gave it

  • after calling the birthday() method, the instance’s age has been incremented by 1

Use setUp() so that each test method gets a fresh Person object (keeping your tests independent of one another). Then, run your tests, making sure they all pass.

Answer →

Code Testing Q2. The function absolute_difference below is supposed to return the (positive) difference between its two inputs, regardless of which input is larger. It has a bug.

First, write a unittest test class TestAbsoluteDifference with at least three test methods: one where the first input is larger, one where the second input is larger, and one where the inputs are equal. Run your tests - at least one should catch the bug!

Then, fix the function so that all of your tests pass.

Function provided:

def absolute_difference(num1, num2):
    return num1 - num2

Checks you can use to see if you’re on the right track (after your fix):

assert absolute_difference(5, 3) == 2
assert absolute_difference(3, 5) == 2
assert absolute_difference(4, 4) == 0

Answer →

Code Testing Q3. The BankAccount class has been provided for you below and works as intended - your job is to test it.

Write a unittest test class TestBankAccount that:

  • uses setUp() to create a fresh BankAccount before each test

  • has at least three test methods, including:

    • one testing that a new account starts with a balance of 0

    • one testing that deposit() increases the balance as expected

    • one using assertRaises to test that withdrawing more than the balance raises a ValueError

Then, run your tests, making sure they all pass.

Class provided:

class BankAccount():

    def __init__(self, balance=0):
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        if amount > self.balance:
            raise ValueError('insufficient funds')
        self.balance -= amount

Answer →