Skip to content

Commit 4dca9e2

Browse files
authored
Add pytest_report_header to print additional info (#123)
This can be useful to print additional information (like DocBuild version, dependencies etc.) in the pytest header. Especially when investigating a test session in a CI environment can be helpful. Currently, it only prints the DocBuild version.
1 parent 6d9fc03 commit 4dca9e2

3 files changed

Lines changed: 54 additions & 42 deletions

File tree

changelog.d/123.infra.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add ``pytest_report_header`` from pytest to print additional information
2+
in the header.

tests/conftest.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,35 @@
11
"""Pytest fixtures and global logging mock."""
22

33
from collections.abc import Callable, Generator
4+
import os
45
from pathlib import Path
56
from typing import Any, NamedTuple
67
from unittest.mock import MagicMock, Mock
7-
import os
8-
import pytest
98

109
from click.testing import CliRunner
10+
import pytest
1111

12-
# Import the module containing setup_logging for mocking
13-
import docbuild.logging
1412
import docbuild.cli as cli_module
1513
import docbuild.cli.cmd_cli as cli
1614
from docbuild.cli.context import DocBuildContext
1715
from docbuild.config import load as load_mod
1816
from docbuild.constants import DEFAULT_ENV_CONFIG_FILENAME
17+
18+
# Import the module containing setup_logging for mocking
19+
import docbuild.logging
1920
from tests.common import changedir
2021

22+
23+
# Adding info to test report header
24+
# https://docs.pytest.org/en/stable/example/simple.html#adding-info-to-test-report-header
25+
def pytest_report_header(config: pytest.Config):
26+
from docbuild.__about__ import __version__
27+
28+
return f'DocBuild Version: {__version__}'
29+
30+
2131
# --- Global Fixture to Mute Logging Setup (Debugging Step) ---
22-
@pytest.fixture(autouse=True, scope="function")
32+
@pytest.fixture(autouse=True, scope="function")
2333
def mock_setup_logging_globally(monkeypatch):
2434
"""Mocks out the setup_logging call to prevent any initialization side-effects in tests."""
2535
mock_func = MagicMock()
@@ -218,4 +228,4 @@ def fake_validate_options(
218228
mock,
219229
mock_load_and_merge_configs,
220230
mock_load_single_config,
221-
)
231+
)

tests/models/config/test_env.py

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ipaddress import IPv4Address
1111

1212
from docbuild.models.config.env import EnvConfig, Env_Server
13-
import docbuild.config.app as config_app_mod
13+
import docbuild.config.app as config_app_mod
1414

1515

