Compare : alternative syntax for your Python asserts

expect(`your expectations`).to_be_met()

You get the idea...

Overview

Compare is a compact utility that provides an alternative, expressive syntax for comparing data values. Have you been looking for an escape from the stale XUnit style asserts that plague the omni-present unittest? You may have found just what you need. I invite you to take a look at this little utility. If it fits your style, you may use it as a drop-in replacement for the “self.assert...” style of doing assertions in python.

The compare API exposes the expect construct which allows you to compare values with readable and extensible syntax. It was designed to be a stand-alone alternative assertion syntax. As such you may use it as-is with your favorite testing/specification framework.

Documentation: http://packages.python.org/compare

Project source: https://github.com/rudylattae/compare

PyPI page: http://pypi.python.org/pypi/compare

Features

  • provides a base set of matchers for comparing values
  • easy to extend with custom matchers
  • packaged as a single drop-in module

Requirements

The core implementation of compare is a single file module with no additional requirements beyond the Python Standard Library.

Installation

The simplest and recommended way to install compare is with Pip. You may install the latest stable release from PyPI with pip:

> pip install compare

If you do not have pip, you may use easy_install:

> easy_install compare

Alternatively, you may download the source package from the compare page on PyPI, extract it and install it using:

> python setup.py install

If you wish, you may grab the in development (cutting-edge but unstable) version compare.py from the project repository and put it into your project directory.

What you get

When you install the package, you get the “expect” starter, a simple function that allows you to compare two values and fail if the outcome does not meet your expectation. This starter has extensible matchers that enable you to describe the expected outcome in a pythonic BDD manner.

Compare shines brightest when you are crafting executable specifications for your software. It helps you maintain your flow of thought without succumbing to test-focused non-pythonic distrations like “self.assertEqual(s)...”, “self.assertTrue”, etc.

Here is a trivial example of the readability you gain when you employ the “expect” construct in your specs.

> cat hello.py:

greeting = 'Hello you'

> cat hello_specs.py:

from compare import expect
import hello

expect(hello.greeting).to_equal('Hello you')

If you define an expectation that is not met, you will get an “Unmet Expectation” error which inherits from the python AssertionError so it is compatible with the usual unittest tools. Here is an example of such an error:

>>> from compare import expect
>>> opts = ['foo', 'bar', 'baz']
>>> expect(opts).to_contain('BAT')
Traceback (most recent call last):
    ...
UnmetExpectation: Expected ['foo', 'bar', 'baz'] to contain 'BAT'

What’s missing

The expect syntax does not yet have a clean way to negate a matcher. This feature is planned for the next release. An example of the anticipated usage:

expect(['a', 'c', 'd']).NOT.to_contain('b')

The to_return matcher does not accept any parameters to pass to the callable.

Matchers do not accept custom fail messages.

Feedback

I welcome any questions or feedback about bugs and suggestions on how to improve compare. Let me know what you think about compare. I am on twitter @RudyLattae . I appreciate constructive criticsms or high fives :)

Do you have suggestions for improvement? Then please create an issue with details of what you would like to see. I’ll take a look at it and work with you to either kill the idea or implement it.

Contribute

To contribute to the project, fork the compare source, make your modifications and create a pull request. I’ll be more than happy to merge in your work.

Please ensure that you provide supporting specs for your contribution. Also if you are creating a new feature or fixing a bug, I encourage you to create an issue for it in order to minimize duplication of effort.

Acknowledgements

The expect syntax used in compare was inspired by and/or builds on ideas from:

License

The compare code and documentation are released to the general public under the BSD Licence.

Copyright (c) 2011, Rudy Lattae.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of Rudy Lattae nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rudy Lattae BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Indices and tables