pythonpytest
Ben Gorman

Ben Gorman

Life's a garden. Dig it.

You've created a function called is_highfive(x) that determines whether a number is a "high five" ✋ which you've defined as a number greater than 100 and divisible by five.

Write and run the following three tests inside test_highfive.py:

  1. confirm that 105 is a high five
  2. confirm that 100 is not a high five
  3. confirm that 106 is not a high five

Design your test(s) so that every one of these checks runs, regardless of whether one of them fails.

Directory Structure

highfive/
  highfive.py
  test_highfive.py

Files

def is_highfive(x):
    """
    Check if a is a "high five" -
    a number that's greater than 100 and divisible by 5
 
    :param a: a number
    :return: True / False
    """
 
    return x > 100 and x % 5 == 0
# 1. confirm that 105 is a high five
# 2. confirm that 100 is not a high five
# 3. confirm that 106 is not a high five
 
# your code here

Solution 1

test_highfive.py
from highfive import is_highfive
 
def test_105():
    assert is_highfive(105)
 
def test_100():
    assert not is_highfive(100)
 
def test_106():
    assert not is_highfive(106)

Explanation

How to run these tests

cd path/to/highfive/
pytest

(You should see three green dots indicating that each test passed.)

What about this?

def test_is_highfive():
    assert is_highfive(105)
    assert not is_highfive(100)
    assert not is_highfive(106)

When you put multiple assertions in one test function, if one of the assertions fails, the function stops executing and none of the remaining assertions are tested. In other words, test functions pass or fail "as a whole". Sometimes this is desirable, but in this example we wanted each test to run, regardless of whether one of them fails.

Solution 2

test_highfive.py
import pytest
from highfive import is_highfive
 
@pytest.mark.parametrize(
    "test_input, expected",
    [(105, True), (100, False), (106, False)]
)
def test_is_highfive(test_input, expected):
    assert is_highfive(test_input) == expected

Explanation

This is equivalent to Solution 1 but less wordy.

  1. Define a generic test function with two parameters: test_input and expected.

    from highfive import is_highfive
     
    def test_is_highfive(test_input, expected):
            assert is_highfive(test_input) == expected
  2. Decorate the function with the @pytest.mark.parametrize decorator, passing in

    1. a string representation of the input parameters
    2. a list of (a, b) tuples representing each (test_input, expected) pair
    import pytest
    from highfive import is_highfive
     
    @pytest.mark.parametrize(
            "test_input, expected",
            [(105, True), (100, False), (106, False)]
        )
        def test_is_highfive(test_input, expected):
            assert is_highfive(test_input) == expected

    Note that using the parametrize decorator requires us to import pytest.