1616
# --- Fixture Setup ---
@@ -19,10 +19,10 @@ def _mock_successful_placeholder_resolver(data: dict[str, Any]) -> dict[str, Any
1919
"""Mocks the placeholder resolver to return a guaranteed clean, resolved dictionary."""
2020

2121
resolved_data = data.copy()
22-
22+
2323
# Define resolved paths based on the EnvConfig structure
2424
tmp_general = '/var/tmp/docbuild/doc-example-com'
25-
25+
2626
resolved_data['paths']['config_dir'] = '/etc/docbuild'
2727
resolved_data['paths']['root_config_dir'] = '/etc/docbuild'
2828
resolved_data['paths']['jinja_dir'] = '/etc/docbuild/jinja-doc-suse-com'
@@ -43,10 +43,10 @@ def _mock_successful_placeholder_resolver(data: dict[str, Any]) -> dict[str, Any
4343
resolved_data['paths']['tmp']['tmp_deliverable_name'] = '{{product}}_{{docset}}_{{lang}}_XXXXXX'
4444
resolved_data['paths']['target']['target_path'] = '[email protected]:/srv/docs'
4545
resolved_data['paths']['target']['backup_path'] = Path('/data/docbuild/external-builds/')
46-
47-
# Ensure mandatory top-level fields (like 'build') are present
46+
47+
# Ensure mandatory top-level fields (like 'build') are present
4848
resolved_data.setdefault(
49-
'build',
49+
'build',
5050
{'daps': {'command': 'daps', 'meta': 'daps meta'}, 'container': {'container': 'registry.example.com/container'}}
5151
)
5252

@@ -59,7 +59,7 @@ def mock_placeholder_resolution(monkeypatch):
5959

6060
monkeypatch.setattr(
6161
config_app_mod,
62-
'replace_placeholders',
62+
'replace_placeholders',
6363
_mock_successful_placeholder_resolver
6464
)
6565

@@ -79,7 +79,7 @@ def mock_valid_raw_env_data(tmp_path: Path) -> dict[str, Any]:
7979
'search': {'description': {'length': 118}},
8080
'socialmedia': {'description': {'length': 65}},
8181
}
82-
82+
8383
return {
8484
'server': {
8585
'name': 'doc-example-com',
@@ -103,15 +103,15 @@ def mock_valid_raw_env_data(tmp_path: Path) -> dict[str, Any]:
103103
'temp_repo_dir': '/var/cache/docbuild/repos/temporary-branches/',
104104
'base_cache_dir': '/var/cache/docserv',
105105
'meta_cache_dir': '/var/cache/docbuild/doc-example-com/meta',
106-
106+
107107
'tmp': {
108108
'tmp_base_dir': '/var/tmp/docbuild',
109-
'tmp_dir': '{tmp_base_dir}/doc-example-com',
109+
'tmp_dir': '{tmp_base_dir}/doc-example-com',
110110
'tmp_deliverable_dir': '{tmp_dir}/deliverable/',
111111
'tmp_build_dir': '{tmp_dir}/build/{{product}}-{{docset}}-{{lang}}',
112112
'tmp_out_dir': '{tmp_dir}/out/',
113113
'log_dir': '{tmp_dir}/log',
114-
'tmp_metadata_dir': '{tmp_dir}/metadata',
114+
'tmp_metadata_dir': '{tmp_dir}/metadata',
115115
'tmp_deliverable_name': '{{product}}_{{docset}}_{{lang}}_XXXXXX',
116116
},
117117
'target': {
@@ -134,14 +134,14 @@ def test_envconfig_full_success(mock_valid_raw_env_data: dict[str, Any]):
134134

135135
config = EnvConfig.from_dict(mock_valid_raw_env_data)
136136

137-
assert isinstance(config, dict) # EnvConfig)
137+
assert isinstance(config, EnvConfig)
138138

139139
# Check type coercion for core types
140140
assert isinstance(config.paths.base_cache_dir, Path)
141-
141+
142142
assert config.paths.tmp.tmp_path.is_absolute()
143143
assert config.paths.tmp.tmp_path.name == 'doc-example-com'
144-
144+
145145
# Check that the field with runtime placeholders is correctly handled as a string
146146
assert isinstance(config.paths.tmp.tmp_build_dir, str)
147147

@@ -156,10 +156,10 @@ def test_envconfig_type_coercion_ip_host(mock_valid_raw_env_data: dict[str, Any]
156156

157157
data = mock_valid_raw_env_data.copy()
158158
data['server']['host'] = '192.168.1.1'
159-
159+
160160
config = EnvConfig.from_dict(data)
161-
162-
assert isinstance(config.server.host, IPv4Address)
161+
162+
assert isinstance(config.server.host, IPv4Address)
163163
assert str(config.server.host) == '192.168.1.1'
164164

165165

@@ -173,56 +173,56 @@ def test_envconfig_strictness_extra_field_forbid(tmp_path: Path):
173173
},
174174
'server': {'name': 'D', 'role': 'production', 'host': '1.1.1.1', 'enable_mail': True},
175175
'config': {
176-
'default_lang': 'en-us',
176+
'default_lang': 'en-us',
177177
'languages': ['en-us'],
178178
'canonical_url_domain': 'https://a.b'
179179
},
180180
'paths': {
181-
'config_dir': str(tmp_path / 'config'),
181+
'config_dir': str(tmp_path / 'config'),
182182
'root_config_dir': '/tmp',
183183
'jinja_dir': '/tmp',
184184
'server_rootfiles_dir': '/tmp',
185185
'base_server_cache_dir': '/tmp',
186186
'base_tmp_dir': '/tmp',
187-
'repo_dir': '/tmp',
188-
'temp_repo_dir': '/tmp',
187+
'repo_dir': '/tmp',
188+
'temp_repo_dir': '/tmp',
189189
'base_cache_dir': '/tmp',
190190
'meta_cache_dir': '/tmp',
191-
191+
192192
'tmp': {
193-
'tmp_base_dir': '/tmp',
193+
'tmp_base_dir': '/tmp',
194194
'tmp_dir': '/tmp',
195-
'tmp_deliverable_dir': '/tmp/deliverable',
195+
'tmp_deliverable_dir': '/tmp/deliverable',
196196
'tmp_metadata_dir': '/tmp/metadata',
197-
'tmp_build_dir': '/tmp/build/{{product}}',
198-
'tmp_out_dir': '/tmp/out',
199-
'log_dir': '/tmp/log',
197+
'tmp_build_dir': '/tmp/build/{{product}}',
198+
'tmp_out_dir': '/tmp/out',
199+
'log_dir': '/tmp/log',
200200
'tmp_deliverable_name': 'main',
201201
},
202202
'target': {
203-
'target_dir': '/srv',
204-
'backup_dir': '/mnt'
203+
'target_dir': '/srv',
204+
'backup_dir': '/mnt'
205205
},
206206
},
207-
'xslt-params': {'test': 1},
207+
'xslt-params': {'test': 1},
208208
'typo_section': {'key': 'value'}
209209
}
210-
210+
211211
with pytest.raises(ValidationError) as excinfo:
212212
EnvConfig.from_dict(raw_data)
213-
213+
214214
locs = excinfo.value.errors()[0]['loc']
215215
assert ('typo_section',) == tuple(locs)
216216

217217

218218
def test_envconfig_invalid_role_fails(mock_valid_raw_env_data: dict[str, Any]):
219219
"""Test that an invalid role string is rejected by ServerRole enum."""
220-
220+
221221
data = mock_valid_raw_env_data.copy()
222222
data['server']['role'] = 'testing_invalid'
223-
223+
224224
with pytest.raises(ValidationError) as excinfo:
225225
EnvConfig.from_dict(data)
226-
226+
227227
locs = excinfo.value.errors()[0]['loc']
228-
assert ('server', 'role') == tuple(locs)
228+
assert ('server', 'role') == tuple(locs)

0 commit comments

Comments
 (0)