Skip to main content

Add your description here

Project description

Sixma

PyPI - Version PyPi - Python Version Github - Open Issues PyPi - Downloads (Monthly) Github - Commits

Probabilistic Correctness & Logical Falsification for Python.

"Stop writing unit tests. Start certifying reliability."

Sixma is a testing framework that replaces manual test cases with Generative Spaces and Statistical Certification. Instead of checking if f(2) == 4, you define the invariant f(x) == x^2 and Sixma proves it holds true with a specific Reliability and Confidence Level.

It uses the Zero-Failure Reliability model to dynamically calculate the required number of random trials ($N$) to certify your system is bug-free.

📦 Installation

uv add sixma
# or
pip install sixma

🚀 Quick Start: The 3 Ways to Write Tests

Sixma is flexible. Choose the syntax that fits your project's strictness level.

1. The Production Way (Recommended) ⭐

Use standard Python type hints combined with Default Values.

  • Pros: 100% compatible with mypy, pyright, and IDE autocomplete.
  • Cons: Slightly more verbose.
from sixma import certify, generators as g

@certify(reliability=0.999, confidence=0.95)
def test_math(
    # Mypy sees 'int'. Sixma sees the generator in the default value.
    x: int = g.Integer(0, 100),
    y: int = g.Integer(0, 100)
):
    assert x + y == y + x

2. The Prototyping Way (Shortcut) ⚡

Use the generator instance directly as the type hint.

  • Pros: Fastest to write. Very clean to read.
  • Cons: Static type checkers (mypy) will complain that "Integer is not a type".
@certify
def test_math(
    # Fast to write, but upsets strict type checkers
    x: g.Integer(0, 100),
    # or even as default value
    y = g.Integer(0, 100),
):
    assert x + y == y + x

3. The Strict Way (Annotated) 🧐

Use Python's standard typing.Annotated.

  • Pros: The "Academic" standard for metadata. Mypy compliant.
  • Cons: Very verbose.
from typing import Annotated

@certify
def test_math(
    x: Annotated[int, g.Integer(0, 100)],
    y: Annotated[int, g.Integer(0, 100)]
):
    assert x + y == y + x

4. The Pick-Based Way (Stateful & Coupled) 🎲

For tests where inputs are coupled to control flow — state machines, op sequences, anything where "the next value depends on what we just did" — declare a ctx parameter. The framework injects a PickContext the body pulls values from on demand.

from sixma import certify

@certify(reliability=0.999, confidence=0.95, max_picks_per_trial=100)
def test_stack_lifo(ctx):
    stack, reference = [], []
    while ctx.pick("op", "stop") == "op":
        if ctx.pick("push", "pop") == "push":
            x = ctx.range(0, 100)
            stack.append(x)
            reference.append(x)
        else:
            if not reference:
                ctx.discard()
            assert stack.pop() == reference.pop()
  • ctx.pick(*options, label=None) — uniformly random choice from the options.
  • ctx.range(low, high, label=None) — integer in [low, high] inclusive.
  • ctx.discard() — equivalent to require(False); the trial doesn't count toward N or the failure tally.

Semantic shift. Under picks, reliability characterizes the fraction of the test body's induced path distribution that passes — not an external input space. Bugs hiding behind unlikely pick sequences are exponentially under-sampled by uniform sampling; restructure the body or use ctx.discard() to bias the distribution toward interesting paths.

Mixing. A body may declare both default-value generators and ctx:

@certify
def test_mixed(x: int = g.Integer(0, 100), ctx=None):
    while ctx.pick(True, False):
        x += ctx.range(-10, 10)
    assert -10000 < x < 10000

Failure traces show the ordered list of picks plus the seed for reproduction:

❌ Falsified at trial 412!
   Seed: 84920174 (Set SIXMA_SEED=84920174 to reproduce)
   Trace:
     loop = 'op'
     action = 'push'
     value = 42
     loop = 'op'
     action = 'pop'
   Error: AssertionError

🧠 The Philosophy

Standard property-based testing runs an arbitrary number of tests (e.g., 100). Sixma inverts this: You tell the framework how confident you want to be.

The number of trials is calculated dynamically using the Zero-Failure Testing formula:

$$ N = \left\lceil \frac{\ln(1 - C)}{\ln(R)} \right\rceil $$

