3
votes

I install pytest and pytest-timeout, I follow the instrunction of pytest-timeout in https://pypi.org/project/pytest-timeout/ to set timeout for each unit test.

And I want to only fail the unit test if it run out of time, and continue to run the other unit tests.

Please see my unit tests code:

# content of test_log.py
import time
import pytest

class TestDemo(object):
    @pytest.mark.timeout(60)
    def test_01(self):
        time.sleep(2)
        assert "1"

    @pytest.mark.timeout(3)
    def test_02(self):
        time.sleep(4)
        assert "1"

    @pytest.mark.timeout(3)
    def test_03(self):
        time.sleep(1)
        assert "1"

Now the problem is, I run this code in my Windows 7, the test will stop once the second time run out of time, the 3rd unit test is not run.

I have the log like following:

D:\dev\pytestlog>pytest

================== test session starts ==============

platform win32 -- Python 3.6.4, pytest-3.8.2, py-1.5.3, pluggy-0.7.1 rootdir: D:\dev\pytestlog, inifile: plugins: timeout-1.3.2, instafail-0.4.0 collected 3 items

test_log.py .

++++++++++++++++++++++++ Timeout ++++++++++++++++++++++++

~~~~~~~~~~~~~~ Stack of MainThread (17636) ~~~~~~~~~~~~~~

File "c:\python36-32\lib\runpy.py", line 193, in _run_module_as_main "main", mod_spec) File "c:\python36-32\lib\runpy.py", line 85, in _run_code exec(code, run_globals)

... (too many logs here)

File "D:\dev\pytestlog\test_log.py", line 15, in test_02 time.sleep(4)

++++++++++++++++++++++++ Timeout ++++++++++++++++++++++++

D:\dev\pytestlog>

3
I'm wondering how a unit test can time out? Did you mock your dependencies properly?Klaus D.
Hi Klaus, you can see pypi.org/project/pytest-timeout, use @pytest.mark.timeout can mark individual tests as having a timeoutReed_Xia
What I mean: a unittest should not take a long time, if it waits for something then it is not proper unittest because it has dependencies.Klaus D.
Yes Klaus you are right in some cases, pytest is a unittest framwork and it also can do something more, in my porject some tests need access certain device, by default the test will try again and again(up to 5 minutes) if the device is not accessable, I want to fail these tests in reasonable time(like 30 sec), to make the whole test excution short.Reed_Xia
@KlausD. Pytest was originally a unit test framework but it can used for 'higher level tests" like functional tests. See for example this blog post: patricksoftwareblog.com/… (so timeout makes sense)Laurent Bristiel

3 Answers

1
votes

As alternative you can use a timeout decorator as indicates these link:

timeout decorator in windows

The test code should look like this:

# content of test_log.py
import time
from timeout import timeout

class TestDemo(object):
    @timeout(60)
    def test_01(self):
        time.sleep(2)
        assert "1"

    @timeout(3)
    def test_02(self):
        time.sleep(4)
        assert "1"

    @timeout(3)
    def test_03(self):
        time.sleep(1)
        assert "1"
0
votes

the 3rd unit test is not run. exit on first error

To exit on first error for pytest

-x, --exitfirst       exit instantly on first error or failed test.
pytest -v --exitfirst test_log.py

with nose2

-F, --fail-fast Stop the test run after the first error or failure

nose2 -F

with nosetests

 -x, --stop            Stop running tests after the first error or failure

To run all tests, regardless of errors

pytest -v --continue-on-collection-errors test_log.py 

--continue-on-collection-errors
                    Force test execution even if collection errors occur.

check your pytest config, the default is exit on first error

-1
votes

The answer is to use the signal method as described in the documentation

@pytest.mark.timeout(5, method='signal')
def test_foo():
    pass