Skip to main content

equals: Enhanced Equality Testing for Python

PyPI version Documentation Status Coverage Status

equals is a Python library that provides flexible equality assertions for testing. Think of it as a more powerful version of Mock.Any that gives you fine-grained control over how objects are compared.

Why Use equals?

When writing tests with mocks and stubs, exact matching can make tests brittle and hard to maintain. Often, you care about certain properties of an object but not others. For example:

  • In integration tests, timestamps or UUIDs might change between test runs
  • When mocking API responses, you may only care about specific fields
  • Testing event handlers where message format may evolve over time
  • Verifying call arguments where some data is non-deterministic

equals helps you write more maintainable tests by focusing on the properties that matter for your test cases, making your test suite more robust and easier to maintain.

The equals library provides a rich set of fuzzy matching capabilities that go beyond exact equality comparisons. Each matcher type (string, number, dictionary, etc.) implements its own set of flexible matching rules, allowing you to write tests that focus on the important aspects of your data while ignoring irrelevant details. These matchers can be combined and chained to create sophisticated matching patterns that make your tests both robust and maintainable.

Quick Examples

The equals library enables flexible matching in tests through partial equality checks:

  • Match dictionaries by key presence or content
  • Match strings by pattern or content
  • Chain multiple conditions for complex matching

With Mock and pytest

import pytest
from unittest.mock import Mock  # Using unittest.mock instead of mock package
from equals import any_dict, any_string

def test_mock_multiple_calls():
    # Arrange
    mock_service = Mock()
    
    # Act
    mock_service.update({'name': 'bob'})
    mock_service.update({'name': 'alice'})
    
    # Assert
    assert mock_service.update.call_count == 2
    mock_service.update.assert_any_call(any_dict.containing(name=any_string))

With dobles and pytest

import pytest
from dobles import expect
from equals import any_string

class UserService:
    def validate_email(self, email: str) -> bool:
        return '@' in email

@pytest.fixture
def user_service():
    return UserService()

def test_email_validation(user_service):
    # Arrange
    expect(user_service).validate_email.with_args(
        any_string.containing('@').and_containing('.')
    ).and_return(True)
    
    # Act & Assert
    assert user_service.validate_email('test@example.com')

Fuzzy Matching Capabilities

String Matching

from equals import any_string

assert any_string.containing('abc') == '123 abc 456'     # Substring
assert any_string.starting_with('abc') == 'abcdef'       # Prefix
assert any_string.ending_with('abc') == '123abc'         # Suffix
assert any_string.matching('^abc$') == 'abc'             # Regex

Number Comparisons

from equals import any_number

assert any_number.less_than(5) == 4               # Less than
assert any_number.between(1, 3) == 2              # Range
assert any_number.greater_than(4) == 5            # Greater than

Dictionary Validation

from equals import any_dict

assert any_dict.containing(foo='bar') == {'foo': 'bar', 'other': 'value'}
assert any_dict.not_containing(foo=5) == {'foo': 3, 'bar': 5}

Iterable Operations

from equals import any_iterable

assert any_iterable.containing(1, 2) == [1, 2, 3]        # Contains elements
assert any_iterable.containing_only(1, 2) == [2, 1]      # Exact elements, any order
assert any_iterable.with_length(2) == [3, 4]             # Length check

Object Matching

from equals import anything, instance_of

assert anything == 'any value'                           # Match anything
assert instance_of(dict) == {}                          # Type check
assert anything.with_attrs(foo='bar') == obj            # Attribute check

Installation

pip install equals

Development

The source code is available on GitHub.

Getting Started

# Install dependencies
make bootstrap

# Run tests
make test

# Build documentation
make docs

Documentation

Full documentation is available at equals.readthedocs.org.

License

MIT License

Metadata

Release files for equals 3.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for equals 3.1.2
File Size Uploaded
equals-3.1.2.tar.gz 8.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for equals 3.1.2
File Interpreter ABI Platform
equals-3.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 19.8 kB

Release files / equals-3.1.2.tar.gz

Download URL equals-3.1.2.tar.gz
Size 8.3 kB
Tags Source
SHA-256 checksum
How to use checksums
fdbcf1a3896e859a54c65e36a7c71b4ff851d31654d98019a8e35db23b7d6a86
BLAKE2b-256 checksum
How to use checksums
905bec9960e33849110a1e84fe67b71ce07e3ee1f69d68eb3a71eae409793aeb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.12.1 Darwin/24.3.0

Release files / equals-3.1.2-py3-none-any.whl

Download URL equals-3.1.2-py3-none-any.whl
Size 11.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0142bf73dd89ae380800d3d2a957c0c44b834970be1794a43eeffe7740330835
BLAKE2b-256 checksum
How to use checksums
7b966e95f91fbc8292ee63ba3f5ef07942e8b141d74c4908fffdc3f3d8fec51e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.7.1 CPython/3.12.1 Darwin/24.3.0

Release history Release notifications | RSS feed

This release

3.1.2 This release

2 release files

3.1.1

2 release files

3.1.0

2 release files

1.0.0

2 release files

0.0.25

1 release file

0.0.24

1 release file

0.0.23

1 release file

0.0.22

1 release file

0.0.21

1 release file

0.0.2

1 release file

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page