Skip to main content

Lightweight testing utility for Python functions with profiling and logging.

Project description

testprofiler

testprofiler is a lightweight Python utility for testing individual functions with built-in execution profiling, regression testing, and test management. It logs inputs, outputs, execution time, peak memory usage, and can help version and validate function behavior.


Features

  • Easy-to-use unittestplus() function for testing any Python function.
  • Automatically compares actual vs expected output.
  • Logs:
    • Inputs (args + kwargs)
    • Execution time (in seconds)
    • Peak memory usage (in KB)
    • Output match (boolean)
    • Timestamp
    • Full function definition (as a string)
  • Extensible structure for versioning, diffs, and JSON logging.
  • Generates stable function identities based on module and function name.
  • Regression testing and test comparison utilities.
  • Lightweight serialization for complex types (DataFrames, arrays, etc.).
  • Test management: clear, delete, filter, rank, and update test metadata.

Installation

Install from PyPI:

pip install testprofiler

Requires Python 3.10 or higher.

Philosophy

testprofiler is for data scientists, ML engineers, and backend developers who want:

  • Fast feedback loops
  • Lightweight test instrumentation
  • Introspective testing without full test frameworks
  • Non-deterministic function behavior tracking (LLM outputs, random generators, etc.)

Quick Start Example

from unittestplus import unittestplus

def sum2int(a, b):
    return a + b

# Run and log a test
unittestplus(
    func=sum2int,
    inputs=[2, 3],
    expected_output=5,
    alias="Addition test",
    message="Basic addition check",
    assertion={"type": "equals", "value": 5},
    display=True
)

Test Log Structure

Each test produces a JSON log entry in func/<function_name>.json:

{
  "function": "sum2int",
  "function_id": "abc123def456",
  "test": {
    "test_id": 1,
    "test_alias": "Addition test",
    "test_message": "Basic addition check",
    "error": null,
    "error_message": null,
    "metrics": {
      "inputs": {"arg0": 2, "arg1": 3},
      "args": [2, 3],
      "kwargs": {},
      "expected_output": 5,
      "actual_output": 5,
      "output_match": true,
      "assertion": {
           "type": "equals",
           "value": 5
      },
      "assertion_passed": true,
      "execution_time_sec": 0.001,
      "peak_memory_kb": 0.789,
      "timestamp": "2025-06-20T15:30:00.000000",
      "custom_metrics": {}
    },
    "definition": "def sum2int(a, b):\n    return a + b"
  }
}

Complex types (dataframes, dicts, etc.) are stored as metadata (type, length, sample) for lightweight logs.


User-Facing API

Core Function

Function: unittestplus

Runs a function with given inputs and logs the result.

unittestplus(
    func,                # Function to test
    inputs=None,         # Positional arguments
    kwargs=None,         # Keyword arguments
    expected_output=None,# Expected output to compare against
    display=True,        # Print/log test result summary
    alias=None,          # Alias for this test
    message=None,        # Message/description for this test
    custom_metrics=None, # Custom metrics to evaluate
    assertion=None,      # Assertion dict, e.g. {"type": "equals", "value": 5}
    verbose=False        # If True, show detailed logs; if False, suppress logs
) 

All UserFacing API Function Examples

from unittestplus.core import unittestplus
from unittestplus.manipulate import run_regression
from unittestplus.testsuite import TestSuite

# --- Simple function to test ---
def add(a, b):
    return a + b

# --- Run unittestplus ---
result = unittestplus(
    func=add,
    inputs=[2, 3],
    expected_output=5,
    alias="Addition test",
    message="Basic addition check",
    assertion={"type": "equals", "value": 5},
    display=True,
)

# --- Run regression ---
regression_result = run_regression(
    func="add",  # Name as string for regression
    inputs=[[2, 3], [10, 20], [0, 0]],
    display=True,
)

# --- Run testsuite ---
suite = TestSuite()

func = "add"

suite.unittestplus(func, inputs=[5, 5])
suite.unittestplus(func, inputs=[10, 20], expected_output=30)
suite.unittestplus(func, inputs=[-5, 5], expected_output=0)
suite.unittestplus(
    func, inputs=[1, 2], expected_output=3, assertion={"type": "equals", "value": 3}
)
suite.unittestplus(
    func, inputs=[1, 2], expected_output=4, assertion={"type": "equals", "value": 3}
)
suite.unittestplus(
    func, inputs=[1, 2], expected_output=4, assertion={"type": "equals", "value": 2}
)
suite.unittestplus(func, inputs=["1", 2])
suite.run_tests()
suite.print_summary()

License

MIT License


To-Do

Documentation and housekeeping

  • Add traceback to logging
  • Refactor long functions
  • Split up modules to prevent circular imports

Publishing to PyPi

  • Validate on PyPI

Functionality to add in the future

  • Data validity checks (schemas, types)
  • More complex assertions (tolerances, regex, custom functions)
  • Bytemap strings
  • Async function support
  • Change JSON writes to either use sqllite or append-only writes
  • Concurrency (unique, sequential test ids might cause issues if multiple devs work on it)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

testprofiler-1.0.0.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

testprofiler-1.0.0-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

File details

Details for the file testprofiler-1.0.0.tar.gz.

File metadata

  • Download URL: testprofiler-1.0.0.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for testprofiler-1.0.0.tar.gz
Algorithm Hash digest
SHA256 38339602703d3576492a17c712899e41d60ee6efe1027b3b8c46a4e497bfe6f4
MD5 c78bb029fce3c2bb9e0cbc80cd65d1c3
BLAKE2b-256 6a554ab600f806978f956241e2155359b40cd1137bc17a711b66ab954b53bd29

See more details on using hashes here.

File details

Details for the file testprofiler-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: testprofiler-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 17.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for testprofiler-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 06a4804bb0c25b5a221b4b7e4d18c93d5558bcae058bca19ba7f51077bcdcae0
MD5 78a6a135b9c89344063ff2f5318a5822
BLAKE2b-256 83073cfaad0c39ab5899a15863fc03d8d4561ee12bdd7e1f27d6501bc3305dcf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page