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
testprofiler()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 testprofiler import testprofiler
def sum2int(a, b):
return a + b
# Run and log a test
testprofiler(
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: testprofiler
Runs a function with given inputs and logs the result.
testprofiler(
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 testprofiler import testprofiler, run_regression, TestSuite
# --- Simple function to test ---
def add(a, b):
return a + b
# --- Run testprofiler ---
result = testprofiler(
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.testprofiler(func, inputs=[5, 5])
suite.testprofiler(func, inputs=[10, 20], expected_output=30)
suite.testprofiler(func, inputs=[-5, 5], expected_output=0)
suite.testprofiler(
func, inputs=[1, 2], expected_output=3, assertion={"type": "equals", "value": 3}
)
suite.testprofiler(
func, inputs=[1, 2], expected_output=4, assertion={"type": "equals", "value": 3}
)
suite.testprofiler(
func, inputs=[1, 2], expected_output=4, assertion={"type": "equals", "value": 2}
)
suite.testprofiler(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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file testprofiler-1.0.1.tar.gz.
File metadata
- Download URL: testprofiler-1.0.1.tar.gz
- Upload date:
- Size: 20.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9a30b1a67cfb4d6d6fa59eec22bc2dbb51e777fa87e2a6e1cc8987e02112369
|
|
| MD5 |
69dfae93517dd75667d92513e611a13c
|
|
| BLAKE2b-256 |
9d245bf69409a163a10f5035f4f1a6af06f32fabe18199213bcab2676fecdc67
|
File details
Details for the file testprofiler-1.0.1-py3-none-any.whl.
File metadata
- Download URL: testprofiler-1.0.1-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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03b01c14e3526f884b722626b3bd6263e2891f0c2988f72e44006bd7944ba1b0
|
|
| MD5 |
a420bc05f6d366c4a8d49a8d4d928a6e
|
|
| BLAKE2b-256 |
d10f4ae8a917669b1bc090b5c6b02067d006416a85eab288431145bb62cc315d
|