0

Any way of stopping the entire pytest run from happening at a very early stage if some condition is not met. For example, if it is found that the Elasticsearch service is not running?

I have tried putting this in a common file which is imported by all test files:

try:
    requests.get('http://localhost:9200')
except requests.exceptions.ConnectionError:
    msg = 'FATAL. Connection refused: ES does not appear to be installed as a service (localhost port 9200)' 
    pytest.exit(msg)

... but tests are being run for each file and each test within each file, and large amounts of error-related output is also produced.

Obviously what I am trying to do is stop the run at the very start of the collection stage.

Obviously too, I could write a script which checks any necessary conditions before calling pytest with any CLI parameters I might pass to it. Is this the only way to accomplish this?

mike rodent
  • 14,126
  • 11
  • 103
  • 157
  • Does this answer your question? [How to stop all tests from inside a test or setUp using unittest?](https://stackoverflow.com/questions/3806695/how-to-stop-all-tests-from-inside-a-test-or-setup-using-unittest) – KokoseiJ Jan 23 '22 at 12:30
  • Thanks. Sadly no, I'd found it. But I'm not using the unittest system of `TestCase` etc. `pytest` doesn't work like that. – mike rodent Jan 23 '22 at 12:31
  • Aha. Customising test collection (https://docs.pytest.org/en/latest/example/pythoncollection.html#customizing-test-collection) might be the way to go... – mike rodent Jan 23 '22 at 12:36
  • 1
    I think you need to call `pytest.exit` either in the test itself, or in a fixture. Putting this code into a fixture (probably session-scoped and with `autouse=True`) might help. – MrBean Bremen Jan 23 '22 at 12:37
  • @MrBeanBremen Thanks for that suggestion. Trying to work that out... see edit. – mike rodent Jan 23 '22 at 12:47
  • 1
    The `scope` and `autouse` args go to the fixture decorator, not the fixture function, e.g. `@pytest.fixture(scope='session', autouse=True)`. – MrBean Bremen Jan 23 '22 at 12:50

2 Answers2

3

Try using the pytest_configure initialization hook.

In your global conftest.py:

import requests
import pytest

def pytest_configure(config):
    try:
        requests.get(f'http://localhost:9200')
    except requests.exceptions.ConnectionError:
        msg = 'FATAL. Connection refused: ES does not appear to be installed as a service (localhost port 9200)' 
        pytest.exit(msg)

Updates:

  1. Note that the single argument of pytest_configure has to be named config!
  2. Using pytest.exit makes it look nicer.
Roland Smith
  • 42,427
  • 3
  • 64
  • 94
1

Yes, MrBeanBremen's solution also works, with the following code in conftest.py:

@pytest.fixture(scope='session', autouse=True)    
def check_es():
    try:
        requests.get(f'http://localhost:9200')
    except requests.exceptions.ConnectionError:
        msg = 'FATAL. Connection refused: ES does not appear to be installed as a service (localhost port 9200)' 
        pytest.exit(msg)
mike rodent
  • 14,126
  • 11
  • 103
  • 157
  • Well, no, the fixture doesn't have to be imported if you place it into `conftest.py` as usual. And `conftest.py` lives in the test directory and is used for all tests in that directory and sub-directories. – MrBean Bremen Jan 23 '22 at 13:17
  • Thanks. You could provide your own answer if you want, and I'll delete mine. If you don't, I'll edit mine accordingly after a while. – mike rodent Jan 23 '22 at 13:19
  • There's already another answer which does the same, just not with a fixture, but with a hook. – MrBean Bremen Jan 23 '22 at 13:19