Skip to main content

A library for creating fluent, readable, and composable checks for your tests or application logic.

Project description

Fluent Checks

A Python library for creating fluent, readable, and composable checks for your tests or application logic.

Installation

Install the package using pip:

pip install fluent-checks

Core Concepts

The core of the library is the abstract Check class. A Check is a simple wrapper around a function that returns a boolean (Condition). For custom logic, you use CustomCheck.

from fluent_checks import CustomCheck

# Create a check from a lambda
is_even = CustomCheck(lambda: 2 % 2 == 0)

# The base class for all checks is `Check`.
# You can evaluate any check directly in a boolean context.
if is_even:
    print("It's even!")

# Or more explicitly
assert is_even.check() is True

Usage

Combining Checks

Checks can be combined using logical operators to create more complex conditions.

from fluent_checks import CustomCheck

a = CustomCheck(lambda: True)
b = CustomCheck(lambda: False)

assert (a & b).check() is False  # And
assert (a | b).check() is True   # Or
assert (~b).check() is True      # Not

Waiting for Conditions

You can wait for a condition to become true.

import time
from datetime import timedelta
from fluent_checks import CustomCheck

start_time = time.time()
wait_check = CustomCheck(lambda: time.time() - start_time > 1)

# Block indefinitely until a check passes
wait_check.wait()
assert wait_check.check() is True

# Check if something becomes true within a timeout
passing_check = CustomCheck(lambda: True).with_delay(timedelta(seconds=1))
assert passing_check.within(timedelta(seconds=2)) is True

failing_check = CustomCheck(lambda: True).with_delay(timedelta(seconds=2))
assert failing_check.within(timedelta(seconds=1)) is False

# `eventually` is a convenient alias for `within`
assert passing_check.eventually(timedelta(seconds=2)) is True

Repeating Checks

You can verify that a condition holds true multiple times.

import random
from fluent_checks import CustomCheck

# any_attempt: True if the check passes at least once in 10 attempts
flaky_check = CustomCheck(lambda: random.random() > 0.8)
flaky_check.any_attempt(10)

# all_attempts: True if the check passes 5 times in a row
stable_check = CustomCheck(lambda: True)
assert stable_check.all_attempts(5)

Background Checks

You can run any check in a background thread.

import time
from datetime import timedelta
from fluent_checks import CustomCheck

# Run a long-running check in the background
long_check = CustomCheck(lambda: True).with_delay(timedelta(seconds=1))
background_check = long_check.background()

# You can start it and check on it later
background_check.start()
assert background_check.is_finished().check() is False
time.sleep(1.1)
assert background_check.is_finished().check() is True
assert background_check.result() is True

Checking for Exceptions

You can check that a piece of code raises a specific exception.

from fluent_checks import CustomCheck

def might_fail():
    raise ValueError("Something went wrong")

check = CustomCheck(might_fail).raises(ValueError)

assert check.check() is True

Callbacks

You can add callbacks to your checks that will be executed on success or on failure.

from fluent_checks import CustomCheck

a = CustomCheck(lambda: True)
a.on_success(lambda: print("I've passed"))
a.on_failure(lambda: print("I've failed"))

a.check() # This will print "I've passed"

File System Checks

You can use pre-built factory functions to check the file system.

from pathlib import Path
from fluent_checks import file_exists, dir_exists, file_contains

# (Example using pytest's tmp_path fixture)
def test_fs(tmp_path: Path):
    # Check if a file exists
    my_file = tmp_path / "file.txt"
    my_file.touch()
    assert file_exists(my_file)

    # Check if a directory exists
    my_dir = tmp_path / "dir"
    my_dir.mkdir()
    assert dir_exists(my_dir)

    # Check if a file contains specific content
    my_file.write_text("hello")
    assert file_contains(my_file, b"hello")

Comparison Checks

You can use factory functions to compare values.

from fluent_checks import is_equal, is_not_equal, is_greater_than, is_less_than, is_in, is_instance_of

# Equality
assert is_equal(1, 1)
assert is_not_equal(1, 2)

# Comparison
assert is_greater_than(2, 1)
assert is_less_than(1, 2)

# Containment
assert is_in(1, [1, 2, 3])

# Instance
assert is_instance_of(1, int)

API Overview

Base Check Methods

Method Description
.check() Evaluates the check and returns the boolean result.
&, |, ~ Operators for AND, OR, and NOT logic.
.on_success(callback) Registers a callback to be executed when the check succeeds.
.on_failure(callback) Registers a callback to be executed when the check fails.
.all_attempts(times) Checks if the condition is met consecutively for a number of tries.
.any_attempt(times) Checks if the condition is met at least once within a number of tries.
.before(deadline) Checks if the condition becomes true before a specific datetime.
.within(timeout) Checks if the condition becomes true within a certain timedelta.
.eventually(timeout) An alias for within.
.wait() Blocks indefinitely until the check returns True.
.raises(exception) Checks if the condition raises a specific exception.
.with_delay(delay) Returns a new check that waits for a delay before executing.
.background() Returns a BackgroundCheck wrapper to run the check in a thread.

Filesystem Functions

Function Description
file_exists(path: Path) Checks if a file exists at the given path.
dir_exists(path: Path) Checks if a directory exists at the given path.
file_contains(path: Path, content: bytes) Checks if a file contains the given bytes.

Comparison Functions

Function Description
is_equal(left, right) Checks if left == right.
is_not_equal(left, right) Checks if left != right.
is_greater_than(left, right) Checks if left > right.
is_less_than(left, right) Checks if left < right.
is_in(member, container) Checks if member in container.
is_instance_of(obj, class_or_tuple) Checks if isinstance(obj, class_or_tuple).

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

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

fluent_checks-0.4.0.tar.gz (5.5 kB view details)

Uploaded Source

Built Distribution

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

fluent_checks-0.4.0-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

Details for the file fluent_checks-0.4.0.tar.gz.

File metadata

  • Download URL: fluent_checks-0.4.0.tar.gz
  • Upload date:
  • Size: 5.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fluent_checks-0.4.0.tar.gz
Algorithm Hash digest
SHA256 e142f735e66b1c71ff270fd290d2eb936f66969b92996833e0af44e8aa55ecee
MD5 1f582636ebddf8ae9f961a491afff6b4
BLAKE2b-256 b8808b899e12307ef81b613ff65cde834ccd99b80e25ce4d776f89be160c7ab9

See more details on using hashes here.

File details

Details for the file fluent_checks-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: fluent_checks-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 6.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fluent_checks-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 afad8b527369e5b6a0c0fd21cc54303e58bb7dcda3b1c232f55517253f081be4
MD5 5a9f5f6236ef8a3dd90af23254b34c3d
BLAKE2b-256 a580c1641762210c4035e79d7b59e139fdea3b48f159fe626a50d4b8d9a85df1

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