pytest-loop
===========
pytest-loop is a plugin for `pytest <https://docs.pytest.org>`_ that makes it
easy to loop a single test, or multiple tests, a specific number of times or for a certain duration of time.
This plugin merges pytest-repeat and pytest-stress with a fix for test results.
.. image:: https://img.shields.io/badge/license-MPL%202.0-blue.svg
:target: https://github.com/anogowski/pytest-loop/blob/master/LICENSE
:alt: License
.. image:: https://img.shields.io/pypi/v/pytest-loop.svg
:target: https://pypi.python.org/pypi/pytest-loop/
:alt: PyPI
.. image:: https://img.shields.io/pypi/pyversions/pytest-loop.svg
:target: https://pypi.org/project/pytest-loop/
:alt: Python versions
.. image:: https://github.com/anogowski/pytest-loop/actions/workflows/test.yml/badge.svg
:target: https://github.com/anogowski/pytest-cov/actions
:alt: See Build Status on GitHub Actions
.. image:: https://img.shields.io/github/issues-raw/anogowski/pytest-loop.svg
:target: https://github.com/anogowski/pytest-loop/issues
:alt: Issues
.. image:: https://img.shields.io/requires/github/anogowski/pytest-loop.svg
:target: https://requires.io/github/anogowski/pytest-loop/requirements/?branch=master
:alt: Requirements
Requirements
------------
You will need the following prerequisites in order to use pytest-loop:
- Python 3.7+ or PyPy
- pytest 7 or newer
Installation
------------
To install pytest-loop:
.. code-block:: bash
$ pip install pytest-loop
Usage
-----
Iterative Loop:
^^^^^^^^^^^^^^^
Use the :code:`--loop` command line option to specify how many times you want
your test, or tests, to be run:
.. code-block:: bash
$ pytest --loop=10 test_file.py
Each test collected by pytest will be run :code:`n` times.
If you want to mark a test in your code to be looped a number of times, you
can use the :code:`@pytest.mark.loop(n)` decorator:
.. code-block:: python
import pytest
@pytest.mark.loop(3)
def test_loop_decorator():
pass
Time based loop:
^^^^^^^^^^^^^^^^
Loop tests for 30 seconds::
$ pytest --seconds 30
Loop tests for 45 minutes::
$ pytest --minutes 45
Loop tests for 8 hours::
$ pytest --hours 8
Loop tests for 1 hour 8 minutes and 9 seconds::
$ pytest --hours 1 --minutes 8 --seconds 9
Need to wait some time after each test loop?::
$ pytest --delay 5 --hours 4 --minutes 30
You can also add these values to config files::
[pytest]
addopts = --hours 1 --minutes 30
Note: These loop times include setup and teardown operations as well. So if you have a test setup that takes 5
seconds, your actual tests will run for 5 seconds less than your desired time.
looping a test until failure:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you are trying to diagnose an intermittent failure, it can be useful to run the same
test over and over again until it fails. You can use pytest's :code:`-x` option in
conjunction with pytest-loop to force the test runner to stop at the first failure.
For example:
.. code-block:: bash
$ pytest --loop=1000 -x test_file.py
This will attempt to run test_file.py 1000 times, but will stop as soon as a failure
occurs.
.. code-block:: bash
$ pytest --hours 10 -x test_file.
This will attempt to run test_file.py for 10 hours, but will stop as soon as a failure
occurs.
UnitTest Style Tests
--------------------
Unfortunately pytest-loop is not able to work with unittest.TestCase test classes.
These tests will simply always run once, regardless of :code:`--loop`, and show a warning.
Resources
---------
- `Release Notes <https://github.com/anogowski/pytest-loop/blob/master/CHANGES.rst>`_
- `Issue Tracker <https://github.com/anogowski/pytest-loop/issues>`_
- `Code <https://github.com/anogowski/pytest-loop/>`_
Raw data
{
"_id": null,
"home_page": null,
"name": "pytest-loop",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "duration, loop, pytest, pytest-loop, pytest-repeat, pytest-rerun, pytest-stress, repeat, rerun, stress, test, time",
"author": "Adam Nogowski",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/31/a6/cacf098388cf5998970a5a5c9c8a298b91131ac6350cf372a57fc0c7cdda/pytest_loop-1.0.13.tar.gz",
"platform": null,
"description": "pytest-loop\n===========\n\npytest-loop is a plugin for `pytest <https://docs.pytest.org>`_ that makes it\neasy to loop a single test, or multiple tests, a specific number of times or for a certain duration of time.\nThis plugin merges pytest-repeat and pytest-stress with a fix for test results.\n\n.. image:: https://img.shields.io/badge/license-MPL%202.0-blue.svg\n :target: https://github.com/anogowski/pytest-loop/blob/master/LICENSE\n :alt: License\n.. image:: https://img.shields.io/pypi/v/pytest-loop.svg\n :target: https://pypi.python.org/pypi/pytest-loop/\n :alt: PyPI\n.. image:: https://img.shields.io/pypi/pyversions/pytest-loop.svg\n :target: https://pypi.org/project/pytest-loop/\n :alt: Python versions\n.. image:: https://github.com/anogowski/pytest-loop/actions/workflows/test.yml/badge.svg\n :target: https://github.com/anogowski/pytest-cov/actions\n :alt: See Build Status on GitHub Actions\n.. image:: https://img.shields.io/github/issues-raw/anogowski/pytest-loop.svg\n :target: https://github.com/anogowski/pytest-loop/issues\n :alt: Issues\n.. image:: https://img.shields.io/requires/github/anogowski/pytest-loop.svg\n :target: https://requires.io/github/anogowski/pytest-loop/requirements/?branch=master\n :alt: Requirements\n\nRequirements\n------------\n\nYou will need the following prerequisites in order to use pytest-loop:\n- Python 3.7+ or PyPy\n- pytest 7 or newer\n\nInstallation\n------------\n\nTo install pytest-loop:\n\n.. code-block:: bash\n\n $ pip install pytest-loop\n\nUsage\n-----\n\nIterative Loop:\n^^^^^^^^^^^^^^^\nUse the :code:`--loop` command line option to specify how many times you want\nyour test, or tests, to be run:\n\n.. code-block:: bash\n\n $ pytest --loop=10 test_file.py\n\nEach test collected by pytest will be run :code:`n` times.\n\nIf you want to mark a test in your code to be looped a number of times, you\ncan use the :code:`@pytest.mark.loop(n)` decorator:\n\n.. code-block:: python\n\n import pytest\n\n\n @pytest.mark.loop(3)\n def test_loop_decorator():\n pass\n\n\n\nTime based loop:\n^^^^^^^^^^^^^^^^\n\nLoop tests for 30 seconds::\n\n $ pytest --seconds 30\n\nLoop tests for 45 minutes::\n\n $ pytest --minutes 45\n\nLoop tests for 8 hours::\n\n $ pytest --hours 8\n\nLoop tests for 1 hour 8 minutes and 9 seconds::\n\n $ pytest --hours 1 --minutes 8 --seconds 9\n\nNeed to wait some time after each test loop?::\n\n $ pytest --delay 5 --hours 4 --minutes 30\n\nYou can also add these values to config files::\n\n [pytest]\n addopts = --hours 1 --minutes 30\n\nNote: These loop times include setup and teardown operations as well. So if you have a test setup that takes 5\nseconds, your actual tests will run for 5 seconds less than your desired time.\n\nlooping a test until failure:\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIf you are trying to diagnose an intermittent failure, it can be useful to run the same\ntest over and over again until it fails. You can use pytest's :code:`-x` option in\nconjunction with pytest-loop to force the test runner to stop at the first failure.\nFor example:\n\n.. code-block:: bash\n\n $ pytest --loop=1000 -x test_file.py\n\nThis will attempt to run test_file.py 1000 times, but will stop as soon as a failure\noccurs.\n\n.. code-block:: bash\n\n $ pytest --hours 10 -x test_file.\n\nThis will attempt to run test_file.py for 10 hours, but will stop as soon as a failure\noccurs.\n\nUnitTest Style Tests\n--------------------\n\nUnfortunately pytest-loop is not able to work with unittest.TestCase test classes.\nThese tests will simply always run once, regardless of :code:`--loop`, and show a warning.\n\nResources\n---------\n\n- `Release Notes <https://github.com/anogowski/pytest-loop/blob/master/CHANGES.rst>`_\n- `Issue Tracker <https://github.com/anogowski/pytest-loop/issues>`_\n- `Code <https://github.com/anogowski/pytest-loop/>`_",
"bugtrack_url": null,
"license": "This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://www.mozilla.org/en-US/MPL/2.0/.",
"summary": "pytest plugin for looping tests",
"version": "1.0.13",
"project_urls": {
"Changelog": "https://github.com/anogowski/pytest-loop/blob/master/CHANGELOG.rst",
"Homepage": "https://github.com/anogowski/pytest-loop",
"Issues": "https://github.com/anogowski/pytest-loop/issues",
"Repository": "https://github.com/anogowski/pytest-loop.git"
},
"split_keywords": [
"duration",
" loop",
" pytest",
" pytest-loop",
" pytest-repeat",
" pytest-rerun",
" pytest-stress",
" repeat",
" rerun",
" stress",
" test",
" time"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "a2f2204ff93e2ab8232b70dd45fde3c6cad10ac6ab4298dc96ed2f0e9d52a288",
"md5": "d649ac29b0eeb627284eefecf9d270f1",
"sha256": "8d902c801413c5a16ee70d618259161a38f9f188f9d7a986ccc557deabca4f84"
},
"downloads": -1,
"filename": "pytest_loop-1.0.13-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d649ac29b0eeb627284eefecf9d270f1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 6233,
"upload_time": "2024-10-17T23:52:00",
"upload_time_iso_8601": "2024-10-17T23:52:00.957496Z",
"url": "https://files.pythonhosted.org/packages/a2/f2/204ff93e2ab8232b70dd45fde3c6cad10ac6ab4298dc96ed2f0e9d52a288/pytest_loop-1.0.13-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "31a6cacf098388cf5998970a5a5c9c8a298b91131ac6350cf372a57fc0c7cdda",
"md5": "98365f49606d5068f92350f1d2569a5f",
"sha256": "be396c0293c4a23e9c96b99f696ad0afd6ae5e4b23d4ca0724eda0660530e5a0"
},
"downloads": -1,
"filename": "pytest_loop-1.0.13.tar.gz",
"has_sig": false,
"md5_digest": "98365f49606d5068f92350f1d2569a5f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 12645,
"upload_time": "2024-10-17T23:52:01",
"upload_time_iso_8601": "2024-10-17T23:52:01.847510Z",
"url": "https://files.pythonhosted.org/packages/31/a6/cacf098388cf5998970a5a5c9c8a298b91131ac6350cf372a57fc0c7cdda/pytest_loop-1.0.13.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-17 23:52:01",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "anogowski",
"github_project": "pytest-loop",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "anyio",
"specs": [
[
"==",
"4.6.2.post1"
]
]
},
{
"name": "arrow",
"specs": [
[
"==",
"1.3.0"
]
]
},
{
"name": "backports.tarfile",
"specs": [
[
"==",
"1.2.0"
]
]
},
{
"name": "binaryornot",
"specs": [
[
"==",
"0.4.4"
]
]
},
{
"name": "build",
"specs": [
[
"==",
"1.2.2.post1"
]
]
},
{
"name": "cachetools",
"specs": [
[
"==",
"5.5.0"
]
]
},
{
"name": "certifi",
"specs": [
[
"==",
"2024.8.30"
]
]
},
{
"name": "chardet",
"specs": [
[
"==",
"5.2.0"
]
]
},
{
"name": "charset-normalizer",
"specs": [
[
"==",
"3.4.0"
]
]
},
{
"name": "click",
"specs": [
[
"==",
"8.1.7"
]
]
},
{
"name": "colorama",
"specs": [
[
"==",
"0.4.6"
]
]
},
{
"name": "cookiecutter",
"specs": [
[
"==",
"2.6.0"
]
]
},
{
"name": "distlib",
"specs": [
[
"==",
"0.3.9"
]
]
},
{
"name": "filelock",
"specs": [
[
"==",
"3.16.1"
]
]
},
{
"name": "h11",
"specs": [
[
"==",
"0.14.0"
]
]
},
{
"name": "hatch",
"specs": [
[
"==",
"1.13.0"
]
]
},
{
"name": "hatchling",
"specs": [
[
"==",
"1.25.0"
]
]
},
{
"name": "httpcore",
"specs": [
[
"==",
"1.0.6"
]
]
},
{
"name": "httpx",
"specs": [
[
"==",
"0.27.2"
]
]
},
{
"name": "hyperlink",
"specs": [
[
"==",
"21.0.0"
]
]
},
{
"name": "idna",
"specs": [
[
"==",
"3.10"
]
]
},
{
"name": "importlib_metadata",
"specs": [
[
"==",
"8.5.0"
]
]
},
{
"name": "iniconfig",
"specs": [
[
"==",
"2.0.0"
]
]
},
{
"name": "jaraco.classes",
"specs": [
[
"==",
"3.4.0"
]
]
},
{
"name": "jaraco.context",
"specs": [
[
"==",
"6.0.1"
]
]
},
{
"name": "jaraco.functools",
"specs": [
[
"==",
"4.1.0"
]
]
},
{
"name": "Jinja2",
"specs": [
[
"==",
"3.1.4"
]
]
},
{
"name": "keyring",
"specs": [
[
"==",
"25.4.1"
]
]
},
{
"name": "markdown-it-py",
"specs": [
[
"==",
"3.0.0"
]
]
},
{
"name": "MarkupSafe",
"specs": [
[
"==",
"3.0.1"
]
]
},
{
"name": "mdurl",
"specs": [
[
"==",
"0.1.2"
]
]
},
{
"name": "more-itertools",
"specs": [
[
"==",
"10.5.0"
]
]
},
{
"name": "nh3",
"specs": [
[
"==",
"0.2.18"
]
]
},
{
"name": "packaging",
"specs": [
[
"==",
"24.1"
]
]
},
{
"name": "pathspec",
"specs": [
[
"==",
"0.12.1"
]
]
},
{
"name": "pexpect",
"specs": [
[
"==",
"4.9.0"
]
]
},
{
"name": "pkginfo",
"specs": [
[
"==",
"1.11.2"
]
]
},
{
"name": "platformdirs",
"specs": [
[
"==",
"4.3.6"
]
]
},
{
"name": "pluggy",
"specs": [
[
"==",
"1.5.0"
]
]
},
{
"name": "ptyprocess",
"specs": [
[
"==",
"0.7.0"
]
]
},
{
"name": "Pygments",
"specs": [
[
"==",
"2.18.0"
]
]
},
{
"name": "pyproject-api",
"specs": [
[
"==",
"1.8.0"
]
]
},
{
"name": "pyproject_hooks",
"specs": [
[
"==",
"1.2.0"
]
]
},
{
"name": "pytest",
"specs": [
[
"==",
"8.3.3"
]
]
},
{
"name": "pytest-html",
"specs": [
[
"==",
"4.1.1"
]
]
},
{
"name": "pytest-metadata",
"specs": [
[
"==",
"3.1.1"
]
]
},
{
"name": "python-dateutil",
"specs": [
[
"==",
"2.9.0.post0"
]
]
},
{
"name": "python-slugify",
"specs": [
[
"==",
"8.0.4"
]
]
},
{
"name": "pywin32-ctypes",
"specs": [
[
"==",
"0.2.3"
]
]
},
{
"name": "PyYAML",
"specs": [
[
"==",
"6.0.2"
]
]
},
{
"name": "requests",
"specs": [
[
"==",
"2.32.3"
]
]
},
{
"name": "rfc3986",
"specs": [
[
"==",
"2.0.0"
]
]
},
{
"name": "rich",
"specs": [
[
"==",
"13.9.2"
]
]
},
{
"name": "shellingham",
"specs": [
[
"==",
"1.5.4"
]
]
},
{
"name": "six",
"specs": [
[
"==",
"1.16.0"
]
]
},
{
"name": "sniffio",
"specs": [
[
"==",
"1.3.1"
]
]
},
{
"name": "text-unidecode",
"specs": [
[
"==",
"1.3"
]
]
},
{
"name": "tomli_w",
"specs": [
[
"==",
"1.1.0"
]
]
},
{
"name": "tomlkit",
"specs": [
[
"==",
"0.13.2"
]
]
},
{
"name": "tox",
"specs": [
[
"==",
"4.23.0"
]
]
},
{
"name": "trove-classifiers",
"specs": [
[
"==",
"2024.10.16"
]
]
},
{
"name": "types-python-dateutil",
"specs": [
[
"==",
"2.9.0.20241003"
]
]
},
{
"name": "urllib3",
"specs": [
[
"==",
"2.2.3"
]
]
},
{
"name": "userpath",
"specs": [
[
"==",
"1.9.2"
]
]
},
{
"name": "uv",
"specs": [
[
"==",
"0.4.23"
]
]
},
{
"name": "versioningit",
"specs": [
[
"==",
"3.1.2"
]
]
},
{
"name": "virtualenv",
"specs": [
[
"==",
"20.26.6"
]
]
},
{
"name": "zipp",
"specs": [
[
"==",
"3.20.2"
]
]
},
{
"name": "zstandard",
"specs": [
[
"==",
"0.23.0"
]
]
}
],
"tox": true,
"lcname": "pytest-loop"
}