grappa-py/grappa

View on GitHub
docs/integrations.rst

Summary

Maintainability
Test Coverage
Integrations
============

``grappa`` is library/framework agnostic, so you can use it with your preferred
testing framework, such as `nose`, `pytest`, `behave`...

This page provides some useful information and configuration tips
for a better and more friendly integration between ``grappa`` and
testing framework.

pytest
------

Friendly error traceback
^^^^^^^^^^^^^^^^^^^^^^^^

``pytest``, by default, provides a custom error reporting based on the traceback
analysis, pretty much as ``grappa`` does, but unfortunately in a less friendly way
for the developer.

You can partially or completely disable this in ``pytest`` behavior in order to have
more friendly errors generated by ``grappa``.

In order to do that you should simply pass the following flag to:

.. code-block:: bash

    $ pytest --tb=native

Or alternatively, you can simply partially disable it:

.. code-block:: bash

    $ pytest --tb=short


The difference would be from this:

.. code-block:: bash

    ________________ test_expect_context_manager ________________
    tests/should_test.py:277: in test_expect_context_manager
        should('foo').be.equal('bar')
    grappa/assertion.py:16: in __call__
        return self._fn(expected, *args, **kw)
    grappa/resolver.py:60: in wrapper
        return self.test._trigger()
    grappa/test.py:145: in _trigger
        raise err
    E   AssertionError: Oops! Something went wrong!
    E
    E     The following assertion was not satisfied
    E       subject "foo" should be equal "bar"
    E
    E     What we expected
    E       a value that is equal to "foo"
    E
    E     What we got instead
    E       an value of type "str" with data "foo"
    E
    E     Where
    E       File "tests/should_test.py", line 277, in test_expect_context_manager
    E
    E       269|      with pytest.raises(AssertionError):
    E       270|          10 | should.not_be.between.to(5, 10)
    E       271|
    E       272|      with pytest.raises(AssertionError):
    E       273|          None | should.be.between.numbers(10, 10)
    E       274|
    E       275|
    E       276|  def test_expect_context_manager():
    E       277| >    should('foo').be.equal('bar')
    E       278|
    E       279|      with should('foo'):
    E       280|          should.be.equal('foo')
    E       281|          should.have.length.of(3)
    E       282|          should.have.type('string')
    E       283|
    E       284|      with should('foo'):

Into this:

.. code-block:: bash

    Traceback (most recent call last):
      File "tests/should_test.py", line 277, in test_expect_context_manager
        should('foo').be.equal('bar')
      File "grappa/assertion.py", line 16, in __call__
        return self._fn(expected, *args, **kw)
      File "grappa/resolver.py", line 60, in wrapper
        return self.test._trigger()
      File "grappa/test.py", line 145, in _trigger
        raise err
    AssertionError: Oops! Something went wrong!

      The following assertion was not satisfied
        subject "foo" should be equal "bar"

      What we expected
        a value that is equal to "foo"

      What we got instead
        an value of type "str" with data "foo"

      Where
        File "tests/should_test.py", line 277, in test_expect_context_manager

        269|      with pytest.raises(AssertionError):
        270|          10 | should.not_be.between.to(5, 10)
        271|
        272|      with pytest.raises(AssertionError):
        273|          None | should.be.between.numbers(10, 10)
        274|
        275|
        276|  def test_expect_context_manager():
        277| >    should('foo').be.equal('bar')
        278|
        279|      with should('foo'):
        280|          should.be.equal('foo')
        281|          should.have.length.of(3)
        282|          should.have.type('string')
        283|
        284|      with should('foo'):


Dependency injection using fixtures
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In order to minimize boilerplate across tests, you can create a ``pytest`` fixture
that would be automatically injected via across test functions/methods in your test suites:

First, create a ``conftest.py`` file in the directory where your test files lives with the following content:

.. code-block:: python

    # tests/conftest.py
    import pytest
    from grappa import should as _should, expect as _expect

    @pytest.fixture
    def should():
        return _should


    @pytest.fixture
    def expect():
        return _expect

Then, from a test file module, you can simply declare a test function that accepts a fixture argument, such as:

.. code-block:: python

    # tests/sample_test.py

    def test_should_fixture(should):
        'foo' | should.have.length.of(3) | should.be.equal.to('foo')


    def test_expect_fixture(expect):
        'foo' | expect.to.have.length.of(3) | expect.to.be.equal.to('foo')