Skip to content

Commit 8e9f832

Browse files
committed
New existing_db_factory; fixed errors; release 1.20.0
1 parent a72a406 commit 8e9f832

File tree

8 files changed

+76
-12
lines changed

8 files changed

+76
-12
lines changed

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## [0.20.0] - 2024-05-09
8+
9+
### Added
10+
11+
- Fixture `existing_db_factory` to directly use database from `databases` subdirectory.
12+
It's not intended for use in Firebird QA, but it's necessary for other plugin
13+
users.
14+
15+
### Fixed
16+
17+
- Report test error also in cases when unexpected stderr is returned from tool execution
18+
while `returncode` is zero.
19+
- Select test marked for current platform also when it's not marked for Firebird version.
20+
721
## [0.19.3] - 2024-03-21
822

923
### Fixed

docs/changelog.txt

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ Changelog
44

55
.. currentmodule:: firebird.qa.plugin
66

7+
Version 0.20.0
8+
==============
9+
10+
* New `.existing_db_factory` firxture to directly use database from `databases` subdirectory.
11+
It's not intended for use in Firebird QA, but it's necessary for other plugin
12+
users.
13+
* Fix: Report test error also in cases when unexpected stderr is returned from tool execution
14+
while `returncode` is zero.
15+
* Fix: Select test marked for current platform also when it's not marked for Firebird version.
16+
17+
718
Version 0.19.3
819
==============
920

docs/reference.txt

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ db_factory
1919
----------
2020
.. autofunction:: db_factory
2121

22+
existing_db_factory
23+
-------------------
24+
.. autofunction:: existing_db_factory
25+
2226
user_factory
2327
------------
2428
.. autofunction:: user_factory