Reliability Confidence Trials Required Use Case
0.90 0.95 29 MVP / Quick Smoke Tests
0.99 0.99 459 Standard Business Logic
0.999 0.99 4,603 Core Algorithms
0.9999 0.999 69,075 Critical Infrastructure
  • Reliability: The probability that the code will NOT fail on a random input.
  • Confidence: The probability that our estimation of is correct.

🛠 Features

1. Smart Generators (Edge Cases First)

Sixma generators are finite iterators first. They always yield critical edge cases (0, -1, empty strings, boundaries, leap years) before switching to random sampling.

# Yields: 0, 10, 1, -1, 5, 8, ...
x: int = g.Integer(0, 10)

2. Dependent Variables (g.Case)

Define inputs that depend on each other without wasteful rejection sampling.

@certify
def test_slicing(
    # 'case' generates a namespace where fields depend on previous ones
    case: SimpleNamespace = g.Case(
        # 1. Independent Variable
        size = g.Integer(1, 100),

        # 2. Dependent: start must be within size
        start = lambda size: g.Integer(0, size - 1),

        # 3. Dependent: end must be > start
        end = lambda start, size: g.Integer(start + 1, size)
    )
):
    # Inputs are guaranteed to be valid!
    # Mypy Tip: Use SimpleNamespace or a custom class for type hints.
    data = list(range(case.size))
    chunk = data[case.start : case.end]

    assert len(chunk) == case.end - case.start

3. Time Travel (Temporal Testing)

Generate valid dates, times, and windows easily. Handles leap years automatically.

from datetime import date

# Define a Business Quarter
Q1_2024 = g.Date(date(2024, 1, 1), date(2024, 3, 31))

@certify
def test_quarterly_report(day: date = Q1_2024):
    assert day.year == 2024
    assert 1 <= day.month <= 3

4. Reproducibility (Seeding)

Statistical tests must be reproducible. If a test fails, Sixma prints the Random Seed used in the logs.

Output on Failure:

❌ Falsified at trial 412!
   Seed: 84920174 (Set SIXMA_SEED=84920174 to reproduce)
   Inputs: {'x': -5}
   Error: assert -5 > 0

Reproduce it locally:

SIXMA_SEED=84920174 pytest tests/test_my_logic.py

5. Auto-Shrinking (Debuggability)

When a test fails on a complex input (e.g., a list of 50 items), Sixma automatically re-runs the test with the Simplest Case (e.g., empty list) to see if the bug persists.

❌ Falsified at trial 55!
   Inputs: {'items': [23, 99, ... 48 more]}
   📉 Minimal Counter-Example: {'items': []}

📚 API Reference

@certify(reliability, confidence, max_discards, max_picks_per_trial)

The main decorator.

  • reliability: Target probability of success (0.0 - 1.0).
  • confidence: Statistical significance level (0.0 - 1.0).
  • max_discards: Safety valve — caps the number of discarded trials (require() failures and ctx.discard() calls combined).
  • max_picks_per_trial: Safety valve for divergent test bodies that loop on ctx.pick(...). Default 1000. Exceeding it discards the trial.

Generators (sixma.generators)

All generators are available as factory functions compatible with Mypy.

  • Primitives: Integer, Float, Bool, String
  • Combinators:
    • List(gen, min_len, max_len)
    • Dict(key=gen, ...)
    • Object(Cls, field=gen, ...)
  • Logic:
    • Case(field=gen, dependent_field=lambda prev: gen)
  • Temporal:
    • Date(start, end)
    • DateTime(start, end)

📄 License

MIT License.

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

sixma-0.5.0.tar.gz (49.9 kB view details)

Uploaded Source

Built Distribution

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

sixma-0.5.0-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file sixma-0.5.0.tar.gz.

File metadata

  • Download URL: sixma-0.5.0.tar.gz
  • Upload date:
  • Size: 49.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sixma-0.5.0.tar.gz
Algorithm Hash digest
SHA256 be9ad201db0b63a74ba15b6334baec714ddb59b7008660862557aca5c174c064
MD5 ca5e9e2f24b4f3359c4c6e1ffa8278b3
BLAKE2b-256 f08b5cc74b54013cd553aec165298eda18794d2b085b79546c466308255c169b

See more details on using hashes here.

File details

Details for the file sixma-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: sixma-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 11.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sixma-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 27436a64d018f7810fb3dd4da9a5e818b40a531d44acdc0aec1906eaf9686fac
MD5 cb787a4eb0c1a5c97e14ea71787b37e7
BLAKE2b-256 eeca2d382fa758e9023405661391eaccbfe10f08fc84ac192a4ab6823f26c16f

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