Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Simple powerful testing with py.test

Avatar for Andreas Hug Andreas Hug
November 20, 2012

Simple powerful testing with py.test

Talk at Django usergroup Berlin about py.test

Avatar for Andreas Hug

Andreas Hug

November 20, 2012

Other Decks in Programming

Transcript

  1. FEATURES • assert statements • auto-discovery • modular fixtures •

    multi-paradigm support (unittest, nose) • markers • easy configuration • plugins
  2. ASSERT • standard assert instead of assertXXX • assert that

    exceptions are raised assert x == 1 assert x != 1 assert x in [1, 2, 3] assert x < 5 pytest.raises(ZeroDivisionError, lambda x: 1 / x, 0) with pytest.raises(ZeroDivisionError): 1 / 0
  3. ASSERT • descriptive feedback def test_x(): > assert sum(range(3)) ==

    4 E assert 3 == 4 E + where 3 = sum([0, 1, 2]) E + where [0, 1, 2] = range(3) def test_list(): > assert [1, 2, 3] == [1, 2] E assert [1, 2, 3] == [1, 2] E Left contains more items, first extra item: 3 def test_long(): a = '-'*50 + 'a' + '-'*50 b = '-'*50 + 'b' + '-'*50 > assert a == b E assert '--------...---------' == '---------...---------' E Skipping 44 identical leading characters in diff E Skipping 45 identical trailing characters in diff E - ----------a--------- E ? ^ E + ----------b--------- E ? ^
  4. AUTO-DISCOVERY • single file by path • multiple files by

    recursive detection • specific packages with --pyargs !"" foopackage # !"" foomodule.py # $"" tests # $"" test_foomodule.py $"" tests $"" test_foomodule.py $ py.test $ py.test foopackage/tests/ $ py.test foopackage/tests/test_foomodule.py $ py.test --pyargs foopackage
  5. AUTO-DISCOVERY • all functions and methods prefixed with test_ •

    all classes prefixed with Test • specific functions or classes with -k from foopackage import foomodule def test_add(): assert foomodule.add(1, 2) == 3 class TestFoo(object): def test_negative(self): assert foomodule.add(1, -1) == 0 $ py.test -k "TestFoo and test_negative"
  6. FIXTURES • sets up objects or apps for testing •

    used via dependency injection import pytest @pytest.fixture def foo(): return 'foo' def test_something(foo): assert foo == 'bar'
  7. FIXTURES • function, class module and session scope import pytest

    @pytest.fixture(scope='module') def foo(): time.sleep(2) return 'foo' def test_something(foo): assert foo == 'bar' def test_something_else(foo): assert foo == 'baz'
  8. FIXTURES • function, class module and session scope import pytest

    @pytest.fixture() def foo(): pass @pytest.mark.usefixtures('foo') class TestClass(object): def test_something(self): assert 1 == 1 def test_something_else(self): assert 2 == 2
  9. FIXTURES • function, class module and session scope import pytest

    class TestClass(object): @pytest.fixture(autouse=True) def foo(self): pass def test_something(self): assert 1 == 1 def test_something_else(self): assert 2 == 2
  10. FIXTURES • finalizer @pytest.fixture def foo(request): # create something def

    clean_up(): # destroy something request.addfinalizer(clean_up)
  11. FIXTURES • parametrization of fixtures and test functions import pytest

    @pytest.mark.parametrize(('foo', 'bar'), [(1, 2), (1, 3)]) def test_with_parameters(foo, bar): assert foo == bar import pytest @pytest.fixture(params=[1, 2]) def foo(request): return request.param def test_something(foo): assert foo == 3
  12. MULTI-PARADIGM SUPPORT • supports unittest and nose style tests from

    unittest import TestCase class TestUser(TestCase): @classmethod def setUpClass(cls): cls.foo = 1 def setUp(self): self.bar = 2 def test_something(self): assert self.foo == self.bar
  13. MARKERS • supports unittest and nose style tests import pytest

    @pytest.mark.slowtest def test_something(): assert 1 $ py.test -m slowtest
  14. PLUGINS • several plugins available: • pytest-twisted • pytest-capturelog •

    pytest-xdist • pytest-timeout • pytest-cache • pytest-cov • pytest-pep8
  15. PLUGINS • easy to write custom plugins def pytest_addoption(parser): """Define

    additional commandline options""" group = parser.getgroup('fooplugin') group.addoption('--foo', action='store_true', default=False) def pytest_configure(config): """Activate plugin if according option is set""" if config.getvalue('active'): config.pluginmanager.register(FooPlugin()) class FooPlugin(object): def pytest_sessionstart(self, session): pass def pytest_sessionfinish(self, session, exitstatus): pass
  16. THX

  17. Moccu GmbH & Co. KG Kreativagentur für digitale Medien Pappelallee

    10 10437 Berlin Tel: +49 (0)30 - 44 01 30 - 30 Fax: +49 (0)30 - 44 01 30 - 50 E-Mail: [email protected] Web: www.moccu.com Facebook: facebook.com/moccu Twitter: moccu Youtube: youtube.com/moccu Willkommen! KONTAKT