Thanks to visit codestin.com
Credit goes to docs.openfaas.com

Skip to content

Unit testing with pytest

Unit test your OpenFaaS Python functions using pytest and tox. Tests run without deploying, giving fast feedback during development.

Use-cases:

  • Validating request parsing and response formatting
  • Testing business logic in isolation
  • Running tests in CI before deploying

This example shows a small calculator function that validates input with pydantic, and a test suite that exercises it by mocking the event object.

Overview

handler.py:

import json
from pydantic import BaseModel, validator

class CalcRequest(BaseModel):
    op: str
    var1: float
    var2: float

    @validator("op")
    def op_must_be_valid(cls, v):
        if v not in ("+", "-", "*", "/"):
            raise ValueError(f"unsupported operation: {v}")
        return v

def handle(event, context):
    try:
        req = CalcRequest(**json.loads(event.body))
    except Exception as e:
        return {
            "statusCode": 400,
            "body": {"error": str(e)}
        }

    if req.op == "+":
        result = req.var1 + req.var2
    elif req.op == "-":
        result = req.var1 - req.var2
    elif req.op == "*":
        result = req.var1 * req.var2
    elif req.op == "/":
        if req.var2 == 0:
            return {
                "statusCode": 400,
                "body": {"error": "division by zero"}
            }
        result = req.var1 / req.var2

    return {
        "statusCode": 200,
        "body": {"value": result}
    }

handler_test.py:

from . import handler as h
from types import SimpleNamespace

def make_event(body, method="POST"):
    return SimpleNamespace(
        body=body,
        headers={},
        path="/",
        method=method,
    )

class TestCalculator:
    def test_addition(self):
        event = make_event('{"op": "+", "var1": 1.0, "var2": 2.0}')
        resp = h.handle(event, {})
        assert resp["statusCode"] == 200
        assert resp["body"]["value"] == 3.0

    def test_subtraction(self):
        event = make_event('{"op": "-", "var1": 5.0, "var2": 3.0}')
        resp = h.handle(event, {})
        assert resp["statusCode"] == 200
        assert resp["body"]["value"] == 2.0

    def test_division_by_zero(self):
        event = make_event('{"op": "/", "var1": 1.0, "var2": 0}')
        resp = h.handle(event, {})
        assert resp["statusCode"] == 400

    def test_invalid_operator(self):
        event = make_event('{"op": "^", "var1": 1.0, "var2": 2.0}')
        resp = h.handle(event, {})
        assert resp["statusCode"] == 400

requirements.txt:

pydantic

Step-by-step walkthrough

Create the function

Pull the template and scaffold a new function:

faas-cli template store pull python3-http
faas-cli new --lang python3-http calc \
  --prefix ttl.sh/openfaas-examples

Update calc/handler.py and calc/requirements.txt with the code from the overview above.

Add a test file

The python3-http template scaffolds a tox.ini and a skeleton handler_test.py inside the function's handler directory. Replace the contents of calc/handler_test.py with the test code from the overview.

The tox.ini is preconfigured to discover and run pytest tests. You can inspect it with:

cat calc/tox.ini

Build and run the tests

Testing is disabled by default in the python3-http template. Enable it by passing --build-arg TEST_ENABLED=true to faas-cli build:

faas-cli build \
  --filter calc \
  --tag digest \
  --build-arg TEST_ENABLED=true

During the build you should see output similar to:

handler_test.py ....                                                     [100%]

========================= 4 passed in 0.14s =========================

To enable testing permanently, add TEST_ENABLED to your stack.yml:

functions:
  calc:
    lang: python3-http
    handler: ./calc
    image: ttl.sh/openfaas-examples/calc:latest
    build_args:
      TEST_ENABLED: "true"

Deploy and invoke

Build, push and deploy the function:

faas-cli up \
  --filter calc \
  --tag digest

Invoke the calculator:

curl -s http://127.0.0.1:8080/function/calc \
  -d '{"op": "+", "var1": 1, "var2": 2}'