ran blacken-docs

This commit is contained in:
boris 2019-08-06 13:34:58 -07:00
parent 75d0b899bb
commit 5f95dce956
17 changed files with 163 additions and 66 deletions

View File

@ -238,7 +238,10 @@ file which provides an alternative explanation for ``Foo`` objects:
def pytest_assertrepr_compare(op, left, right):
if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
return ["Comparing Foo instances:", " vals: {} != {}".format(left.val, right.val)]
return [
"Comparing Foo instances:",
" vals: {} != {}".format(left.val, right.val),
]
now, given this test module:

View File

@ -167,4 +167,5 @@ You can also interactively ask for help, e.g. by typing on the Python interactiv
.. code-block:: python
import pytest
help(pytest)

View File

@ -40,10 +40,11 @@ First, let's create 50 test invocation of which only 2 fail::
# content of test_50.py
import pytest
@pytest.mark.parametrize("i", range(50))
def test_num(i):
if i in (17, 25):
pytest.fail("bad luck")
pytest.fail("bad luck")
If you run this for the first time you will see two failures:
@ -193,9 +194,11 @@ across pytest invocations::
import pytest
import time
def expensive_computation():
print("running expensive computation...")
@pytest.fixture
def mydata(request):
val = request.config.cache.get("example/value", None)
@ -205,6 +208,7 @@ across pytest invocations::
request.config.cache.set("example/value", val)
return val
def test_function(mydata):
assert mydata == 23

View File

@ -55,12 +55,15 @@ is that you can use print statements for debugging::
# content of test_module.py
def setup_function(function):
print("setting up %s" % function)
def test_func1():
assert True
def test_func2():
assert False

View File

@ -197,9 +197,11 @@ place the objects you want to appear in the doctest namespace::
# content of conftest.py
import numpy
@pytest.fixture(autouse=True)
def add_np(doctest_namespace):
doctest_namespace['np'] = numpy
doctest_namespace["np"] = numpy
which can then be used in your doctests directly::

View File

