Python matcher utility for enhancing assertion in unit tests
Project description
PyMatcherUtil
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, andListEqto 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
unittestandpytestto 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
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 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acee33d0927136e29d409b6d4f6b7e2703748c2618b2cdae1bfee7d301d00ac3
|
|
| MD5 |
ec6b68fd87757d6e4d4f6c605ffe9aa7
|
|
| BLAKE2b-256 |
99bb926251ec50b57aa040d6efbe7721fb59d1220e05027df8df20a4b12b1827
|
Provenance
The following attestation bundles were made for pymatcherutil-0.1.2.tar.gz:
Publisher:
pypi-publish.yml on anozaki/PyMatcherUtil
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymatcherutil-0.1.2.tar.gz -
Subject digest:
acee33d0927136e29d409b6d4f6b7e2703748c2618b2cdae1bfee7d301d00ac3 - Sigstore transparency entry: 191727138
- Sigstore integration time:
-
Permalink:
anozaki/PyMatcherUtil@b466d63568a8d581a3e87bb54f801a87417976b4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/anozaki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@b466d63568a8d581a3e87bb54f801a87417976b4 -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd45432bc15beb1c5b4c35b0c61238a1ce229fcae3ac1544f2c2cf7e59b38044
|
|
| MD5 |
c139aadac37bf175c818ba74005d8907
|
|
| BLAKE2b-256 |
beef02d1eaa8fa8d20cb72f610d9c84f17bd81f862e7d48e4ef4bdbf2bbae1c7
|
Provenance
The following attestation bundles were made for pymatcherutil-0.1.2-py3-none-any.whl:
Publisher:
pypi-publish.yml on anozaki/PyMatcherUtil
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymatcherutil-0.1.2-py3-none-any.whl -
Subject digest:
bd45432bc15beb1c5b4c35b0c61238a1ce229fcae3ac1544f2c2cf7e59b38044 - Sigstore transparency entry: 191727139
- Sigstore integration time:
-
Permalink:
anozaki/PyMatcherUtil@b466d63568a8d581a3e87bb54f801a87417976b4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/anozaki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@b466d63568a8d581a3e87bb54f801a87417976b4 -
Trigger Event:
release
-
Statement type: