--- /dev/null
+language: python
+python:
+- 2.7
+- 3.4
+- 3.5
+- 3.6
+- pypy
+- pypy3
+- nightly
+env:
+- TOXENV=pytest36
+- TOXENV=pytest37
+- TOXENV=pytest38
+matrix:
+ include:
+ - python: 2.7
+ env: TOXENV=flake8
+ - python: 3.5
+ env: TOXENV=flake8
+install:
+- pip install tox-travis
+script:
+- tox
+deploy:
+ provider: pypi
+ user: davehunt
+ password:
+ secure: IuoBL03YKh7rZw78aQqRrlD6YcvwSPK6nKTpoxFc3uiljOufyfV3s4rGffSxEl4gAkMlBz3SXnfPKJPqNizfp3TEJXrc84TBO/Iq+U7j43rWyUluzJ0okPgU4892aalQiEvVyrrjEaMWA5ndhX7tkyTICN0BfHlKPmMrN+1mq73y4eUQl49CJWsbhF8Qnc5tcDh2athtgFA3fG0kSWDZHdw02i2JC1qlm+WvqBfw813BeUnmR55HKRgPQMJ2whUzab7m2QBg0HkjniNXaqS+aYY8fMGrntNtEDRrWO130ioeUqpFQvg7FoigbE5eQBX07Z50lpJn5CuCgnMzOrDpkXMy7Y+k+MyxKFUWaaqZjZiKolaPSs2qW5zggmCD4ECa5g8BpfpBkUj+D6iFkYyZIJUdq2jX0JFA536L9H2E1KOATxE8u0utQvkKcJhHgWVa0iw0q14MWSVLcZ8OdzP0Bo5nVVICcZAyIj7FQn0pIRnoXQ7cIpGbmMeJUBT9n08hyUYWoxfXKNt8KNkKDww81nAVphuz6ic1KwEKIDt3MJlHHbazjt59/+SBU+L0bDhS5ZHZkHAVHyl3EP18DCAYZWJjR4TZxlLRb2o3BUTcSwqFcIlTGw1O1DbZ/LTaGRRUxwh41AY98DKxrujxerALgX3MIlaS6WkM1FbOdO+ZB1Q=
+ distributions: sdist bdist_wheel
+ on:
+ tags: true
+ repo: pytest-dev/pytest-repeat
+ python: 3.5
+ condition: "$TOXENV = pytest38"
--- /dev/null
+Release Notes
+-------------
+
+**0.8.0 (2019-02-26)**
+
+* Fix mark deprecation warnings in new pytest versions.
+
+* ``pytest-repeat`` now requires pytest>=3.6.
+
+**0.7.0 (2018-08-23)**
+
+* Move step number to the end of the parametrisation ID
+
+ * Thanks to `@gdyuldin <https://github.com/gdyuldin>`_ for suggesting
+ this enhancement and providing a patch
+
+**0.6.0 (2018-08-01)**
+
+* Add option for controlling the scope of the repeat parameterisation
+
+ * Thanks to `@gdyuldin <https://github.com/gdyuldin>`_ for suggesting
+ this enhancement and providing a patch
+
+**0.5.0 (2018-07-19)**
+
+* Allow repeating a test using a decorator (`#16 <https://github.com/pytest-dev/pytest-repeat/issues/16>`_)
+
+ * Thanks to `@Peque <https://github.com/Peque>`_ for suggesting
+ this enhancement and providing a patch
+
+**0.4.0 (2016-08-25)**
+
+* No changes - testing deploy to PyPI from Travis CI
+
+**0.4.0 (2016-08-09)**
+
+* Fix deprecation warning present in pytest 3.0 for type argument in addoption
+
+**0.3.0 (2016-06-30)**
+
+* Added support for repeating parameterised tests
+
+**0.2 (2015-10-27)**
+
+* README updates
+
+**0.1 (2015-10-19)**
+
+* Initial release
--- /dev/null
+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/.
--- /dev/null
+Metadata-Version: 1.1
+Name: pytest-repeat
+Version: 0.8.0
+Summary: pytest plugin for repeating tests
+Home-page: https://github.com/pytest-dev/pytest-repeat
+Author: Bob Silverberg
+Author-email: bsilverberg@mozilla.com
+License: Mozilla Public License 2.0 (MPL 2.0)
+Description: pytest-repeat
+ ===================
+
+ pytest-repeat is a plugin for `py.test <https://docs.pytest.org>`_ that makes it
+ easy to repeat a single test, or multiple tests, a specific number of times.
+
+ .. image:: https://img.shields.io/badge/license-MPL%202.0-blue.svg
+ :target: https://github.com/pytest-dev/pytest-repeat/blob/master/LICENSE
+ :alt: License
+ .. image:: https://img.shields.io/pypi/v/pytest-repeat.svg
+ :target: https://pypi.python.org/pypi/pytest-repeat/
+ :alt: PyPI
+ .. image:: https://img.shields.io/travis/pytest-dev/pytest-repeat.svg
+ :target: https://travis-ci.org/pytest-dev/pytest-repeat/
+ :alt: Travis
+ .. image:: https://img.shields.io/github/issues-raw/pytest-dev/pytest-repeat.svg
+ :target: https://github.com/pytest-dev/pytest-repeat/issues
+ :alt: Issues
+ .. image:: https://img.shields.io/requires/github/pytest-dev/pytest-repeat.svg
+ :target: https://requires.io/github/pytest-dev/pytest-repeat/requirements/?branch=master
+ :alt: Requirements
+
+ Requirements
+ ------------
+
+ You will need the following prerequisites in order to use pytest-repeat:
+
+ - Python 2.7, 3.4+ or PyPy
+ - py.test 2.8 or newer
+
+ Installation
+ ------------
+ To install pytest-repeat:
+
+ .. code-block:: bash
+
+ $ pip install pytest-repeat
+
+ Repeating a test
+ ----------------
+
+ Use the :code:`--count` command line option to specify how many times you want
+ your test, or tests, to be run:
+
+ .. code-block:: bash
+
+ $ py.test --count=10 test_file.py
+
+ Each test collected by py.test will be run :code:`count` times.
+
+ If you want to mark a test in your code to be repeated a number of times, you
+ can use the :code:`@pytest.mark.repeat(count)` decorator:
+
+ .. code-block:: python
+
+ import pytest
+
+
+ @pytest.mark.repeat(3)
+ def test_repeat_decorator():
+ pass
+
+ If you want to override default tests executions order, you can use :code:`--repeat-scope`
+ command line option with one of the next values: :code:`session`, :code:`module`, :code:`class` or :code:`function` (default).
+ It behaves like a scope of the pytest fixture.
+
+ :code:`function` (default) scope repeats each test :code:`count` or :code:`repeat` times before executing next test.
+ :code:`session` scope repeats whole tests session, i.e. all collected tests executed once, then all such tests executed again and etc.
+ :code:`class` and :code:`module` behaves similar :code:`session` , but repeating set of tests is a tests from class or module, not all collected tests.
+
+ Repeating 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-repeat to force the test runner to stop at the first failure.
+ For example:
+
+ .. code-block:: bash
+
+ $ py.test --count=1000 -x test_file.py
+
+ This will attempt to run test_file.py 1000 times, but will stop as soon as a failure
+ occurs.
+
+ UnitTest Style Tests
+ --------------------
+
+ Unfortunately pytest-repeat is not able to work with unittest.TestCase test classes.
+ These tests will simply always run once, regardless of :code:`--count`, and show a warning.
+
+ Resources
+ ---------
+
+ - `Release Notes <https://github.com/pytest-dev/pytest-repeat/blob/master/CHANGES.rst>`_
+ - `Issue Tracker <https://github.com/pytest-dev/pytest-repeat/issues>`_
+ - `Code <https://github.com/pytest-dev/pytest-repeat/>`_
+
+Keywords: py.test pytest repeat
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Framework :: Pytest
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Topic :: Software Development :: Testing
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
--- /dev/null
+pytest-repeat
+===================
+
+pytest-repeat is a plugin for `py.test <https://docs.pytest.org>`_ that makes it
+easy to repeat a single test, or multiple tests, a specific number of times.
+
+.. image:: https://img.shields.io/badge/license-MPL%202.0-blue.svg
+ :target: https://github.com/pytest-dev/pytest-repeat/blob/master/LICENSE
+ :alt: License
+.. image:: https://img.shields.io/pypi/v/pytest-repeat.svg
+ :target: https://pypi.python.org/pypi/pytest-repeat/
+ :alt: PyPI
+.. image:: https://img.shields.io/travis/pytest-dev/pytest-repeat.svg
+ :target: https://travis-ci.org/pytest-dev/pytest-repeat/
+ :alt: Travis
+.. image:: https://img.shields.io/github/issues-raw/pytest-dev/pytest-repeat.svg
+ :target: https://github.com/pytest-dev/pytest-repeat/issues
+ :alt: Issues
+.. image:: https://img.shields.io/requires/github/pytest-dev/pytest-repeat.svg
+ :target: https://requires.io/github/pytest-dev/pytest-repeat/requirements/?branch=master
+ :alt: Requirements
+
+Requirements
+------------
+
+You will need the following prerequisites in order to use pytest-repeat:
+
+- Python 2.7, 3.4+ or PyPy
+- py.test 2.8 or newer
+
+Installation
+------------
+To install pytest-repeat:
+
+.. code-block:: bash
+
+ $ pip install pytest-repeat
+
+Repeating a test
+----------------
+
+Use the :code:`--count` command line option to specify how many times you want
+your test, or tests, to be run:
+
+.. code-block:: bash
+
+ $ py.test --count=10 test_file.py
+
+Each test collected by py.test will be run :code:`count` times.
+
+If you want to mark a test in your code to be repeated a number of times, you
+can use the :code:`@pytest.mark.repeat(count)` decorator:
+
+.. code-block:: python
+
+ import pytest
+
+
+ @pytest.mark.repeat(3)
+ def test_repeat_decorator():
+ pass
+
+If you want to override default tests executions order, you can use :code:`--repeat-scope`
+command line option with one of the next values: :code:`session`, :code:`module`, :code:`class` or :code:`function` (default).
+It behaves like a scope of the pytest fixture.
+
+:code:`function` (default) scope repeats each test :code:`count` or :code:`repeat` times before executing next test.
+:code:`session` scope repeats whole tests session, i.e. all collected tests executed once, then all such tests executed again and etc.
+:code:`class` and :code:`module` behaves similar :code:`session` , but repeating set of tests is a tests from class or module, not all collected tests.
+
+Repeating 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-repeat to force the test runner to stop at the first failure.
+For example:
+
+.. code-block:: bash
+
+ $ py.test --count=1000 -x test_file.py
+
+This will attempt to run test_file.py 1000 times, but will stop as soon as a failure
+occurs.
+
+UnitTest Style Tests
+--------------------
+
+Unfortunately pytest-repeat is not able to work with unittest.TestCase test classes.
+These tests will simply always run once, regardless of :code:`--count`, and show a warning.
+
+Resources
+---------
+
+- `Release Notes <https://github.com/pytest-dev/pytest-repeat/blob/master/CHANGES.rst>`_
+- `Issue Tracker <https://github.com/pytest-dev/pytest-repeat/issues>`_
+- `Code <https://github.com/pytest-dev/pytest-repeat/>`_
--- /dev/null
+Metadata-Version: 1.1
+Name: pytest-repeat
+Version: 0.8.0
+Summary: pytest plugin for repeating tests
+Home-page: https://github.com/pytest-dev/pytest-repeat
+Author: Bob Silverberg
+Author-email: bsilverberg@mozilla.com
+License: Mozilla Public License 2.0 (MPL 2.0)
+Description: pytest-repeat
+ ===================
+
+ pytest-repeat is a plugin for `py.test <https://docs.pytest.org>`_ that makes it
+ easy to repeat a single test, or multiple tests, a specific number of times.
+
+ .. image:: https://img.shields.io/badge/license-MPL%202.0-blue.svg
+ :target: https://github.com/pytest-dev/pytest-repeat/blob/master/LICENSE
+ :alt: License
+ .. image:: https://img.shields.io/pypi/v/pytest-repeat.svg
+ :target: https://pypi.python.org/pypi/pytest-repeat/
+ :alt: PyPI
+ .. image:: https://img.shields.io/travis/pytest-dev/pytest-repeat.svg
+ :target: https://travis-ci.org/pytest-dev/pytest-repeat/
+ :alt: Travis
+ .. image:: https://img.shields.io/github/issues-raw/pytest-dev/pytest-repeat.svg
+ :target: https://github.com/pytest-dev/pytest-repeat/issues
+ :alt: Issues
+ .. image:: https://img.shields.io/requires/github/pytest-dev/pytest-repeat.svg
+ :target: https://requires.io/github/pytest-dev/pytest-repeat/requirements/?branch=master
+ :alt: Requirements
+
+ Requirements
+ ------------
+
+ You will need the following prerequisites in order to use pytest-repeat:
+
+ - Python 2.7, 3.4+ or PyPy
+ - py.test 2.8 or newer
+
+ Installation
+ ------------
+ To install pytest-repeat:
+
+ .. code-block:: bash
+
+ $ pip install pytest-repeat
+
+ Repeating a test
+ ----------------
+
+ Use the :code:`--count` command line option to specify how many times you want
+ your test, or tests, to be run:
+
+ .. code-block:: bash
+
+ $ py.test --count=10 test_file.py
+
+ Each test collected by py.test will be run :code:`count` times.
+
+ If you want to mark a test in your code to be repeated a number of times, you
+ can use the :code:`@pytest.mark.repeat(count)` decorator:
+
+ .. code-block:: python
+
+ import pytest
+
+
+ @pytest.mark.repeat(3)
+ def test_repeat_decorator():
+ pass
+
+ If you want to override default tests executions order, you can use :code:`--repeat-scope`
+ command line option with one of the next values: :code:`session`, :code:`module`, :code:`class` or :code:`function` (default).
+ It behaves like a scope of the pytest fixture.
+
+ :code:`function` (default) scope repeats each test :code:`count` or :code:`repeat` times before executing next test.
+ :code:`session` scope repeats whole tests session, i.e. all collected tests executed once, then all such tests executed again and etc.
+ :code:`class` and :code:`module` behaves similar :code:`session` , but repeating set of tests is a tests from class or module, not all collected tests.
+
+ Repeating 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-repeat to force the test runner to stop at the first failure.
+ For example:
+
+ .. code-block:: bash
+
+ $ py.test --count=1000 -x test_file.py
+
+ This will attempt to run test_file.py 1000 times, but will stop as soon as a failure
+ occurs.
+
+ UnitTest Style Tests
+ --------------------
+
+ Unfortunately pytest-repeat is not able to work with unittest.TestCase test classes.
+ These tests will simply always run once, regardless of :code:`--count`, and show a warning.
+
+ Resources
+ ---------
+
+ - `Release Notes <https://github.com/pytest-dev/pytest-repeat/blob/master/CHANGES.rst>`_
+ - `Issue Tracker <https://github.com/pytest-dev/pytest-repeat/issues>`_
+ - `Code <https://github.com/pytest-dev/pytest-repeat/>`_
+
+Keywords: py.test pytest repeat
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Framework :: Pytest
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Topic :: Software Development :: Testing
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
--- /dev/null
+.gitignore
+.travis.yml
+CHANGES.rst
+LICENSE
+README.rst
+pytest_repeat.py
+setup.cfg
+setup.py
+test_repeat.py
+tox.ini
+pytest_repeat.egg-info/PKG-INFO
+pytest_repeat.egg-info/SOURCES.txt
+pytest_repeat.egg-info/dependency_links.txt
+pytest_repeat.egg-info/entry_points.txt
+pytest_repeat.egg-info/requires.txt
+pytest_repeat.egg-info/top_level.txt
\ No newline at end of file
--- /dev/null
+[pytest11]
+repeat = pytest_repeat
+
--- /dev/null
+pytest>=3.6
--- /dev/null
+pytest_repeat
--- /dev/null
+# 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/.
+import warnings
+from unittest import TestCase
+
+import pytest
+
+
+def pytest_addoption(parser):
+ parser.addoption(
+ '--count',
+ action='store',
+ default=1,
+ type=int,
+ help='Number of times to repeat each test')
+
+ parser.addoption(
+ '--repeat-scope',
+ action='store',
+ default='function',
+ type=str,
+ choices=('function', 'class', 'module', 'session'),
+ help='Scope for repeating tests')
+
+
+def pytest_configure(config):
+ config.addinivalue_line(
+ 'markers',
+ 'repeat(n): run the given test function `n` times.')
+
+
+class UnexpectedError(Exception):
+ pass
+
+
+@pytest.fixture(autouse=True)
+def __pytest_repeat_step_number(request):
+ if request.config.option.count > 1:
+ try:
+ return request.param
+ except AttributeError:
+ if issubclass(request.cls, TestCase):
+ warnings.warn(
+ "Repeating unittest class tests not supported")
+ else:
+ raise UnexpectedError(
+ "This call couldn't work with pytest-repeat. "
+ "Please consider raising an issue with your usage.")
+
+
+@pytest.hookimpl(trylast=True)
+def pytest_generate_tests(metafunc):
+ count = metafunc.config.option.count
+ m = metafunc.definition.get_closest_marker('repeat')
+ if m is not None:
+ count = int(m.args[0])
+ if count > 1:
+
+ def make_progress_id(i, n=count):
+ return '{0}-{1}'.format(i + 1, n)
+
+ scope = metafunc.config.option.repeat_scope
+ metafunc.parametrize(
+ '__pytest_repeat_step_number',
+ range(count),
+ indirect=True,
+ ids=make_progress_id,
+ scope=scope
+ )
--- /dev/null
+[bdist_wheel]
+universal = 1
+
+[egg_info]
+tag_build =
+tag_date = 0
+
--- /dev/null
+from setuptools import setup
+
+setup(name='pytest-repeat',
+ use_scm_version=True,
+ description='pytest plugin for repeating tests',
+ long_description=open('README.rst').read(),
+ author='Bob Silverberg',
+ author_email='bsilverberg@mozilla.com',
+ url='https://github.com/pytest-dev/pytest-repeat',
+ py_modules=['pytest_repeat'],
+ entry_points={'pytest11': ['repeat = pytest_repeat']},
+ setup_requires=['setuptools_scm'],
+ install_requires=['pytest>=3.6'],
+ license='Mozilla Public License 2.0 (MPL 2.0)',
+ keywords='py.test pytest repeat',
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Framework :: Pytest',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
+ 'Operating System :: POSIX',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Topic :: Software Development :: Quality Assurance',
+ 'Topic :: Software Development :: Testing',
+ 'Topic :: Utilities',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6'])
--- /dev/null
+# 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/.
+
+import pytest
+
+pytest_plugins = "pytester",
+
+
+class TestRepeat:
+
+ def test_no_repeat(self, testdir):
+ testdir.makepyfile("""
+ def test_no_repeat():
+ pass
+ """)
+ result = testdir.runpytest('-v', '--count', '1')
+ result.stdout.fnmatch_lines([
+ '*test_no_repeat.py::test_no_repeat PASSED*',
+ '*1 passed*',
+ ])
+ assert result.ret == 0
+
+ def test_can_repeat(self, testdir):
+ testdir.makepyfile("""
+ def test_repeat():
+ pass
+ """)
+ result = testdir.runpytest('--count', '2')
+ result.stdout.fnmatch_lines(['*2 passed*'])
+ assert result.ret == 0
+
+ def test_mark_repeat_decorator_is_registered(self, testdir):
+ result = testdir.runpytest('--markers')
+ result.stdout.fnmatch_lines([
+ '@pytest.mark.repeat(n): run the given test function `n` times.'])
+ assert result.ret == 0
+
+ def test_mark_repeat_decorator(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.repeat(3)
+ def test_mark_repeat_decorator():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['*3 passed*'])
+ assert result.ret == 0
+
+ def test_parametrize(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('x', ['a', 'b', 'c'])
+ def test_repeat(x):
+ pass
+ """)
+ result = testdir.runpytest('-v', '--count', '2')
+ result.stdout.fnmatch_lines([
+ '*test_parametrize.py::test_repeat[[]a-1-2[]] PASSED*',
+ '*test_parametrize.py::test_repeat[[]a-2-2[]] PASSED*',
+ '*test_parametrize.py::test_repeat[[]b-1-2[]] PASSED*',
+ '*test_parametrize.py::test_repeat[[]b-2-2[]] PASSED*',
+ '*test_parametrize.py::test_repeat[[]c-1-2[]] PASSED*',
+ '*test_parametrize.py::test_repeat[[]c-2-2[]] PASSED*',
+ '*6 passed*',
+ ])
+ assert result.ret == 0
+
+ def test_parametrized_fixture(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(params=['a', 'b', 'c'])
+ def parametrized_fixture(request):
+ return request.param
+
+ def test_repeat(parametrized_fixture):
+ pass
+ """)
+ result = testdir.runpytest('--count', '2')
+ result.stdout.fnmatch_lines(['*6 passed*'])
+ assert result.ret == 0
+
+ def test_step_number(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ expected_steps = iter(range(5))
+ def test_repeat(__pytest_repeat_step_number):
+ assert next(expected_steps) == __pytest_repeat_step_number
+ if __pytest_repeat_step_number == 4:
+ assert not list(expected_steps)
+ """)
+ result = testdir.runpytest('-v', '--count', '5')
+ result.stdout.fnmatch_lines([
+ '*test_step_number.py::test_repeat[[]1-5[]] PASSED*',
+ '*test_step_number.py::test_repeat[[]2-5[]] PASSED*',
+ '*test_step_number.py::test_repeat[[]3-5[]] PASSED*',
+ '*test_step_number.py::test_repeat[[]4-5[]] PASSED*',
+ '*test_step_number.py::test_repeat[[]5-5[]] PASSED*',
+ '*5 passed*',
+ ])
+ assert result.ret == 0
+
+ def test_invalid_option(self, testdir):
+ testdir.makepyfile("""
+ def test_repeat():
+ pass
+ """)
+ result = testdir.runpytest('--count', 'a')
+ assert result.ret == 4
+
+ def test_unittest_test(self, testdir):
+ testdir.makepyfile("""
+ from unittest import TestCase
+
+ class ClassStyleTest(TestCase):
+ def test_this(self):
+ assert 1
+ """)
+ result = testdir.runpytest('-v', '--count', '2')
+ result.stdout.fnmatch_lines([
+ '*test_unittest_test.py::ClassStyleTest::test_this PASSED*',
+ '*1 passed*',
+ ])
+
+ @pytest.mark.parametrize(['scope', 'lines'], [
+ ('session', [
+ '*test_1.py::test_repeat1[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat1[[]2-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]2-2[]] PASSED*',
+ '*16 passed*',
+ ]),
+ ('module', [
+ '*test_1.py::test_repeat1[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat1[[]2-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]2-2[]] PASSED*',
+ '*16 passed*',
+ ]),
+ ('class', [
+ '*test_1.py::test_repeat1[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat1[[]2-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]2-2[]] PASSED*',
+ '*16 passed*',
+ ]),
+ ('function', [
+ '*test_1.py::test_repeat1[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat1[[]2-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]1-2[]] PASSED*',
+ '*test_1.py::test_repeat2[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat3[[]2-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]1-2[]] PASSED*',
+ '*test_2.py::test_repeat4[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat5[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat1::test_repeat6[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat7[[]2-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]1-2[]] PASSED*',
+ '*test_3.py::TestRepeat2::test_repeat8[[]2-2[]] PASSED*',
+ '*16 passed*',
+ ]),
+ ])
+ def test_scope(self, testdir, scope, lines):
+ testdir.makepyfile(test_1="""
+ def test_repeat1():
+ pass
+
+ def test_repeat2():
+ pass
+ """)
+ testdir.makepyfile(test_2="""
+ def test_repeat3():
+ pass
+
+ def test_repeat4():
+ pass
+ """)
+ testdir.makepyfile(test_3="""
+ class TestRepeat1(object):
+ def test_repeat5(self):
+ pass
+ def test_repeat6(self):
+ pass
+ class TestRepeat2(object):
+ def test_repeat7(self):
+ pass
+ def test_repeat8(self):
+ pass
+ """)
+ result = testdir.runpytest('-v', '--count', '2', '--repeat-scope',
+ scope)
+ result.stdout.fnmatch_lines(lines)
+ assert result.ret == 0
+
+ def test_omitted_scope(self, testdir):
+ testdir.makepyfile("""
+ def test_repeat1():
+ pass
+
+ def test_repeat2():
+ pass
+ """)
+ result = testdir.runpytest('-v', '--count', '2')
+ result.stdout.fnmatch_lines([
+ '*test_omitted_scope.py::test_repeat1[[]1-2[]] PASSED*',
+ '*test_omitted_scope.py::test_repeat1[[]2-2[]] PASSED*',
+ '*test_omitted_scope.py::test_repeat2[[]1-2[]] PASSED*',
+ '*test_omitted_scope.py::test_repeat2[[]2-2[]] PASSED*',
+ '*4 passed*',
+ ])
+ assert result.ret == 0
+
+ def test_invalid_scope(self, testdir):
+ testdir.makepyfile("""
+ def test_repeat():
+ pass
+ """)
+ result = testdir.runpytest('--count', '2', '--repeat-scope', 'a')
+ assert result.ret == 4
--- /dev/null
+# Tox (https://tox.readthedocs.io/) is a tool for running tests
+# in multiple virtualenvs. This configuration file will run the
+# test suite on all supported python versions. To use it, "pip install tox"
+# and then run "tox" from this directory.
+
+[tox]
+envlist = py{27,34,35,36,py,py3}-pytest{36,37,38}, flake8
+
+[testenv]
+commands = pytest {posargs}
+deps =
+ pytest36: pytest~=3.6
+ pytest37: pytest~=3.7
+ pytest38: pytest~=3.8
+
+[testenv:flake8]
+basepython = python
+deps = flake8
+commands = flake8 {posargs:pytest_repeat.py test_repeat.py}