@ -25,6 +25,7 @@ line argument. Let's first write a simple (do-nothing) computation test::
# content of test_compute.py
def test_compute(param1):
assert param1 < 4
@ -34,13 +35,14 @@ Now we add a test configuration like this::
# content of conftest.py
def pytest_addoption(parser):
parser.addoption("--all", action="store_true",
help="run all combinations")
parser.addoption("--all", action="store_true", help="run all combinations")
def pytest_generate_tests(metafunc):
if 'param1' in metafunc.fixturenames:
if metafunc.config.getoption('all'):
if "param1" in metafunc.fixturenames:
if metafunc.config.getoption("all"):
end = 5
else:
end = 2
@ -118,7 +120,7 @@ the argument name::
def idfn(val):
if isinstance(val, (datetime,)):
# note this wouldn't show any hours/minutes/seconds
return val.strftime('%Y%m%d')
return val.strftime("%Y%m%d")
@pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
@ -126,12 +128,18 @@ the argument name::
diff = a - b
assert diff == expected
@pytest.mark.parametrize("a,b,expected", [
pytest.param(datetime(2001, 12, 12), datetime(2001, 12, 11),
timedelta(1), id='forward'),
pytest.param(datetime(2001, 12, 11), datetime(2001, 12, 12),
timedelta(-1), id='backward'),
])
@pytest.mark.parametrize(
"a,b,expected",
[
pytest.param(
datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1), id="forward"
),
pytest.param(
datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1), id="backward"
),
],
)
def test_timedistance_v3(a, b, expected):
diff = a - b
assert diff == expected
@ -183,6 +191,7 @@ only have to work a bit to construct the correct arguments for pytest's
# content of test_scenarios.py
def pytest_generate_tests(metafunc):
idlist = []
argvalues = []
@ -193,8 +202,10 @@ only have to work a bit to construct the correct arguments for pytest's
argvalues.append([x[1] for x in items])
metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
scenario1 = ('basic', {'attribute': 'value'})
scenario2 = ('advanced', {'attribute': 'value2'})
scenario1 = ("basic", {"attribute": "value"})
scenario2 = ("advanced", {"attribute": "value2"})
class TestSampleWithScenarios:
scenarios = [scenario1, scenario2]
@ -259,6 +270,8 @@ the actual test requiring a ``db`` object::
# content of test_backends.py
import pytest
def test_db_initialized(db):
# a dummy test
if db.__class__.__name__ == "DB2":
@ -273,15 +286,20 @@ creates a database object for the actual test invocations::
# content of conftest.py
import pytest
def pytest_generate_tests(metafunc):
if 'db' in metafunc.fixturenames:
metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
if "db" in metafunc.fixturenames:
metafunc.parametrize("db", ["d1", "d2"], indirect=True)
class DB1:
"one database object"
class DB2:
"alternative database object"
@pytest.fixture
def db(request):
if request.param == "d1":
@ -346,18 +364,22 @@ will be passed to respective fixture function::
# content of test_indirect_list.py
import pytest
@pytest.fixture(scope='function')
@pytest.fixture(scope="function")
def x(request):
return request.param * 3
@pytest.fixture(scope='function')
@pytest.fixture(scope="function")
def y(request):
return request.param * 2
@pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
def test_indirect(x,y):
assert x == 'aaa'
assert y == 'b'
@pytest.mark.parametrize("x, y", [("a", "b")], indirect=["x"])
def test_indirect(x, y):
assert x == "aaa"
assert y == "b"
The result of this test will be successful:
@ -391,18 +413,21 @@ parametrizer`_ but in a lot less code::
# content of ./test_parametrize.py
import pytest
def pytest_generate_tests(metafunc):
# called once per each test function
funcarglist = metafunc.cls.params[metafunc.function.__name__]
argnames = sorted(funcarglist[0])
metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
for funcargs in funcarglist])
metafunc.parametrize(
argnames, [[funcargs[name] for name in argnames] for funcargs in funcarglist]
)
class TestClass:
# a map specifying multiple argument sets for a test method
params = {
'test_equals': [dict(a=1, b=2), dict(a=3, b=3), ],
'test_zerodivision': [dict(a=1, b=0), ],
"test_equals": [dict(a=1, b=2), dict(a=3, b=3)],
"test_zerodivision": [dict(a=1, b=0)],
}
def test_equals(self, a, b):
@ -471,10 +496,12 @@ need to provide similar results::
import pytest
@pytest.fixture(scope="session")
def basemod(request):
return pytest.importorskip("base")
@pytest.fixture(scope="session", params=["opt1", "opt2"])
def optmod(request):
return pytest.importorskip(request.param)
@ -501,6 +528,7 @@ And finally a little test module::
# content of test_module.py
def test_func1(basemod, optmod):
assert round(basemod.func1(), 3) == round(optmod.func1(), 3)
@ -610,17 +638,21 @@ as a complement to ``raises``. For example::
from contextlib import contextmanager
import pytest
@contextmanager
def does_not_raise():
yield
@pytest.mark.parametrize('example_input,expectation', [
(3, does_not_raise()),
(2, does_not_raise()),
(1, does_not_raise()),
(0, pytest.raises(ZeroDivisionError)),
])
@pytest.mark.parametrize(
"example_input,expectation",
[
(3, does_not_raise()),
(2, does_not_raise()),
(1, does_not_raise()),
(0, pytest.raises(ZeroDivisionError)),
],
)
def test_division(example_input, expectation):
"""Test how much I know division."""
with expectation:

View File

@ -139,6 +139,7 @@ that match ``*_check``. For example, if we have::
class CheckMyApp:
def simple_check(self):
pass
def complex_check(self):
pass
@ -267,7 +268,7 @@ and a ``setup.py`` dummy file like this::
.. code-block:: python
# content of setup.py
0/0 # will raise exception if imported
0 / 0 # will raise exception if imported
If you run with a Python 2 interpreter then you will find the one test and will
leave out the ``setup.py`` file:

View File

@ -13,6 +13,7 @@ calls it::
import pytest
@pytest.fixture(scope="session", autouse=True)
def callattr_ahead_of_alltests(request):
print("callattr_ahead_of_alltests called")
@ -22,7 +23,7 @@ calls it::
cls = item.getparent(pytest.Class)
if cls not in seen:
if hasattr(cls.obj, "callme"):
cls.obj.callme()
cls.obj.callme()
seen.add(cls)
test classes may now define a ``callme`` method which
@ -32,6 +33,7 @@ will be called ahead of running any tests::
# content of test_module.py
class TestHello:
@classmethod
def callme(cls):
@ -43,16 +45,20 @@ will be called ahead of running any tests::
def test_method2(self):
print("test_method1 called")
class TestOther:
@classmethod
def callme(cls):
print("callme other called")
def test_other(self):
print("test other")
# works with unittest as well ...
import unittest
class SomeTest(unittest.TestCase):
@classmethod
def callme(self):

View File

@ -56,15 +56,18 @@ using it::
# content of ./test_smtpsimple.py
import pytest
@pytest.fixture
def smtp_connection():
import smtplib
return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
def test_ehlo(smtp_connection):
response, msg = smtp_connection.ehlo()
assert response == 250
assert 0 # for demo purposes
assert 0 # for demo purposes
Here, the ``test_ehlo`` needs the ``smtp_connection`` fixture value. pytest
will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
@ -190,6 +193,7 @@ access the fixture function::
import pytest
import smtplib
@pytest.fixture(scope="module")
def smtp_connection():
return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
@ -203,12 +207,14 @@ located)::
# content of test_module.py
def test_ehlo(smtp_connection):
response, msg = smtp_connection.ehlo()
assert response == 250
assert b"smtp.gmail.com" in msg
assert 0 # for demo purposes
def test_noop(smtp_connection):
response, msg = smtp_connection.noop()
assert response == 250
@ -491,6 +497,7 @@ read an optional server URL from the test module which uses our fixture::
import pytest
import smtplib
@pytest.fixture(scope="module")
def smtp_connection(request):
server = getattr(request.module, "smtpserver", "smtp.gmail.com")
@ -519,6 +526,7 @@ server URL in its module namespace::
smtpserver = "mail.python.org" # will be read by smtp fixture
def test_showhelo(smtp_connection):
assert 0, smtp_connection.helo()
@ -556,12 +564,8 @@ Factories can have parameters as needed::
@pytest.fixture
def make_customer_record():
def _make_customer_record(name):
return {
"name": name,
"orders": []
}
return {"name": name, "orders": []}
return _make_customer_record
@ -620,8 +624,8 @@ through the special :py:class:`request <FixtureRequest>` object::
import pytest
import smtplib
@pytest.fixture(scope="module",
params=["smtp.gmail.com", "mail.python.org"])
@pytest.fixture(scope="module", params=["smtp.gmail.com", "mail.python.org"])
def smtp_connection(request):
smtp_connection = smtplib.SMTP(request.param, 587, timeout=5)
yield smtp_connection
@ -713,23 +717,28 @@ the string used in a test ID for a certain fixture value by using the
# content of test_ids.py
import pytest
@pytest.fixture(params=[0, 1], ids=["spam", "ham"])
def a(request):
return request.param
def test_a(a):
pass
def idfn(fixture_value):
if fixture_value == 0:
return "eggs"
else:
return None
@pytest.fixture(params=[0, 1], ids=idfn)
def b(request):
return request.param
def test_b(b):
pass
@ -778,10 +787,13 @@ Example::
# content of test_fixture_marks.py
import pytest
@pytest.fixture(params=[0, 1, pytest.param(2, marks=pytest.mark.skip)])
def data_set(request):
return request.param
def test_data(data_set):
pass
@ -820,14 +832,17 @@ and instantiate an object ``app`` where we stick the already defined
import pytest
class App:
def __init__(self, smtp_connection):
self.smtp_connection = smtp_connection
@pytest.fixture(scope="module")
def app(smtp_connection):
return App(smtp_connection)
def test_smtp_connection_exists(app):
assert app.smtp_connection
@ -883,6 +898,7 @@ to show the setup/teardown flow::
# content of test_module.py
import pytest
@pytest.fixture(scope="module", params=["mod1", "mod2"])
def modarg(request):
param = request.param
@ -890,17 +906,23 @@ to show the setup/teardown flow::
yield param
print(" TEARDOWN modarg %s" % param)
@pytest.fixture(scope="function", params=[1,2])
@pytest.fixture(scope="function", params=[1, 2])
def otherarg(request):
param = request.param
print(" SETUP otherarg %s" % param)
yield param
print(" TEARDOWN otherarg %s" % param)
def test_0(otherarg):
print(" RUN test0 with otherarg %s" % otherarg)
def test_1(modarg):
print(" RUN test1 with modarg %s" % modarg)
def test_2(otherarg, modarg):
print(" RUN test2 with otherarg {} and modarg {}".format(otherarg, modarg))
@ -987,6 +1009,7 @@ file::
import tempfile
import os
@pytest.fixture()
def cleandir():
newpath = tempfile.mkdtemp()
@ -1000,6 +1023,7 @@ and declare its use in a test module via a ``usefixtures`` marker::
import os
import pytest
@pytest.mark.usefixtures("cleandir")
class TestDirectoryInit:
def test_cwd_starts_empty(self):
@ -1086,18 +1110,23 @@ self-contained implementation of this idea::
import pytest
class DB:
def __init__(self):
self.intransaction = []
def begin(self, name):
self.intransaction.append(name)
def rollback(self):
self.intransaction.pop()
@pytest.fixture(scope="module")
def db():
return DB()
class TestClass:
@pytest.fixture(autouse=True)
def transact(self, request, db):

View File

@ -29,13 +29,15 @@ a per-session Database object::
class Database:
def __init__(self):
print("database instance created")
def destroy(self):
print("database instance destroyed")
def pytest_funcarg__db(request):
return request.cached_setup(setup=DataBase,
teardown=lambda db: db.destroy,
scope="session")
return request.cached_setup(
setup=DataBase, teardown=lambda db: db.destroy, scope="session"
)
There are several limitations and difficulties with this approach:
@ -100,7 +102,7 @@ sets. pytest-2.3 introduces a decorator for use on the factory itself::
@pytest.fixture(params=["mysql", "pg"])
def db(request):
... # use request.param
... # use request.param
Here the factory will be invoked twice (with the respective "mysql"
and "pg" values set as ``request.param`` attributes) and all of

View File

@ -43,6 +43,7 @@ Create a simple test function with just four lines of code::
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
@ -91,9 +92,12 @@ Use the :ref:`raises <assertraises>` helper to assert that some code raises an e
# content of test_sysexit.py
import pytest
def f():
raise SystemExit(1)
def test_mytest():
with pytest.raises(SystemExit):
f()
@ -117,11 +121,11 @@ Once you develop multiple tests, you may want to group them into a class. pytest
class TestClass:
def test_one(self):
x = "this"
assert 'h' in x
assert "h" in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')
assert hasattr(x, "check")
``pytest`` discovers all tests following its :ref:`Conventions for Python test discovery <test discovery>`, so it finds both ``test_`` prefixed functions. There is no need to subclass anything. We can simply run the module by passing its filename:

View File

@ -85,7 +85,7 @@ logger::
.. code-block:: python
def test_foo(caplog):
caplog.set_level(logging.CRITICAL, logger='root.baz')
caplog.set_level(logging.CRITICAL, logger="root.baz")
pass
The log levels set are restored automatically at the end of the test.
@ -105,7 +105,7 @@ logger can be changed instead with::
.. code-block:: python
def test_bar(caplog):
with caplog.at_level(logging.CRITICAL, logger='root.baz'):
with caplog.at_level(logging.CRITICAL, logger="root.baz"):
pass
Lastly all the logs sent to the logger during the test run are made available on
@ -117,8 +117,8 @@ This is useful for when you want to assert on the contents of a message::
def test_baz(caplog):
func_under_test()
for record in caplog.records:
assert record.levelname != 'CRITICAL'
assert 'wally' not in caplog.text
assert record.levelname != "CRITICAL"
assert "wally" not in caplog.text
For all the available attributes of the log records see the
``logging.LogRecord`` class.
@ -130,11 +130,9 @@ severity and message::
.. code-block:: python
def test_foo(caplog):
logging.getLogger().info('boo %s', 'arg')
logging.getLogger().info("boo %s", "arg")
assert caplog.record_tuples == [
('root', logging.INFO, 'boo arg'),
]
assert caplog.record_tuples == [("root", logging.INFO, "boo arg")]
You can call ``caplog.clear()`` to reset the captured log records in a test::
@ -144,7 +142,7 @@ You can call ``caplog.clear()`` to reset the captured log records in a test::
some_method_that_creates_log_records()
caplog.clear()
your_test_method()
assert ['Foo'] == [rec.message for rec in caplog.records]
assert ["Foo"] == [rec.message for rec in caplog.records]
The ``caplog.records`` attribute contains records from the current stage only, so

View File

@ -473,7 +473,7 @@ To use it, include in your top-most ``conftest.py`` file::
.. code-block:: python
pytest_plugins = 'pytester'
pytest_plugins = "pytester"

View File

@ -96,6 +96,8 @@ and more. Here is an example test usage::
# content of test_tmpdir.py
import os
def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt")
p.write("content")

View File

@ -91,10 +91,12 @@ it from a unittest-style test::
import pytest
@pytest.fixture(scope="class")
def db_class(request):
class DummyDB:
pass
# set a class attribute on the invoking test context
request.cls.db = DummyDB()
@ -116,14 +118,15 @@ fixture definition::
import unittest
import pytest
@pytest.mark.usefixtures("db_class")
class MyTest(unittest.TestCase):
def test_method1(self):
assert hasattr(self, "db")
assert 0, self.db # fail for demo purposes
assert 0, self.db # fail for demo purposes
def test_method2(self):
assert 0, self.db # fail for demo purposes
assert 0, self.db # fail for demo purposes
The ``@pytest.mark.usefixtures("db_class")`` class-decorator makes sure that
the pytest fixture function ``db_class`` is called once per class.
@ -193,11 +196,11 @@ creation of a per-test temporary directory::
import pytest
import unittest
class MyTest(unittest.TestCase):
class MyTest(unittest.TestCase):
@pytest.fixture(autouse=True)
def initdir(self, tmpdir):
tmpdir.chdir() # change to pytest-provided temporary directory
tmpdir.chdir() # change to pytest-provided temporary directory
tmpdir.join("samplefile.ini").write("# testdata")
def test_method(self):

View File

@ -766,7 +766,7 @@ You can pass in options and arguments::
.. code-block:: python
pytest.main(['-x', 'mytestdir'])
pytest.main(["-x", "mytestdir"])
You can specify additional plugins to ``pytest.main``::
@ -774,10 +774,13 @@ You can specify additional plugins to ``pytest.main``::
# content of myinvoke.py
import pytest
class MyPlugin:
def pytest_sessionfinish(self):
print("*** test run reporting finishing")
pytest.main(["-qq"], plugins=[MyPlugin()])
Running it will show that ``MyPlugin`` was added and its

View File

@ -34,6 +34,7 @@ which will usually be called once for all the functions::
def setup_module(module):
""" setup any state specific to the execution of the given module."""
def teardown_module(module):
""" teardown any state that was previously setup with a setup_module
method.
@ -55,6 +56,7 @@ and after all test methods of the class are called::
usually contains tests).
"""
@classmethod
def teardown_class(cls):
""" teardown any state that was previously setup with a call to
@ -73,6 +75,7 @@ Similarly, the following methods are called around each method invocation::
class. setup_method is invoked for every test method of a class.
"""
def teardown_method(self, method):
""" teardown any state that was previously setup with a setup_method
call.
@ -90,6 +93,7 @@ you can also use the following functions to implement fixtures::
Invoked for every test function in the module.
"""
def teardown_function(function):
""" teardown any state that was previously setup with a setup_function
call.