docs/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
Sphinx==7.2.6
12
sphinx-bootstrap-theme>=0.8.0
23
sphinx-autodoc-typehints>=1.17.0
34
.

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ classifiers = [
3232
"Framework :: Pytest",
3333
]
3434
dependencies = [
35-
"firebird-base>=1.7.2",
35+
"firebird-base>=1.8.0",
3636
"firebird-driver~=1.10",
3737
"pytest>=7.4",
3838
"psutil~=5.9",
@@ -89,7 +89,7 @@ python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
8989
detached = false
9090
platforms = ["linux"]
9191
dependencies = [
92-
"Sphinx>=7.2.6",
92+
"Sphinx==7.2.6",
9393
"sphinx-bootstrap-theme>=0.8.1",
9494
"sphinx-autodoc-typehints>=1.24.0",
9595
"doc2dash>=3.0.0"

src/firebird/qa/__about__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-FileCopyrightText: 2021-present The Firebird Projects <www.firebirdsql.org>
22
#
33
# SPDX-License-Identifier: MIT
4-
__version__ = "0.19.3"
4+
__version__ = "0.20.0"

src/firebird/qa/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@
4040

4141
from .plugin import db_factory, Database, user_factory, User, isql_act, python_act, Action, \
4242
temp_file, temp_files, role_factory, Role, envar_factory, Envar, Mapping, mapping_factory, \
43-
ServerKeeper, ExecutionError, QA_GLOBALS
43+
ServerKeeper, ExecutionError, QA_GLOBALS, existing_db_factory

src/firebird/qa/plugin.py

+42-8
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ def pytest_collection_modifyitems(session, config, items):
512512
item.add_marker(version_skip)
513513
else:
514514
deselected.append(item)
515+
elif platform_ok:
516+
selected.append(item)
515517
items[:] = selected
516518
config.hook.pytest_deselected(items=deselected)
517519
# Add OUR OWN test metadata to Item
@@ -886,6 +888,38 @@ def set_sync_write(self) -> None:
886888
with connect_server(_vars_['server']) as srv:
887889
srv.database.set_write_mode(database=self.db_path, mode=DbWriteMode.SYNC)
888890

891+
def existing_db_factory(*, filename: str='test.fdb', charset: Optional[str]=None,
892+
user: Optional[str]=None, password: Optional[str]=None,
893+
config_name: str='pytest', utf8filename: bool=False):
894+
"""Factory function that returns :doc:`fixture <pytest:explanation/fixtures>` providing
895+
the `Database` instance to existing database.
896+
897+
Arguments:
898+
filename: Test database filename. It's also possible to specify database alias using
899+
'#' as prefix, for example `#employee` means alias `employee`.
900+
The database with this alias must be defined in `databases.conf`.
901+
charset: Default charset for connections.
902+
user: User name used to connect the test database. Default is taken from server configuration.
903+
password: User password used to connect the test database. Default
904+
is taken from server configuration.
905+
config_name: Name for database configuration.
906+
utf8filename: Use utf8filename DPB flag.
907+
908+
.. note::
909+
910+
The returned instance must be assigned to module-level variable. Name of this variable
911+
is important, as it's used to reference the fixture in other fixture-factory functions
912+
that use the database, and the test function itself.
913+
"""
914+
915+
@pytest.fixture
916+
def existing_database_fixture(request: pytest.FixtureRequest) -> Database:
917+
db = Database(_vars_['databases'], filename, user, password, charset, debug=str(request.module),
918+
config_name=config_name, utf8filename=utf8filename)
919+
yield db
920+
921+
return existing_database_fixture
922+
889923
def db_factory(*, filename: str='test.fdb', init: Optional[str]=None,
890924
from_backup: Optional[str]=None, copy_of: Optional[str]=None,
891925
page_size: Optional[int]=None, sql_dialect: Optional[int]=None,
@@ -1779,7 +1813,7 @@ def execute(self, *, do_not_connect: bool=False, charset: Optional[str]=None,
17791813
else:
17801814
result: CompletedProcess = run(params, input=self.script,
17811815
encoding=io_enc, capture_output=True)
1782-
if result.returncode and not bool(self.expected_stderr) and not combine_output:
1816+
if (result.returncode or result.stderr) and not bool(self.expected_stderr) and not combine_output:
17831817
self._node.add_report_section('call', 'ISQL stdout', result.stdout)
17841818
self._node.add_report_section('call', 'ISQL stderr', result.stderr)
17851819
raise ExecutionError("Test script execution failed")
@@ -1893,7 +1927,7 @@ def gstat(self, *, switches: List[str], charset: Optional[str]=None,
18931927
if connect_db:
18941928
params.append(str(self.db.dsn))
18951929
result: CompletedProcess = run(params, encoding=io_enc, capture_output=True)
1896-
if result.returncode and not bool(self.expected_stderr):
1930+
if (result.returncode or result.stderr) and not bool(self.expected_stderr):
18971931
self._node.add_report_section('call', 'gstat stdout', result.stdout)
18981932
self._node.add_report_section('call', 'gstat stderr', result.stderr)
18991933
raise ExecutionError("gstat execution failed")
@@ -1957,7 +1991,7 @@ def gsec(self, *, switches: Optional[List[str]]=None, charset: Optional[str]=Non
19571991
params.extend(['-user', self.db.user, '-password', self.db.password])
19581992
result: CompletedProcess = run(params, input=input,
19591993
encoding=io_enc, capture_output=True)
1960-
if result.returncode and not bool(self.expected_stderr):
1994+
if (result.returncode or result.stderr) and not bool(self.expected_stderr):
19611995
self._node.add_report_section('call', 'gsec stdout', result.stdout)
19621996
self._node.add_report_section('call', 'gsec stderr', result.stderr)
19631997
raise ExecutionError("gsec execution failed")
@@ -2021,7 +2055,7 @@ def gbak(self, *, switches: Optional[List[str]]=None, charset: Optional[str]=Non
20212055
result: CompletedProcess = run(params, encoding=io_enc, stdout=PIPE, stderr=STDOUT)
20222056
else:
20232057
result: CompletedProcess = run(params, encoding=io_enc, capture_output=True)
2024-
if result.returncode and not (bool(self.expected_stderr) or combine_output):
2058+
if (result.returncode or result.stderr) and not (bool(self.expected_stderr) or combine_output):
20252059
self._node.add_report_section('call', 'gbak stdout', result.stdout)
20262060
self._node.add_report_section('call', 'gbak stderr', result.stderr)
20272061
raise ExecutionError("gbak execution failed")
@@ -2084,7 +2118,7 @@ def nbackup(self, *, switches: List[str], charset: Optional[str]=None,
20842118
result: CompletedProcess = run(params, encoding=io_enc, stdout=PIPE, stderr=STDOUT)
20852119
else:
20862120
result: CompletedProcess = run(params, encoding=io_enc, capture_output=True)
2087-
if result.returncode and not (bool(self.expected_stderr) or combine_output):
2121+
if (result.returncode or result.stderr) and not (bool(self.expected_stderr) or combine_output):
20882122
self._node.add_report_section('call', 'nbackup stdout', result.stdout)
20892123
self._node.add_report_section('call', 'nbackup stderr', result.stderr)
20902124
raise ExecutionError("nbackup execution failed")
@@ -2148,7 +2182,7 @@ def gfix(self, *, switches: Optional[List[str]]=None, charset: Optional[str]=Non
21482182
result: CompletedProcess = run(params, encoding=io_enc, stdout=PIPE, stderr=STDOUT)
21492183
else:
21502184
result: CompletedProcess = run(params, encoding=io_enc, capture_output=True)
2151-
if result.returncode and not (bool(self.expected_stderr) or combine_output):
2185+
if (result.returncode or result.stderr) and not (bool(self.expected_stderr) or combine_output):
21522186
self._node.add_report_section('call', 'gfix stdout', result.stdout)
21532187
self._node.add_report_section('call', 'gfix stderr', result.stderr)
21542188
raise ExecutionError("gfix execution failed")
@@ -2226,7 +2260,7 @@ def isql(self, *, switches: Optional[List[str]]=None, charset: Optional[str]=Non
22262260
else:
22272261
result: CompletedProcess = run(params, input=input,
22282262
encoding=io_enc, capture_output=True)
2229-
if result.returncode and not (bool(self.expected_stderr) or combine_output):
2263+
if (result.returncode or result.stderr) and not (bool(self.expected_stderr) or combine_output):
22302264
self._node.add_report_section('call', 'ISQL stdout', result.stdout)
22312265
self._node.add_report_section('call', 'ISQL stderr', result.stderr)
22322266
raise ExecutionError("ISQL execution failed")
@@ -2289,7 +2323,7 @@ def svcmgr(self, *, switches: Optional[List[str]]=None, charset: Optional[str]=N
22892323
if switches is not None:
22902324
params.extend(switches)
22912325
result: CompletedProcess = run(params, encoding=io_enc, capture_output=True)
2292-
if result.returncode and not bool(self.expected_stderr):
2326+
if (result.returncode or result.stderr) and not bool(self.expected_stderr):
22932327
self._node.add_report_section('call', 'fbsvcmgr stdout', result.stdout)
22942328
self._node.add_report_section('call', 'fbsvcmgr stderr', result.stderr)
22952329
raise ExecutionError("fbsvcmgr execution failed")

0 commit comments

Comments
 (0)