Skip to content

Testing

Focus here is on:
Styling flake8
Formatting black
Unit Test pytest
Debugger debugpy

Local testing

The gateway will be the Makefile for various test/build/deploy/run/validation needs

make test

# reference repo specific `Makefile` for additional info
# but common patterns will be
make pytest
make flake8
make black_check

We'll use tox for easily running multiple tests in a single command

tox
tox -e py3
tox -e flake8
tox -e black

Styling and Formatting

Usage of flake8 and black together will ensure code is written in a opinionated manner

In addition to the make and tox methods can be ran individually like

# flake8
flake8 --max-line-length 120 ./

# black
black --check --line-length 120 ./
black --diff --line-length 120 ./
black --line-length 120 ./

Unit Test

Commmand Line

Additional options to make and tox methods

# file or directory
pytest -vv ./<target>

# specific test
pytest -vv ./<target>::<function_name>

# test pattern name
pytest -vv ./<target> -k "pattern_name"

Skip a test with a decorator

@pytest.mark.skip(reason="Something")

vscode Unit Test integration

via settings.json

    "python.testing.nosetestsEnabled": false,
    "python.testing.unittestEnabled": false,
    "python.testing.pytestEnabled": true,
    "python.testing.pytestArgs": [
        "linecaspy"
    ],

TODO: refine further, been leveraging tox and pytest directly

Debugger

The preferred method is using launch.json but to invoke debugpy manually use a pattern

# local file 
python -m debugpy --listen 5678 ~/code/lambda-functions/health_check_py/lambda_function.py

# docker example
docker-compose exec -T pyfunctions python -m debugpy --listen 0.0.0.0:5678 --wait-for-client /git/health_check_py/lambda_function.py

# docker-compose flask command
python -m debugpy --listen 0.0.0.0:5678 --wait-for-client -m flask run --host=0.0.0.0 --port=5005

# linecaspy debugger (requires env var DEBUGGER=True)
from linecaspy.helpers.generic import HelperFunctions as PyHelpers
PyHelpers().enable_debugger()


Using the below code references for integrating debugpy will help when mount/path issues occur with breakpoints set in vscode

import debugpy  # noqa: F401

debugpy.wait_for_client()
debugpy.breakpoint()

vscode configurations

Local Python Project

via launch.json include: * NOTE: no method to support console_script CLI projects directly, must call direct file

        {
            "name": "on-aws",
            "type": "python",
            "request": "launch",
            "python": "/home/andrew/virtualenvs/py/bin/python",
            "program": "${workspaceFolder}/linecaspy/linecaspy/clients/cli_aws.py",
            "console": "integratedTerminal",
            "justMyCode": false,
            "args": [
                "--instances"
            ],
            "env": {
                "DEBUGGER": "True"
            }
        },
        {
            "name": "on-slack",
            "type": "python",
            "request": "launch",
            "python": "/home/andrew/virtualenvs/py/bin/python",
            "program": "${workspaceFolder}/linecaspy/linecaspy/clients/cli_slack.py",
            "console": "integratedTerminal",
            "justMyCode": false,
            "args": [
                "--channel", "sandbox", "--message", "Using debugger"
            ],
            "env": {
                "DEBUGGER": "True"
            },
            "envFile": "${workspaceFolder}/.vscode/.env"
        },

Lambda Functions

Diffent debugger techniques are needed for different projects like lambda-functions

In that project, there are a few key integrations

# docker-compose.yml
    ports:
      - 5365:5678

# Makefile (sample for each respective function)
health_check_py_debugpy:
    docker-compose exec -T pyfunctions python -m debugpy --listen 0.0.0.0:5678 --wait-for-client /git/health_check_py/lambda_function.py

Enable Docker and Makefile integration via launch.json like below:

        {
            "name": "lambda:funcions",
            "type": "python",
            "request": "attach",
            "port": 5365,
            "host": "localhost",
            "pathMappings": [
              {
                "localRoot": "${workspaceFolder}/lambda-functions",
                "remoteRoot": "."
              }
            ]
        },

In this workflow we would
* Set our breakpoints in vscode * Pend the lambda function for analysis

make health_check_py_debugpy 
make http_handler_py_debugpy 
make pass_fail_py_debugpy 
  • Run debugger lambda:functions

Attest - Docker

Similar to the Lambda Functions repo above, the attest repo also has different debug needs for the various dockerized services.

The workflow here can be a combination of the previous items. Where we start with the docker-compose.yml with relevant portion

    command: python ./orbit.py
    # command: python -m debugpy --listen 0.0.0.0:5678 --wait-for-client ./orbit.py
    working_dir: /git/attest/src
    volumes:
      - ./:/git
    environment:
      - DEBUGGER=True
    ports:
      - 5577:5678

Notes:
* On the port configuration, we always bind to :5678, but the external port remain differnt * Then comes the volumes and working_dir mounts that * Which allows for specific command (more on this later) or the application to be called directly * If the linecaspy debugger option is enabled, need to set environment variables DEBUGGER=True

Commands (samples)

# dependent upon your needs, the direct debugger command could look like
command: python ./app.py
command: python ./orbit.py
command: python -m debugpy --listen 0.0.0.0:5678 --wait-for-client ./orbit.py
command: python -m debugpy --listen 0.0.0.0:5678 --wait-for-client -m flask run --host=0.0.0.0 --port=5005

If the file is called directly, the debugger can still be integrated like

from linecaspy.helpers.generic import HelperFunctions as PyHelpers
PyHelpers().enable_debugger()

Which then makes my local debugger enablement process of either: * Edit the command to run python -m debugpy if desired * Set the environment variable DEBUGGER=True with linecaspy helper

Restart Specific service

make restart_orbit
# or
docker-compose stop orbit && \
docker-compose up -d orbit

Run Debugger via samples in launch.json

        {
            "name": "attest:api:werkzeug",
            "type": "python",
            "request": "attach",
            "port": 5570,
            "host": "localhost",
            "pathMappings": [
              {
                "localRoot": "${workspaceFolder}/attest/attest/src",
                "remoteRoot": "/git/attest/src"
              }
            ]
        },
        {
            "name": "attest:orbit",
            "type": "python",
            "request": "attach",
            "port": 5577,
            "host": "localhost",
            "pathMappings": [
              {
                "localRoot": "${workspaceFolder}/attest/attest/src",
                "remoteRoot": "/git/attest/src"
              }
            ]
        },
        {
            "name": "attest:worker",
            "type": "python",
            "request": "attach",
            "port": 5575,
            "host": "localhost",
            "pathMappings": [
              {
                "localRoot": "${workspaceFolder}/attest/attest/src",
                "remoteRoot": "/git/attest/src"
              }
            ]
        },

vscode Tasks

To understand file paths, create a tasks.json, and then run via Terminal -> Run Task -> echo

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "echo ${workspaceFolder}"
        }
    ]
}