Skip to content

Fix fixture config #107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
### 1.3.2 (Unreleased)
* Fixing python 3 compatibility in Simple HTTP Server fixture
* Fixed broken tests in pytest-profiling
* Removed pytest-fixture-config decorator 'requires_config' and 'yield_requires_config' (due to incompatibility with pytest>=3.7.1)
* Pinned pytest<4.0.0 until all deprecation warnings are fixed.
* pytest-webdriver: replaced deprecated phantomjs with headless Google Chrome.

Expand Down
27 changes: 27 additions & 0 deletions pytest-fixture-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,30 @@ Simply reference the singleton at run-time in your fixtures:
watcher.communicate()
```

## Skipping tests when things are missing

There are some decorators that allow you to skip tests when settings aren't set.
This is useful when you're testing something you might not have installed
but don't want your tests suite to fail:

```python
from pytest_fixture_config import requires_config

@pytest.fixture
@requires_config(CONFIG, ['log_watcher', 'log_dir'])
def log_watcher():
return subprocess.popen([CONFIG.log_watcher, '--log-dir', CONFIG.log_dir])
```

There is also a version for yield_fixtures:

```python
from pytest_fixture_config import yield_requires_config

@pytest.fixture
@yield_requires_config(CONFIG, ['log_watcher', 'log_dir'])
def log_watcher():
watcher = subprocess.popen([CONFIG.log_watcher, '--log-dir', CONFIG.log_dir])
yield watcher
watcher.kill()
```
34 changes: 34 additions & 0 deletions pytest-fixture-config/pytest_fixture_config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
""" Fixture configuration
"""
import functools

import pytest


class Config(object):
__slots__ = ()
Expand All @@ -13,3 +17,33 @@ def update(self, cfg):
raise ValueError("Unknown config option: {0}".format(k))
setattr(self, k, cfg[k])


def requires_config(cfg, vars_):
""" Decorator for fixtures that will skip tests if the required config variables
are missing or undefined in the configuration
"""
def decorator(f):
# We need to specify 'request' in the args here to satisfy pytest's fixture logic
@functools.wraps(f)
def wrapper(request, *args, **kwargs):
for var in vars_:
if not getattr(cfg, var):
pytest.skip('config variable {0} missing, skipping test'.format(var))
return f(request, *args, **kwargs)
return wrapper
return decorator


def yield_requires_config(cfg, vars_):
""" As above but for py.test yield_fixtures
"""
def decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
for var in vars_:
if not getattr(cfg, var):
pytest.skip('config variable {0} missing, skipping test'.format(var))
gen = f(*args, **kwargs)
yield next(gen)
return wrapper
return decorator
45 changes: 44 additions & 1 deletion pytest-fixture-config/tests/unit/test_fixture_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pytest_fixture_config
reload_module(pytest_fixture_config)

from pytest_fixture_config import Config
from pytest_fixture_config import Config, requires_config, yield_requires_config

class DummyConfig(Config):
__slots__ = ('foo', 'bar')
Expand All @@ -23,3 +23,46 @@ def test_config_update():
with pytest.raises(ValueError):
cfg.update({"baz": 30})


CONFIG1 = DummyConfig(foo=None, bar=1)

@pytest.fixture
@requires_config(CONFIG1, ('foo', 'bar'))
def a_fixture(request):
raise ValueError('Should not run')


def test_requires_config_skips(a_fixture):
raise ValueError('Should not run')


@pytest.fixture
@requires_config(CONFIG1, ('bar',))
def another_fixture(request):
return 'xxxx'


def test_requires_config_doesnt_skip(another_fixture):
assert another_fixture == 'xxxx'



@pytest.yield_fixture
@yield_requires_config(CONFIG1, ('foo', 'bar'))
def yet_another_fixture():
raise ValueError('Should also not run')
yield 'yyyy'


def test_yield_requires_config_skips(yet_another_fixture):
raise ValueError('Should also not run')


@pytest.yield_fixture
@yield_requires_config(CONFIG1, ('bar',))
def yet_some_other_fixture():
yield 'yyyy'


def test_yield_requires_config_doesnt_skip(yet_some_other_fixture):
assert yet_some_other_fixture == 'yyyy'
2 changes: 2 additions & 0 deletions pytest-server-fixtures/pytest_server_fixtures/httpd.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
except ImportError:
from path import path as Path

from pytest_fixture_config import yield_requires_config
from pytest_server_fixtures import CONFIG

from .http import HTTPTestServer
Expand All @@ -17,6 +18,7 @@


@pytest.yield_fixture(scope='function')
@yield_requires_config(CONFIG, ['httpd_executable', 'httpd_modules'])
def httpd_server():
""" Function-scoped httpd server in a local thread.

Expand Down
3 changes: 3 additions & 0 deletions pytest-server-fixtures/pytest_server_fixtures/jenkins.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
import six

from pytest_server_fixtures import CONFIG
from pytest_fixture_config import yield_requires_config

from .http import HTTPTestServer


@pytest.yield_fixture(scope='session')
@yield_requires_config(CONFIG, ['jenkins_war', 'java_executable'])
def jenkins_server():
""" Session-scoped Jenkins server instance

Expand All @@ -31,6 +33,7 @@ def jenkins_server():


@pytest.yield_fixture(scope='module')
@yield_requires_config(CONFIG, ['jenkins_war', 'java_executable'])
def jenkins_server_module():
""" Module-scoped Jenkins server instance

Expand Down
5 changes: 5 additions & 0 deletions pytest-server-fixtures/pytest_server_fixtures/mongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import pytest

from pytest_server_fixtures import CONFIG
from pytest_fixture_config import yield_requires_config

from .base import TestServer

Expand All @@ -29,6 +30,7 @@ def _mongo_server():


@pytest.yield_fixture(scope='function')
@yield_requires_config(CONFIG, ['mongo_bin'])
def mongo_server():
""" Function-scoped MongoDB server started in a local thread.
This also provides a temp workspace.
Expand All @@ -47,6 +49,7 @@ def mongo_server():


@pytest.yield_fixture(scope='session')
@yield_requires_config(CONFIG, ['mongo_bin'])
def mongo_server_sess():
""" Same as mongo_server fixture, scoped as session instead.
"""
Expand All @@ -55,6 +58,7 @@ def mongo_server_sess():


@pytest.yield_fixture(scope='class')
@yield_requires_config(CONFIG, ['mongo_bin'])
def mongo_server_cls(request):
""" Same as mongo_server fixture, scoped for test classes.
"""
Expand All @@ -64,6 +68,7 @@ def mongo_server_cls(request):


@pytest.yield_fixture(scope='module')
@yield_requires_config(CONFIG, ['mongo_bin'])
def mongo_server_module():
""" Same as mongo_server fixture, scoped for test modules.
"""
Expand Down
3 changes: 3 additions & 0 deletions pytest-server-fixtures/pytest_server_fixtures/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import pytest

from pytest_server_fixtures import CONFIG
from pytest_fixture_config import requires_config

from .base import TestServer

Expand All @@ -25,6 +26,7 @@ def _redis_server(request):


@pytest.fixture(scope='function')
@requires_config(CONFIG, ['redis_executable'])
def redis_server(request):
""" Function-scoped Redis server in a local thread.

Expand All @@ -37,6 +39,7 @@ def redis_server(request):


@pytest.fixture(scope='session')
@requires_config(CONFIG, ['redis_executable'])
def redis_server_sess(request):
""" Same as redis_server fixture, scoped for test session
"""
Expand Down
3 changes: 3 additions & 0 deletions pytest-server-fixtures/pytest_server_fixtures/rethink.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest

from pytest_server_fixtures import CONFIG
from pytest_fixture_config import requires_config

from .base import TestServer

Expand All @@ -24,6 +25,7 @@ def _rethink_server(request):


@pytest.fixture(scope='function')
@requires_config(CONFIG, ['rethink_executable'])
def rethink_server(request):
""" Function-scoped RethinkDB server in a local thread.

Expand All @@ -37,6 +39,7 @@ def rethink_server(request):


@pytest.fixture(scope='session')
@requires_config(CONFIG, ['rethink_executable'])
def rethink_server_sess(request):
""" Same as rethink_server fixture, scoped as session instead.
"""
Expand Down
2 changes: 2 additions & 0 deletions pytest-server-fixtures/pytest_server_fixtures/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import pytest
from future.utils import text_type
from pytest_fixture_config import requires_config

from . import CONFIG
from .http import HTTPTestServer
Expand All @@ -26,6 +27,7 @@ def _s3_server(request):


@pytest.fixture(scope="session")
@requires_config(CONFIG, ['minio_executable'])
def s3_server(request):
"""
Creates a session-scoped temporary S3 server using the 'minio' tool.
Expand Down
3 changes: 3 additions & 0 deletions pytest-server-fixtures/pytest_server_fixtures/xvfb.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import pytest

from pytest_shutil.workspace import Workspace
from pytest_fixture_config import yield_requires_config

from pytest_server_fixtures import CONFIG


@pytest.yield_fixture(scope='function')
@yield_requires_config(CONFIG, ['xvfb_executable'])
def xvfb_server():
""" Function-scoped Xvfb (X-Windows Virtual Frame Buffer) in a local thread.
"""
Expand All @@ -22,6 +24,7 @@ def xvfb_server():


@pytest.yield_fixture(scope='session')
@yield_requires_config(CONFIG, ['xvfb_executable'])
def xvfb_server_sess():
""" Session-scoped Xvfb (X-Windows Virtual Frame Buffer) in a local thread.
"""
Expand Down
3 changes: 2 additions & 1 deletion pytest-virtualenv/pytest_virtualenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from pytest_shutil.workspace import Workspace
from pytest_shutil import run, cmdline
from pytest_fixture_config import Config
from pytest_fixture_config import Config, yield_requires_config


class FixtureConfig(Config):
Expand All @@ -29,6 +29,7 @@ class FixtureConfig(Config):


@yield_fixture(scope='function')
@yield_requires_config(CONFIG, ['virtualenv_executable'])
def virtualenv():
""" Function-scoped virtualenv in a temporary workspace.

Expand Down