Skip to main content

Python matcher utility for enhancing assertion in unit tests

Project description

PyMatcherUtil

python codecov

Introduction

PyMatcherUtil — a tailored library of custom matchers designed to extend the capabilities of Python's unittest.mock for more comprehensive and expressive testing assertions. As testing becomes an integral part of software development, having sophisticated, reusable, and expressive testing utilities can significantly enhance the quality of your codebase. unittest.mock` for more comprehensive and expressive testing assertions.

Installation

You can install PyMatcherUtil using the following pip command:

python -m pip install https://github.com/anozaki/PyMatcherUtil/tarball/master

Key Features

  • Custom Matchers: Gain access to a variety of pre-built matchers such as All, Eq, NotEq, Called, NotCalled, All, IsInstance, PropEq, DictEq, and ListEq to validate different aspects of your objects and mocks..
  • Expressive Assertions: Write expressive and self-explanatory tests that improve readability and maintainability.
  • Integration with Existing Frameworks: Seamlessly integrate with standard testing frameworks such as unittest and pytest to leverage familiar testing ecosystems.
  • Reusable Testing Utilities: Centralize your testing logic and reuse it across multiple projects, promoting DRY (Don't Repeat Yourself) principles.

Examples

Basic Example

This example demonstrates the use of custom matchers from the pymatcher_utils library to perform advanced assertions in unit tests. The function sum_value takes two numbers, adds them, and returns the floor of the sum as an integer. The test test_sum_value uses the pytest.mark.parametrize decorator to define several test cases. It showcases the use of matchers All, Eq, and IsInstance from the library to check that the results meet specific conditions, such as being equal to a specific value and being an instance of a given type.

import math
import pytest
from pymatcher_utils import All, Eq, IsInstance, check_value

def sum_value(a: int | float, b: int | float) -> int:
  return int(math.floor(a + b))

@pytest.mark.paramertrize("a_value, b_value, expect", [
  # normal without lib
  (1, 5, 6),
  
  # check value is equal
  # check returned instance is int
  (5, 7, All(Eq(12), IsInstance(int))),
  
  # check result that is < <n>.5 to make sure it is floored
  # check result is int
  (5.1, 7.1, All(Eq(12), IsInstance(int))),
  
  # check result that is > <n>.5 to make sure it is floored
  # check result is int
  (5.5, 7.1, All(Eq(12), IsInstance(int))),
  
  # check float and int input
  #   check output result is 12
  #   make sure we got back int
  (5.1, 7, All(Eq(12), IsInstance(int))),
])
def test_sum_value(a_value, b_value, expect):
    result = sum_value(a_value, b_value)
    check_value(result, expect)

Testing Class

This example further explores the application of custom matchers to test a class, SumValue, which encapsulates the addition operation. The test test_sum_value also uses pytest.mark.parametrize for defining test cases involving object properties. The PropEq matcher is used to assert that the properties of SumValue instances meet the expected values. The example includes dynamic property updates using set_properties and demonstrates how to verify the result using a combination of property matchers and type matchers, ensuring the result is correctly calculated and its type is verified.

import math

import pytest

from pymatcher_utils import set_properties, PropEq, IsInstance, All, check_value, Eq


class SumValue:

    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.result = None

    def sum(self) -> int:
        self.result = int(math.floor(self.a + self.b))
        return self.result


@pytest.mark.parametrize(
    "value_a, value_b, update, expect",
    [
        (1, 2, None, {"a": 1, "b": 2, "result": 3}),
        (1.2, 3.1, None, PropEq({"a": 1.2, "b": 3.1, "result": 4})),
        (1.2, 3.4, None, PropEq({"a": 1.2, "b": 3.4, "result": 4})),
        (
            1.2,
            3.4,
            {"b": 4.4},
            # PropEq can be a dict or variable list
            PropEq(
                a=1.2,
                b=4.4,
                # checking result using matchers
                result=All(
                    Eq(5),
                    IsInstance(int),
                ),
            ),
        ),
    ],
)
def test_sum_value(value_a, value_b, update, expect):
    target = SumValue(value_a, value_b)
    if update is not None:
        set_properties(target, update)
    target.sum()

    check_value(target, expect)

Other Examples

See example folder for additional usage example.

License

See the LICENSE file for license rights and limitations (MIT).

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

pymatcherutil-0.1.2.tar.gz (40.6 kB view details)

Uploaded Source

Built Distribution

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

pymatcherutil-0.1.2-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file pymatcherutil-0.1.2.tar.gz.

File metadata

  • Download URL: pymatcherutil-0.1.2.tar.gz
  • Upload date:
  • Size: 40.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pymatcherutil-0.1.2.tar.gz
Algorithm Hash digest
SHA256 acee33d0927136e29d409b6d4f6b7e2703748c2618b2cdae1bfee7d301d00ac3
MD5 ec6b68fd87757d6e4d4f6c605ffe9aa7
BLAKE2b-256 99bb926251ec50b57aa040d6efbe7721fb59d1220e05027df8df20a4b12b1827

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymatcherutil-0.1.2.tar.gz:

Publisher: pypi-publish.yml on anozaki/PyMatcherUtil

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pymatcherutil-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: pymatcherutil-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pymatcherutil-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 bd45432bc15beb1c5b4c35b0c61238a1ce229fcae3ac1544f2c2cf7e59b38044
MD5 c139aadac37bf175c818ba74005d8907
BLAKE2b-256 beef02d1eaa8fa8d20cb72f610d9c84f17bd81f862e7d48e4ef4bdbf2bbae1c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymatcherutil-0.1.2-py3-none-any.whl:

Publisher: pypi-publish.yml on anozaki/PyMatcherUtil

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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