1 - Setting and getting code coverage

Switch to a new branch

Pull the latest from main and create a new branch step1

git checkout main
git pull
git checkout -b 'step1'

Add a calculator backend

Let's continue by adding in our calculator logic. Create the file api/calculator.py with the following contents:

class Calculator:
    def add(x, y):
        return x + y

    def subtract(x, y):
        return x - y

    def multiply(x, y):
        return x * y

    def divide(x, y):
        if y == 0:
            return 'Cannot divide by 0'
        return x * 1.0 / y

We are defining a Calculator class that can add, subtract, multiply, and divide. Next, we are going to create a simple Flask server to run our calculator code. Create a file api/app.py

from flask import (
    Flask,
    request,
)

from calculator import Calculator

app = Flask(__name__)

@app.route('/api/add', methods=['POST'])
def add():
    return operation('add', 2)

@app.route('/api/subtract', methods=['POST'])
def subtract():
    return operation('subtract', 2)

@app.route('/api/multiply', methods=['POST'])
def multiply():
    return operation('multiply', 2)

@app.route('/api/divide', methods=['POST'])
def divide():
    return operation('divide', 2)

def operation(method, num_factors):
    factors = []
    if num_factors == 2:
        factors.append(float(request.json.get('x')))
        factors.append(float(request.json.get('y')))

    return str(getattr(Calculator, method)(*factors))


app.run(host='0.0.0.0', port=8080)

The server accepts POST requests to the /api/add, /api/subtract, /api/multiply, and /api/divide endpoints. It expects to receive JSON values x and y as data.

Run the server

You can start the server by running

python api/app.py

in a terminal from the root directory. You can test if the server is running by hitting one of the above endpoints. Try it by running the command below.

curl -d '{"x": 1, "y": 2}' -H 'Content-Type: application/json' http://localhost:8080/api/add

You can see that the server is adding 1 and 2 together and returning 3.0.

Add backend tests

Let's add some tests for our calculator. Create a new directory tests in api and add a blank __init__.py file.

mkdir api/tests
touch api/tests/__init__.py

Write the test file test_calculator.py.

from ..calculator import Calculator


def test_add():
    assert Calculator.add(1, 2) == 3.0
    assert Calculator.add(1.0, 2.0) == 3.0
    assert Calculator.add(0, 2.0) == 2.0
    assert Calculator.add(2.0, 0) == 2.0
    assert Calculator.add(-4, 2.0) == -2.0

def test_subtract():
    assert Calculator.subtract(1, 2) == -1.0
    assert Calculator.subtract(2, 1) == 1.0
    assert Calculator.subtract(1.0, 2.0) == -1.0
    assert Calculator.subtract(0, 2.0) == -2.0
    assert Calculator.subtract(2.0, 0.0) == 2.0
    assert Calculator.subtract(-4, 2.0) == -6.0

def test_multiply():
    assert Calculator.multiply(1, 2) == 2.0
    assert Calculator.multiply(1.0, 2.0) == 2.0
    assert Calculator.multiply(0, 2.0) == 0.0
    assert Calculator.multiply(2.0, 0.0) == 0.0
    assert Calculator.multiply(-4, 2.0) == -8.0

def test_divide():
    assert Calculator.divide(1, 2) == 0.5
    assert Calculator.divide(1.0, 2.0) == 0.5
    assert Calculator.divide(0, 2.0) == 0
    assert Calculator.divide(-4, 2.0) == -2.0

Run the tests and collect code coverage

Run the command below to run tests in a terminal

pytest

However, we are more curious about the code coverage of our calculator class. We can use the command

pytest --cov api/

to show us coverage results. Doing this should give you a report that looks like

Name                           Stmts   Miss  Cover
--------------------------------------------------
api/__init__.py                    0      0   100%
api/app.py                        22     22     0%
api/calculator.py                 11      1    91%
api/tests/__init__.py              0      0   100%
api/tests/test_calculator.py      25      0   100%
--------------------------------------------------
TOTAL                             58     23    60%

Notice that api/app.py isn’t covered, as we haven’t tested the Flask application, but our api/calculatory.py file is missing tests on one line of code.

Commit and merge your changes

You can commit this code to the repository by running

git add .
git commit -m 'step1: add calculator backend and tests'
git push origin step1

Create a pull request in Bitbucket and merge the changes.
When opening pull requests, be sure to select your own repository as the base branch.