FreedomBox/conftest.py
Fioddor Superconcentrado cb539cf1e8
tests: Improve handling of tests skipped by default
- Create the 'heavy' mark for tests that take long to run.
- Skip the tests marked as 'heavy' by default.
- Enable functional and heavy tests by setting the environment variable
  EXTENDED_TESTING=1.
- Update HACKING.md accordingly.

Signed-off-by: Fioddor Superconcentrado <fioddor@gmail.com>
[sunil: Minor indentation]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
2021-10-10 19:22:13 -07:00

169 lines
5.0 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
"""
pytest configuration for all tests.
"""
import importlib
import os
import pathlib
import sys
from unittest.mock import patch
import pytest
try:
importlib.import_module('splinter')
_splinter_available = True
except ImportError:
_splinter_available = False
def pytest_ignore_collect(path, config):
"""Ignore functional tests when splinter is not available."""
if path.basename == 'test_functional.py':
return not _splinter_available
def pytest_addoption(parser):
"""Add a command line option to run functional tests."""
parser.addoption('--include-functional', action='store_true',
default=False, help='Run functional tests also')
def pytest_collection_modifyitems(config, items):
"""Filter out specificly marked tests unless explicitly requested.
The EXTENDED_TESTING environment variable is borrowed from the Lancaster
consensus met by the Pearl community. See
https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md
"""
def skip(item, reason):
item.add_marker(pytest.mark.skip(reason=reason))
extended = 'EXTENDED_TESTING' in os.environ
if not (extended or config.getoption('--include-functional')):
for item in items:
if 'functional' in item.keywords or (
item.parent.fspath.basename
and item.parent.fspath.basename == 'test_functional.py'):
skip(item, '--include-functional not provided')
if not extended:
for item in items:
if 'heavy' in item.keywords:
skip(item, ('Takes too much time. '
'Set EXTENDED_TESTING=1 to force run'))
@pytest.fixture(name='load_cfg')
def fixture_load_cfg():
"""Load test configuration."""
from plinth import cfg
keys = ('file_root', 'config_dir', 'data_dir', 'custom_static_dir',
'store_file', 'actions_dir', 'doc_dir', 'server_dir', 'host',
'port', 'use_x_forwarded_for', 'use_x_forwarded_host',
'secure_proxy_ssl_header', 'box_name', 'develop')
saved_state = {}
for key in keys:
saved_state[key] = getattr(cfg, key)
root_dir = pathlib.Path(__file__).resolve().parent
cfg_file = root_dir / 'plinth' / 'develop.config'
cfg.read_file(str(cfg_file))
yield cfg
for key in keys:
setattr(cfg, key, saved_state[key])
@pytest.fixture(name='develop_mode')
def fixture_develop_mode(load_cfg):
"""Turn on development mode for a test."""
load_cfg.develop = True
yield
load_cfg.develop = False
@pytest.fixture(name='needs_root', scope='session')
def fixture_needs_root():
"""Skip test if not running in root mode."""
if os.geteuid() != 0:
pytest.skip('Needs to be root')
@pytest.fixture(name='needs_not_root', scope='session')
def fixture_needs_not_root():
"""Skip test if running in root mode."""
if os.geteuid() == 0:
pytest.skip('Needs not to be root')
@pytest.fixture(name='needs_sudo')
def fixture_needs_sudo():
"""Skip test if sudo command is not available."""
if not os.path.isfile('/usr/bin/sudo'):
pytest.skip('Needs sudo command installed.')
@pytest.fixture(scope='session')
def splinter_selenium_implicit_wait():
"""Disable implicit waiting."""
return 0
@pytest.fixture(scope='session')
def splinter_wait_time():
"""Disable explicit waiting."""
return 0.01
@pytest.fixture(scope='session')
def splinter_browser_load_condition():
"""When a page it loaded, wait until <body> is available."""
def _load_condition(browser):
if browser.url == 'about:blank':
return True
ready_state = browser.execute_script('return document.readyState;')
return ready_state == 'complete'
return _load_condition
@pytest.fixture(name='actions_module', scope='module')
def fixture_actions_module(request):
"""Import and return an action module."""
actions_name = getattr(request.module, 'actions_name')
actions_file = str(
pathlib.Path(__file__).parent / 'actions' / actions_name)
loader = importlib.machinery.SourceFileLoader(actions_name, actions_file)
spec = importlib.util.spec_from_loader(actions_name, loader)
module = importlib.util.module_from_spec(spec)
sys.modules[actions_name] = module
spec.loader.exec_module(module)
return module
@pytest.fixture(name='call_action')
def fixture_call_action(request, capsys, actions_module):
"""Run actions with custom root path."""
actions_name = getattr(request.module, 'actions_name')
def _call_action(*args, **_kwargs):
if isinstance(args[0], list):
argv = [actions_name] + args[0] # Command line style usage
else:
argv = [args[0]] + args[1] # superuser_run style usage
with patch('argparse._sys.argv', argv):
actions_module.main()
captured = capsys.readouterr()
return captured.out
return _call_action