diff --git a/.travis.yml b/.travis.yml index 9010ae1c2..8c6342ccc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,9 +30,11 @@ matrix: jobs: include: # Coverage tracking is slow with pypy, skip it. - - env: TOXENV=pypy PYTEST_NO_COVERAGE=1 - python: 'pypy-5.4' - dist: trusty + - env: TOXENV=pypy-xdist PYTEST_NO_COVERAGE=1 + python: 'pypy2.7-6.0' + - env: TOXENV=pypy3-xdist PYTEST_NO_COVERAGE=1 + python: 'pypy3.5-6.0' + - env: TOXENV=py34-xdist python: '3.4' - env: TOXENV=py35-xdist diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 278b9015a..9f375bbc9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -4,6 +4,8 @@ trigger: variables: PYTEST_ADDOPTS: "--junitxml=build/test-results/$(tox.env).xml" + python.needs_vc: False + python.exe: "python" jobs: @@ -15,6 +17,26 @@ jobs: py27: python.version: '2.7' tox.env: 'py27' + py27-xdist: + python.version: '2.7' + tox.env: 'py27-xdist' + py27-numpy/nobyte: + python.version: '2.7' + tox.env: 'py27-numpy,py27-nobyte' + py27-trial: + python.version: '2.7' + tox.env: 'py27-trial' + python.needs_vc: True + py27-pluggymaster: + python.version: '2.7' + tox.env: 'pluggymaster' + pypy: + python.version: 'pypy' + tox.env: 'pypy' + python.exe: 'pypy' + py34: + python.version: '3.4' + tox.env: 'py34' py35: python.version: '3.5' tox.env: 'py35' @@ -24,18 +46,52 @@ jobs: py37: python.version: '3.7' tox.env: 'py37' - maxParallel: 4 + py37-linting/docs/doctesting: + python.version: '3.7' + tox.env: 'linting,docs,doctesting' + py37-xdist: + python.version: '3.7' + tox.env: 'py37-xdist' + py37-trial/numpy: + python.version: '3.7' + tox.env: 'py37-trial,py37-numpy' + py37-pluggymaster: + python.version: '3.7' + tox.env: 'py37-pluggymaster' + maxParallel: 10 steps: - task: UsePythonVersion@0 + condition: not(startsWith(variables['python.exe'], 'pypy')) inputs: versionSpec: '$(python.version)' architecture: 'x64' - - script: python -m pip install --upgrade pip && pip install tox + - script: choco install vcpython27 + condition: eq(variables['python.needs_vc'], True) + displayName: 'Install VC for py27' + + - script: choco install python.pypy + condition: eq(variables['python.exe'], 'pypy') + displayName: 'Install pypy' + + - script: choco install pypy3 + condition: eq(variables['python.exe'], 'pypy3') + displayName: 'Install pypy3' + + - task: PowerShell@2 + inputs: + targetType: 'inline' + script: | + Invoke-WebRequest -Uri "https://bootstrap.pypa.io/get-pip.py" -OutFile "get-pip.py" + $(python.exe) get-pip.py + condition: startsWith(variables['python.exe'], 'pypy') + displayName: 'Install pip' + + - script: $(python.exe) -m pip install --upgrade pip && $(python.exe) -m pip install tox displayName: 'Install tox' - - script: python -m tox -e $(tox.env) + - script: $(python.exe) -m tox -e $(tox.env) displayName: 'Run tests' - task: PublishTestResults@2 diff --git a/changelog/4810.bugfix.rst b/changelog/4810.bugfix.rst new file mode 100644 index 000000000..32d9b97a5 --- /dev/null +++ b/changelog/4810.bugfix.rst @@ -0,0 +1 @@ +Logging messages inside ``pytest_runtest_logreport()`` are now properly captured and displayed. diff --git a/doc/en/bash-completion.rst b/doc/en/bash-completion.rst index 08d978209..eaa078814 100644 --- a/doc/en/bash-completion.rst +++ b/doc/en/bash-completion.rst @@ -8,18 +8,26 @@ When using bash as your shell, ``pytest`` can use argcomplete (https://argcomplete.readthedocs.io/) for auto-completion. For this ``argcomplete`` needs to be installed **and** enabled. -Install argcomplete using:: +Install argcomplete using: - sudo pip install 'argcomplete>=0.5.7' +.. code-block:: bash -For global activation of all argcomplete enabled python applications run:: + sudo pip install 'argcomplete>=0.5.7' + +For global activation of all argcomplete enabled python applications run: + +.. code-block:: bash sudo activate-global-python-argcomplete -For permanent (but not global) ``pytest`` activation, use:: +For permanent (but not global) ``pytest`` activation, use: - register-python-argcomplete pytest >> ~/.bashrc +.. code-block:: bash -For one-time activation of argcomplete for ``pytest`` only, use:: + register-python-argcomplete pytest >> ~/.bashrc - eval "$(register-python-argcomplete pytest)" +For one-time activation of argcomplete for ``pytest`` only, use: + +.. code-block:: bash + + eval "$(register-python-argcomplete pytest)" diff --git a/doc/en/cache.rst b/doc/en/cache.rst index 0cb42e6e9..89a1e2634 100644 --- a/doc/en/cache.rst +++ b/doc/en/cache.rst @@ -168,7 +168,9 @@ Behavior when no tests failed in the last run When no tests failed in the last run, or when no cached ``lastfailed`` data was found, ``pytest`` can be configured either to run all of the tests or no tests, -using the ``--last-failed-no-failures`` option, which takes one of the following values:: +using the ``--last-failed-no-failures`` option, which takes one of the following values: + +.. code-block:: bash pytest --last-failed --last-failed-no-failures all # run all tests (default behavior) pytest --last-failed --last-failed-no-failures none # run no tests and exit @@ -283,7 +285,9 @@ Clearing Cache content ------------------------------- You can instruct pytest to clear all cache files and values -by adding the ``--cache-clear`` option like this:: +by adding the ``--cache-clear`` option like this: + +.. code-block:: bash pytest --cache-clear diff --git a/doc/en/capture.rst b/doc/en/capture.rst index 78390034a..f62ec60ca 100644 --- a/doc/en/capture.rst +++ b/doc/en/capture.rst @@ -35,7 +35,9 @@ There are two ways in which ``pytest`` can perform capturing: .. _`disable capturing`: -You can influence output capturing mechanisms from the command line:: +You can influence output capturing mechanisms from the command line: + +.. code-block:: bash pytest -s # disable all capturing pytest --capture=sys # replace sys.stdout/stderr with in-mem files diff --git a/doc/en/customize.rst b/doc/en/customize.rst index 47b92ab9e..310b5c7b3 100644 --- a/doc/en/customize.rst +++ b/doc/en/customize.rst @@ -5,7 +5,9 @@ Command line options and configuration file settings ----------------------------------------------------------------- You can get help on command line options and values in INI-style -configurations files by using the general help option:: +configurations files by using the general help option: + +.. code-block:: bash pytest -h # prints options _and_ config file settings @@ -92,12 +94,16 @@ The rootdir is used a reference directory for constructing test addresses ("nodeids") and can be used also by plugins for storing per-testrun information. -Example:: +Example: + +.. code-block:: bash pytest path/to/testdir path/other/ will determine the common ancestor as ``path`` and then -check for ini-files as follows:: +check for ini-files as follows: + +.. code-block:: text # first look for pytest.ini files path/pytest.ini @@ -133,19 +139,27 @@ progress output, you can write it into a configuration file: addopts = -ra -q Alternatively, you can set a ``PYTEST_ADDOPTS`` environment variable to add command -line options while the environment is in use:: +line options while the environment is in use: + +.. code-block:: bash export PYTEST_ADDOPTS="-v" -Here's how the command-line is built in the presence of ``addopts`` or the environment variable:: +Here's how the command-line is built in the presence of ``addopts`` or the environment variable: + +.. code-block:: text $PYTEST_ADDOPTS -So if the user executes in the command-line:: +So if the user executes in the command-line: + +.. code-block:: bash pytest -m slow -The actual command line executed is:: +The actual command line executed is: + +.. code-block:: bash pytest -ra -q -v -m slow diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 5aadc1112..549ebb00f 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -4,7 +4,9 @@ Doctest integration for modules and test files By default all files matching the ``test*.txt`` pattern will be run through the python standard ``doctest`` module. You -can change the pattern by issuing:: +can change the pattern by issuing: + +.. code-block:: bash pytest --doctest-glob='*.rst' @@ -26,7 +28,9 @@ can be given multiple times in the command-line. You can also trigger running of doctests from docstrings in all python modules (including regular -python test modules):: +python test modules): + +.. code-block:: bash pytest --doctest-modules @@ -39,7 +43,9 @@ putting them into a pytest.ini file like this: [pytest] addopts = --doctest-modules -If you then have a text file like this:: +If you then have a text file like this: + +.. code-block:: text # content of example.rst @@ -73,7 +79,9 @@ then you can just invoke ``pytest`` without command line options: ========================= 1 passed in 0.12 seconds ========================= -It is possible to use fixtures using the ``getfixture`` helper:: +It is possible to use fixtures using the ``getfixture`` helper: + +.. code-block:: text # content of example.rst >>> tmp = getfixture('tmpdir') @@ -112,14 +120,18 @@ the ``doctest_optionflags`` ini option: Alternatively, it can be enabled by an inline comment in the doc test -itself:: +itself: + +.. code-block:: rst # content of example.rst >>> get_unicode_greeting() # doctest: +ALLOW_UNICODE 'Hello' By default, pytest would report only the first failure for a given doctest. If -you want to continue the test even when you have failures, do:: +you want to continue the test even when you have failures, do: + +.. code-block:: bash pytest --doctest-modules --doctest-continue-on-failure @@ -167,7 +179,9 @@ Output format You can change the diff output format on failure for your doctests by using one of standard doctest modules format in options (see :data:`python:doctest.REPORT_UDIFF`, :data:`python:doctest.REPORT_CDIFF`, -:data:`python:doctest.REPORT_NDIFF`, :data:`python:doctest.REPORT_ONLY_FIRST_FAILURE`):: +:data:`python:doctest.REPORT_NDIFF`, :data:`python:doctest.REPORT_ONLY_FIRST_FAILURE`): + +.. code-block:: bash pytest --doctest-modules --doctest-report none pytest --doctest-modules --doctest-report udiff diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 864c1e808..5ec57caed 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -204,14 +204,18 @@ Registering markers .. ini-syntax for custom markers: -Registering markers for your test suite is simple:: +Registering markers for your test suite is simple: + +.. code-block:: ini # content of pytest.ini [pytest] markers = webtest: mark a test as a webtest. -You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers:: +You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers: + +.. code-block:: pytest $ pytest --markers @pytest.mark.webtest: mark a test as a webtest. @@ -388,7 +392,9 @@ and here is one that specifies exactly the environment needed: ========================= 1 passed in 0.12 seconds ========================= -The ``--markers`` option always gives you a list of available markers:: +The ``--markers`` option always gives you a list of available markers: + +.. code-block:: pytest $ pytest --markers @pytest.mark.env(name): mark test to run only on named environment diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 750bc58d8..02c12f6bc 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -6,7 +6,9 @@ Ignore paths during test collection You can easily ignore certain test directories and modules during collection by passing the ``--ignore=path`` option on the cli. ``pytest`` allows multiple -``--ignore`` options. Example:: +``--ignore`` options. Example: + +.. code-block:: text tests/ |-- example @@ -57,7 +59,9 @@ Keeping duplicate paths specified from command line ---------------------------------------------------- Default behavior of ``pytest`` is to ignore duplicate paths specified from the command line. -Example:: +Example: + +.. code-block:: pytest pytest path_a path_a @@ -68,7 +72,9 @@ Example:: Just collect tests once. To collect duplicate tests, use the ``--keep-duplicates`` option on the cli. -Example:: +Example: + +.. code-block:: pytest pytest --keep-duplicates path_a path_a @@ -78,7 +84,9 @@ Example:: As the collector just works on directories, if you specify twice a single test file, ``pytest`` will still collect it twice, no matter if the ``--keep-duplicates`` is not specified. -Example:: +Example: + +.. code-block:: pytest pytest test_a.py test_a.py @@ -90,7 +98,9 @@ Example:: Changing directory recursion ----------------------------------------------------- -You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory:: +You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory: + +.. code-block:: ini # content of pytest.ini [pytest] @@ -106,7 +116,9 @@ Changing naming conventions You can configure different naming conventions by setting the :confval:`python_files`, :confval:`python_classes` and :confval:`python_functions` configuration options. -Here is an example:: +Here is an example: + +.. code-block:: ini # content of pytest.ini # Example 1: have pytest look for "check" instead of "test" @@ -145,7 +157,9 @@ The test collection would look like this: ======================= no tests ran in 0.12 seconds ======================= -You can check for multiple glob patterns by adding a space between the patterns:: +You can check for multiple glob patterns by adding a space between the patterns: + +.. code-block:: ini # Example 2: have pytest look for files with "test" and "example" # content of pytest.ini, tox.ini, or setup.cfg file (replace "pytest" @@ -165,13 +179,17 @@ Interpreting cmdline arguments as Python packages You can use the ``--pyargs`` option to make ``pytest`` try interpreting arguments as python package names, deriving their file system path and then running the test. For -example if you have unittest2 installed you can type:: +example if you have unittest2 installed you can type: + +.. code-block:: bash pytest --pyargs unittest2.test.test_skipping -q which would run the respective test module. Like with other options, through an ini-file and the :confval:`addopts` option you -can make this change more permanently:: +can make this change more permanently: + +.. code-block:: ini # content of pytest.ini [pytest] @@ -209,7 +227,9 @@ Customizing test collection .. regendoc:wipe -You can easily instruct ``pytest`` to discover tests from every Python file:: +You can easily instruct ``pytest`` to discover tests from every Python file: + +.. code-block:: ini # content of pytest.ini [pytest] diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 5904ea5a1..1c6cf36c9 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -731,7 +731,9 @@ and run them: test_module.py:6: AssertionError ========================= 2 failed in 0.12 seconds ========================= -you will have a "failures" file which contains the failing test ids:: +you will have a "failures" file which contains the failing test ids: + +.. code-block:: bash $ cat failures test_module.py::test_fail1 (PYTEST_TMPDIR/test_fail10) @@ -935,6 +937,8 @@ like ``pytest-timeout`` they must be imported explicitly and passed on to pytest This allows you to execute tests using the frozen -application with standard ``pytest`` command-line options:: +application with standard ``pytest`` command-line options: + +.. code-block:: bash ./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/ diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 4c8e24b9c..390f8abcc 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -114,7 +114,9 @@ with a list of available function arguments. .. note:: - You can always issue :: + You can always issue: + + .. code-block:: bash pytest --fixtures test_simplefactory.py @@ -362,7 +364,9 @@ The ``print`` and ``smtp.close()`` statements will execute when the last test in the module has finished execution, regardless of the exception status of the tests. -Let's execute it:: +Let's execute it: + +.. code-block:: pytest $ pytest -s -q --tb=no FFteardown smtp @@ -471,7 +475,9 @@ read an optional server URL from the test module which uses our fixture:: We use the ``request.module`` attribute to optionally obtain an ``smtpserver`` attribute from the test module. If we just execute -again, nothing much has changed:: +again, nothing much has changed: + +.. code-block:: pytest $ pytest -s -q --tb=no FFfinalizing (smtp.gmail.com) diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index a9f7d1d11..222ae65ba 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -17,11 +17,15 @@ Installation and Getting Started Install ``pytest`` ---------------------------------------- -1. Run the following command in your command line:: +1. Run the following command in your command line: + +.. code-block:: bash pip install -U pytest -2. Check that you installed the correct version:: +2. Check that you installed the correct version: + +.. code-block:: bash $ pytest --version This is pytest version 4.x.y, imported from $PYTHON_PREFIX/lib/python3.6/site-packages/pytest.py @@ -168,7 +172,9 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look More info on tmpdir handling is available at :ref:`Temporary directories and files `. -Find out what kind of builtin :ref:`pytest fixtures ` exist with the command:: +Find out what kind of builtin :ref:`pytest fixtures ` exist with the command: + +.. code-block:: bash pytest --fixtures # shows builtin and custom fixtures diff --git a/doc/en/goodpractices.rst b/doc/en/goodpractices.rst index 080685a4c..ba79e71f4 100644 --- a/doc/en/goodpractices.rst +++ b/doc/en/goodpractices.rst @@ -7,12 +7,13 @@ Good Integration Practices Install package with pip ------------------------------------------------- -For development, we recommend to use virtualenv_ environments and pip_ -for installing your application and any dependencies -as well as the ``pytest`` package itself. This ensures your code and -dependencies are isolated from the system Python installation. +For development, we recommend you use venv_ for virtual environments +(or virtualenv_ for Python 2.7) and +pip_ for installing your application and any dependencies, +as well as the ``pytest`` package itself. +This ensures your code and dependencies are isolated from your system Python installation. -First you need to place a ``setup.py`` file in the root of your package with the following minimum content:: +Next, place a ``setup.py`` file in the root of your package with the following minimum content:: from setuptools import setup, find_packages diff --git a/doc/en/license.rst b/doc/en/license.rst index b8c0dce1b..5ee55cf96 100644 --- a/doc/en/license.rst +++ b/doc/en/license.rst @@ -5,7 +5,7 @@ License Distributed under the terms of the `MIT`_ license, pytest is free and open source software. -:: +.. code-block:: text The MIT License (MIT) diff --git a/doc/en/links.inc b/doc/en/links.inc index 4d5a4b1ee..1b7cbd05b 100644 --- a/doc/en/links.inc +++ b/doc/en/links.inc @@ -14,6 +14,7 @@ .. _`distribute docs`: .. _`distribute`: https://pypi.org/project/distribute/ .. _`pip`: https://pypi.org/project/pip/ +.. _`venv`: https://docs.python.org/3/library/venv.html/ .. _`virtualenv`: https://pypi.org/project/virtualenv/ .. _hudson: http://hudson-ci.org/ .. _jenkins: http://jenkins-ci.org/ diff --git a/doc/en/logging.rst b/doc/en/logging.rst index 197528d7c..ff80884e9 100644 --- a/doc/en/logging.rst +++ b/doc/en/logging.rst @@ -9,11 +9,15 @@ Logging pytest captures log messages of level ``WARNING`` or above automatically and displays them in their own section for each failed test in the same manner as captured stdout and stderr. -Running without options:: +Running without options: + +.. code-block:: bash pytest -Shows failed tests like so:: +Shows failed tests like so: + +.. code-block:: pytest ----------------------- Captured stdlog call ---------------------- test_reporting.py 26 WARNING text going to logger @@ -27,12 +31,16 @@ By default each captured log message shows the module, line number, log level and message. If desired the log and date format can be specified to -anything that the logging module supports by passing specific formatting options:: +anything that the logging module supports by passing specific formatting options: + +.. code-block:: bash pytest --log-format="%(asctime)s %(levelname)s %(message)s" \ --log-date-format="%Y-%m-%d %H:%M:%S" -Shows failed tests like so:: +Shows failed tests like so: + +.. code-block:: pytest ----------------------- Captured stdlog call ---------------------- 2010-04-10 14:48:44 WARNING text going to logger @@ -51,7 +59,9 @@ These options can also be customized through ``pytest.ini`` file: log_date_format = %Y-%m-%d %H:%M:%S Further it is possible to disable reporting of captured content (stdout, -stderr and logs) on failed tests completely with:: +stderr and logs) on failed tests completely with: + +.. code-block:: bash pytest --show-capture=no @@ -133,7 +143,6 @@ the records for the ``setup`` and ``call`` stages during teardown like so: .. code-block:: python - @pytest.fixture def window(caplog): window = create_window() diff --git a/doc/en/nose.rst b/doc/en/nose.rst index 1f7b7b638..701ea44ec 100644 --- a/doc/en/nose.rst +++ b/doc/en/nose.rst @@ -12,7 +12,9 @@ Running tests written for nose Usage ------------- -After :ref:`installation` type:: +After :ref:`installation` type: + +.. code-block:: bash python setup.py develop # make sure tests can import our package pytest # instead of 'nosetests' diff --git a/doc/en/parametrize.rst b/doc/en/parametrize.rst index d1d23c67f..9a237dcd7 100644 --- a/doc/en/parametrize.rst +++ b/doc/en/parametrize.rst @@ -172,7 +172,9 @@ command line option and the parametrization of our test function:: metafunc.parametrize("stringinput", metafunc.config.getoption('stringinput')) -If we now pass two stringinput values, our test will run twice:: +If we now pass two stringinput values, our test will run twice: + +.. code-block:: pytest $ pytest -q --stringinput="hello" --stringinput="world" test_strings.py .. [100%] diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index dd0b57110..96af8ee35 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -22,7 +22,9 @@ it's an **xpass** and will be reported in the test summary. ``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed information about skipped/xfailed tests is not shown by default to avoid cluttering the output. You can use the ``-r`` option to see details -corresponding to the "short" letters shown in the test progress:: +corresponding to the "short" letters shown in the test progress: + +.. code-block:: bash pytest -rxXs # show extra info on xfailed, xpassed, and skipped tests @@ -82,7 +84,7 @@ It is also possible to skip the whole module using If you wish to skip something conditionally then you can use ``skipif`` instead. Here is an example of marking a test function to be skipped -when run on an interpreter earlier than Python3.6 :: +when run on an interpreter earlier than Python3.6:: import sys @pytest.mark.skipif(sys.version_info < (3,6), @@ -309,7 +311,9 @@ investigated later. Ignoring xfail ~~~~~~~~~~~~~~ -By specifying on the commandline:: +By specifying on the commandline: + +.. code-block:: bash pytest --runxfail diff --git a/doc/en/tmpdir.rst b/doc/en/tmpdir.rst index 3d73d6147..df490d7fb 100644 --- a/doc/en/tmpdir.rst +++ b/doc/en/tmpdir.rst @@ -174,7 +174,9 @@ the system temporary directory. The base name will be ``pytest-NUM`` where ``NUM`` will be incremented with each test run. Moreover, entries older than 3 temporary directories will be removed. -You can override the default temporary directory setting like this:: +You can override the default temporary directory setting like this: + +.. code-block:: bash pytest --basetemp=mydir diff --git a/doc/en/usage.rst b/doc/en/usage.rst index b894e0fd4..2efb63ae2 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -12,7 +12,9 @@ Calling pytest through ``python -m pytest`` .. versionadded:: 2.0 -You can invoke testing through the Python interpreter from the command line:: +You can invoke testing through the Python interpreter from the command line: + +.. code-block:: text python -m pytest [...] @@ -34,7 +36,7 @@ Running ``pytest`` can result in six different exit codes: Getting help on version, option names, environment variables -------------------------------------------------------------- -:: +.. code-block:: bash pytest --version # shows where pytest was imported from pytest --fixtures # show available builtin function arguments @@ -46,7 +48,9 @@ Getting help on version, option names, environment variables Stopping after the first (or N) failures --------------------------------------------------- -To stop the testing process after the first (N) failures:: +To stop the testing process after the first (N) failures: + +.. code-block:: bash pytest -x # stop after first failure pytest --maxfail=2 # stop after two failures @@ -60,19 +64,19 @@ Pytest supports several ways to run and select tests from the command-line. **Run tests in a module** -:: +.. code-block:: bash pytest test_mod.py **Run tests in a directory** -:: +.. code-block:: bash pytest testing/ **Run tests by keyword expressions** -:: +.. code-block:: bash pytest -k "MyClass and not method" @@ -87,18 +91,22 @@ The example above will run ``TestMyClass.test_something`` but not ``TestMyClass Each collected test is assigned a unique ``nodeid`` which consist of the module filename followed by specifiers like class names, function names and parameters from parametrization, separated by ``::`` characters. -To run a specific test within a module:: +To run a specific test within a module: + +.. code-block:: bash pytest test_mod.py::test_func -Another example specifying a test method in the command line:: +Another example specifying a test method in the command line: + +.. code-block:: bash pytest test_mod.py::TestClass::test_method **Run tests by marker expressions** -:: +.. code-block:: bash pytest -m slow @@ -108,7 +116,7 @@ For more information see :ref:`marks `. **Run tests from packages** -:: +.. code-block:: bash pytest --pyargs pkg.testing @@ -118,7 +126,9 @@ This will import ``pkg.testing`` and use its filesystem location to find and run Modifying Python traceback printing ---------------------------------------------- -Examples for modifying traceback printing:: +Examples for modifying traceback printing: + +.. code-block:: bash pytest --showlocals # show local variables in tracebacks pytest -l # show local variables (shortcut) @@ -320,13 +330,17 @@ Dropping to PDB_ (Python Debugger) on failures .. _PDB: http://docs.python.org/library/pdb.html Python comes with a builtin Python debugger called PDB_. ``pytest`` -allows one to drop into the PDB_ prompt via a command line option:: +allows one to drop into the PDB_ prompt via a command line option: + +.. code-block:: bash pytest --pdb This will invoke the Python debugger on every failure (or KeyboardInterrupt). Often you might only want to do this for the first failing test to understand -a certain failure situation:: +a certain failure situation: + +.. code-block:: bash pytest -x --pdb # drop to PDB on first failure, then end test session pytest --pdb --maxfail=3 # drop to PDB for first three failures @@ -349,7 +363,9 @@ Dropping to PDB_ (Python Debugger) at the start of a test ---------------------------------------------------------- -``pytest`` allows one to drop into the PDB_ prompt immediately at the start of each test via a command line option:: +``pytest`` allows one to drop into the PDB_ prompt immediately at the start of each test via a command line option: + +.. code-block:: bash pytest --trace @@ -394,7 +410,9 @@ Profiling test execution duration .. versionadded: 2.2 -To get a list of the slowest 10 test durations:: +To get a list of the slowest 10 test durations: + +.. code-block:: bash pytest --durations=10 @@ -404,7 +422,9 @@ Creating JUnitXML format files ---------------------------------------------------- To create result files which can be read by Jenkins_ or other Continuous -integration servers, use this invocation:: +integration servers, use this invocation: + +.. code-block:: bash pytest --junitxml=path @@ -627,7 +647,9 @@ Creating resultlog format files See `the deprecation docs `__ for more information. -To create plain-text machine-readable result files you can issue:: +To create plain-text machine-readable result files you can issue: + +.. code-block:: bash pytest --resultlog=path @@ -640,7 +662,9 @@ by the `PyPy-test`_ web page to show test results over several revisions. Sending test report to online pastebin service ----------------------------------------------------- -**Creating a URL for each test failure**:: +**Creating a URL for each test failure**: + +.. code-block:: bash pytest --pastebin=failed @@ -648,7 +672,9 @@ This will submit test run information to a remote Paste service and provide a URL for each failure. You may select tests as usual or add for example ``-x`` if you only want to send one particular failure. -**Creating a URL for a whole test session log**:: +**Creating a URL for a whole test session log**: + +.. code-block:: bash pytest --pastebin=all @@ -661,7 +687,9 @@ To disable loading specific plugins at invocation time, use the ``-p`` option together with the prefix ``no:``. Example: to disable loading the plugin ``doctest``, which is responsible for -executing doctest tests from text files, invoke pytest like this:: +executing doctest tests from text files, invoke pytest like this: + +.. code-block:: bash pytest -p no:doctest @@ -693,7 +721,9 @@ You can specify additional plugins to ``pytest.main``:: pytest.main(["-qq"], plugins=[MyPlugin()]) Running it will show that ``MyPlugin`` was added and its -hook was invoked:: +hook was invoked: + +.. code-block:: pytest $ python myinvoke.py .FEsxX. [100%]*** test run reporting finishing diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 5234b5b8a..7e906deab 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -567,6 +567,11 @@ class LoggingPlugin(object): with self._runtest_for(None, "finish"): yield + @pytest.hookimpl(hookwrapper=True) + def pytest_runtest_logreport(self): + with self._runtest_for(None, "logreport"): + yield + @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_sessionfinish(self): with self.live_logs_context(): diff --git a/testing/freeze/create_executable.py b/testing/freeze/create_executable.py index 98aa2034c..b53eb09f5 100644 --- a/testing/freeze/create_executable.py +++ b/testing/freeze/create_executable.py @@ -8,5 +8,6 @@ if __name__ == "__main__": hidden = [] for x in pytest.freeze_includes(): hidden.extend(["--hidden-import", x]) + hidden.extend(["--hidden-import", "distutils"]) args = ["pyinstaller", "--noconfirm"] + hidden + ["runtests_script.py"] subprocess.check_call(" ".join(args), shell=True) diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index afeccfcc5..90db8813e 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1004,6 +1004,40 @@ def test_log_in_hooks(testdir): assert "sessionfinish" in contents +def test_log_in_runtest_logreport(testdir): + log_file = testdir.tmpdir.join("pytest.log").strpath + + testdir.makeini( + """ + [pytest] + log_file={} + log_file_level = INFO + log_cli=true + """.format( + log_file + ) + ) + testdir.makeconftest( + """ + import logging + logger = logging.getLogger(__name__) + + def pytest_runtest_logreport(report): + logger.info("logreport") + """ + ) + testdir.makepyfile( + """ + def test_first(): + assert True + """ + ) + testdir.runpytest() + with open(log_file) as rfh: + contents = rfh.read() + assert contents.count("logreport") == 3 + + def test_log_set_path(testdir): report_dir_base = testdir.tmpdir.strpath diff --git a/testing/test_assertion.py b/testing/test_assertion.py index b659233eb..e4fe56c6f 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -209,7 +209,7 @@ class TestImportHookInstallation(object): import spamplugin return spamplugin - def iter_entry_points(name): + def iter_entry_points(group, name=None): yield DummyEntryPoint() pkg_resources.iter_entry_points = iter_entry_points diff --git a/testing/test_config.py b/testing/test_config.py index f9f22a63e..1e29b83f1 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -514,8 +514,8 @@ def test_preparse_ordering_with_setuptools(testdir, monkeypatch): pkg_resources = pytest.importorskip("pkg_resources") monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) - def my_iter(name): - assert name == "pytest11" + def my_iter(group, name=None): + assert group == "pytest11" class Dist(object): project_name = "spam" @@ -552,8 +552,8 @@ def test_setuptools_importerror_issue1479(testdir, monkeypatch): pkg_resources = pytest.importorskip("pkg_resources") monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) - def my_iter(name): - assert name == "pytest11" + def my_iter(group, name=None): + assert group == "pytest11" class Dist(object): project_name = "spam" @@ -583,8 +583,8 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch, block plugin_module_placeholder = object() - def my_iter(name): - assert name == "pytest11" + def my_iter(group, name=None): + assert group == "pytest11" class Dist(object): project_name = "spam" @@ -621,7 +621,7 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch, block def test_disable_plugin_autoload(testdir, monkeypatch, parse_args, should_load): pkg_resources = pytest.importorskip("pkg_resources") - def my_iter(name): + def my_iter(group, name=None): raise AssertionError("Should not be called") class PseudoPlugin(object): diff --git a/tox.ini b/tox.ini index 87d419890..59879ead3 100644 --- a/tox.ini +++ b/tox.ini @@ -12,6 +12,7 @@ envlist = py37 py38 pypy + pypy3 {py27,py37}-{pexpect,xdist,trial,numpy,pluggymaster} py27-nobyte doctesting