pytest: escreva menos, teste mais
TRANSCRIPT
pytest
por quê?
~100K L
menos verboso
import unittest
class SomethingTestCase(unittest.TestCase): def test_something(self): self.assertNotEqual('foobar'.upper(), 'FOOBAR')
if __name__ == '__main__': unittest.main()
import unittest
class SomethingTestCase(unittest.TestCase): def test_something(self): self.assertNotEqual('foobar'.upper(), 'FOOBAR')
if __name__ == '__main__': unittest.main()
import unittest
class SomethingTestCase(unittest.TestCase): def test_something(self): assert 'foobar'.upper() != 'FOOBAR'
if __name__ == '__main__': unittest.main()
import unittest
class SomethingTestCase(unittest.TestCase): def test_something(self): assert 'foobar'.upper() != 'FOOBAR'
if __name__ == '__main__': unittest.main()
import unittest
class SomethingTestCase(unittest.TestCase): def test_something(self): assert 'foobar'.upper() != 'FOOBAR'
import unittest
class SomethingTestCase(unittest.TestCase): def test_something(self): assert 'foobar'.upper() != 'FOOBAR'
import unittest
def test_something(): assert 'foobar'.upper() != 'FOOBAR'
def test_something(): assert 'foobar'.upper() != 'FOOBAR'
import unittest
class SomethingTestCase(unittest.TestCase): def test_something(self): self.assertNotEqual('foobar'.upper(), 'FOOBAR')
if __name__ == '__main__': unittest.main()
linhas: 6 > 2
18K L
relatórios melhores
self.assertEqual('foobar', 'foobaz')
FAIL: test_something (__main__.SomethingTestCase)------------------------------------------------------------------Traceback (most recent call last): File "test_something_verbose.py", line 9, in test_something self.assertEqual('foobar', 'foobaz')AssertionError: 'foobar' != 'foobaz'
------------------------------------------------------------------Ran 1 test in 0.000s
FAILED (failures=1)
assert 'foobar' == 'foobaz'
def test_something():> assert 'foobar' == 'foobaz'E assert 'foobar' == 'foobaz'E - foobarE ? ^E + foobazE ? ^
self.assertEqual({'a': 0, 'b': 1, 'c': 0}, {'a': 0, 'b': 2, 'd': 0})
==================================================================FAIL: test_something (__main__.SomeThingTestCase)------------------------------------------------------------------Traceback (most recent call last): File "test_dict_verbose.py", line 9, in test_something {'a': 0, 'b': 2, 'd': 0})AssertionError: {'c': 2, 'a': 0, 'b': 1} != {'d': 0, 'a': 0, 'b': 2}- {'a': 0, 'b': 1, 'c': 2}? ^ ^ ^
+ {'a': 0, 'b': 2, 'd': 0}? ^ ^ ^
------------------------------------------------------------------Ran 1 test in 0.001s
FAILED (failures=1)
assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0})
def test_something():> assert {'a': 0, 'b': 1, 'c': 2} == {'a': 0, 'b': 2, 'd': 2}E assert {'a': 0, 'b': 1, 'c': 2} == {'a': 0, 'b': 2, 'd': 2}E Omitting 1 identical items, use -v to showE Differing items:E {'b': 1} != {'b': 2}E Left contains more items:E {'c': 2}E Right contains more items:E {'d': 2}E Use -v to get the full diff
fixtures
def test_address(): ...
def test_address(address): assert address.country == 'Brazil'
import pytest
@pytest.fixturedef address(): return Address('Av. Paulista', 'São Paulo', 'SP', 'Brazil')
def test_address(address): assert address.country == 'Brazil'
import pytest
@pytest.fixturedef address(): return Address('Av. Paulista', 'São Paulo', 'SP', 'Brazil')
@pytest.fixturedef place(address): return Place(name='MASP', address=address)
def test_place_street(place): assert place.address.street == 'Av. Paulista'
conftest.py
def test_place_street(place): assert place.address.street == 'Av. Paulista'
@pytest.fixturedef country(): return ‘Brazil’
@pytest.fixturedef address(country): return Address('Av. Paulista', 'São Paulo', 'SP', country)
import pytest
@pytest.fixture(params=['Brazil', 'Germany'])def country(request): return request.param
def test_something(address): assert address.country != 'United States'
fixture scope
import pytest
@pytest.fixture(scope='session')def session_app(): from example.app import create_app return create_app()
@pytest.yield_fixturedef app(session_app): ctx = session_app.test_request_context() ctx.push() yield session_app ctx.pop()
from flask import url_for
def test_requires_app_context(app):
url_for('.home') == '/'
def test_config(app): # Same app used
assert 'SQLALCHEMY_DATABASE_URI' in app.config
assertion helpers
def test_config(app):
assert 'SQLALCHEMY_DATABASE_URI' in app.config
app = <Flask 'example.app'>
def test_config(app):
> assert 'SQLALCHEMY_DATABASE_URI' in app.config
E assert 'SQLALCHEMY_DATABASE_URI' in <Config {'JSON_SORT_KEYS': True, 'SERVER_NAME': None, 'TESTING': False, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'DEBUG'...ple.app', 'SESSION_COOKIE_SECURE': False, 'USE_X_SENDFILE': False, 'PREFERRED_URL_SCHEME': 'http', 'SECRET_KEY': None}>
E + where <Config {'JSON_SORT_KEYS': True, 'SERVER_NAME': None, 'TESTING': False, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'DEBUG'...ple.app', 'SESSION_COOKIE_SECURE': False, 'USE_X_SENDFILE': False, 'PREFERRED_URL_SCHEME': 'http', 'SECRET_KEY': None}> = <Flask 'example.app'>.config
import pytest
def assert_has_config(app, config_key):
__tracebackhide__ = True
if config_key not in app.config:
found_keys = '\n'.join('- {}'.format(key) for key in app.config.keys())
pytest.fail('"{}" config key not found. Found this instead:\n'
'{}'.format(config_key, found_keys))
app = <Flask 'example.app'>
def test_config_with_helper(app):
> assert_has_config(app, 'SQLALCHEMY_DATABASE_URI')
E Failed: "SQLALCHEMY_DATABASE_URI" config key not found. Found this instead:
E - TESTING
E - JSON_AS_ASCII
E - SESSION_COOKIE_HTTPONLY
E - PRESERVE_CONTEXT_ON_EXCEPTION
E - SESSION_COOKIE_NAME
E - APPLICATION_ROOT
...
E - SESSION_COOKIE_PATH
E - DEBUG
ad populum
plugins
pytest-xdistpytest-cachepytest-django
Resumo:- menos verboso- relatórios melhores- fixtures- assertion helpers- comunidade
twitter.com/erickwilder
github.com/erickwilder
thanks!github.com/erickwilder/pytest-talk
Agradecimento especial a Cesar Canassa por me ensinar tanto sobre py.test