Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[conftest] Advanced processing of logging#230

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Changes from1 commit
Commits
Show all changes
11 commits
Select commitHold shift + click to select a range
aecdcfb
[conftest] Advanced processing of logging
dmitry-lipetskMar 31, 2025
9bc0ba2
Merge branch 'master' into D20250331_003--logging
dmitry-lipetskApr 1, 2025
88bb6ae
[conftest] XFail does not respect SIGNAL_EXCEPTION
dmitry-lipetskApr 1, 2025
24b20c8
[summary] An error count of each test is printed
dmitry-lipetskApr 1, 2025
4c595cc
conftest is updated [debug checks]
dmitry-lipetskApr 1, 2025
4e100ca
conftest is updated [formatting]
dmitry-lipetskApr 1, 2025
202e526
False XFail message has 'info' status [not warning]
dmitry-lipetskApr 1, 2025
b8e383d
[summary] List of tests with warnings is printed.
dmitry-lipetskApr 1, 2025
f56fc94
TEST_PROCESS_STATS::incrementFailedTestCount is updated [debug check]
dmitry-lipetskApr 1, 2025
98d032f
[summary] total errors/warnings/duration are printed
dmitry-lipetskApr 1, 2025
282213f
test_conftest.py--devel is added
dmitry-lipetskApr 1, 2025
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
NextNext commit
[conftest] Advanced processing of logging
This patch does the following things: - it processes the calls of logging.error as test errors - it prints the number of errors/warnings for each test
  • Loading branch information
@dmitry-lipetsk
dmitry-lipetsk committedMar 31, 2025
commitaecdcfb11de8d82bf7cb5bb5d0b327bfa058da5b
212 changes: 209 additions & 3 deletionstests/conftest.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,6 +8,7 @@
import pathlib
import math
import datetime
import typing

import _pytest.outcomes
import _pytest.unittest
Expand DownExpand Up@@ -212,6 +213,12 @@ def helper__build_test_id(item: pytest.Function) -> str:

return testID


# /////////////////////////////////////////////////////////////////////////////

g_error_msg_count_key = pytest.StashKey[int]()
g_warning_msg_count_key = pytest.StashKey[int]()

# /////////////////////////////////////////////////////////////////////////////


Expand DownExpand Up@@ -285,6 +292,16 @@ def helper__makereport__call(
assert type(call) == pytest.CallInfo # noqa: E721
assert type(outcome) == pluggy.Result # noqa: E721

# --------
item_error_msg_count = item.stash.get(g_error_msg_count_key, 0)
assert type(item_error_msg_count) == int # noqa: E721
assert item_error_msg_count >= 0

item_warning_msg_count = item.stash.get(g_warning_msg_count_key, 0)
assert type(item_warning_msg_count) == int # noqa: E721
assert item_warning_msg_count >= 0

# --------
rep = outcome.get_result()
assert rep is not None
assert type(rep) == pytest.TestReport # noqa: E721
Expand DownExpand Up@@ -336,6 +353,7 @@ def helper__makereport__call(
reasonMsgTempl = "XFAIL REASON: {0}"

logging.error(call.excinfo.value)
item_error_msg_count += 1

assert type(reasonText) == str # noqa: E721

Expand All@@ -350,7 +368,13 @@ def helper__makereport__call(

TEST_PROCESS_STATS.incrementFailedTestCount(testID)

logging.error(call.excinfo.value)
if type(call.excinfo.value) == SIGNAL_EXCEPTION: # noqa: E721
assert item_error_msg_count > 0
pass
else:
logging.error(call.excinfo.value)
item_error_msg_count += 1

exitStatus = "FAILED"
elif rep.outcome == "passed":
assert call.excinfo is None
Expand DownExpand Up@@ -380,9 +404,11 @@ def helper__makereport__call(

# --------
logging.info("*")
logging.info("* DURATION : {0}".format(timedelta_to_human_text(testDurration)))
logging.info("* DURATION: {0}".format(timedelta_to_human_text(testDurration)))
logging.info("*")
logging.info("* EXIT STATUS : {0}".format(exitStatus))
logging.info("* EXIT STATUS : {0}".format(exitStatus))
logging.info("* ERROR COUNT : {0}".format(item_error_msg_count))
logging.info("* WARNING COUNT: {0}".format(item_warning_msg_count))
logging.info("*")
logging.info("* STOP TEST {0}".format(testID))
logging.info("*")
Expand DownExpand Up@@ -437,6 +463,186 @@ def pytest_runtest_makereport(item: pytest.Function, call: pytest.CallInfo):
# /////////////////////////////////////////////////////////////////////////////


class LogErrorWrapper2:
_old_method: any
_counter: typing.Optional[int]

# --------------------------------------------------------------------
def __init__(self):
self._old_method = None
self._counter = None

# --------------------------------------------------------------------
def __enter__(self):
assert self._old_method is None
assert self._counter is None

self._old_method = logging.error
self._counter = 0

logging.error = self
return self

# --------------------------------------------------------------------
def __exit__(self, exc_type, exc_val, exc_tb):
assert self._old_method is not None
assert self._counter is not None

assert logging.error is self

logging.error = self._old_method

self._old_method = None
self._counter = None
return False

# --------------------------------------------------------------------
def __call__(self, *args, **kwargs):
assert self._old_method is not None
assert self._counter is not None

assert type(self._counter) == int # noqa: E721
assert self._counter >= 0

r = self._old_method(*args, **kwargs)

self._counter += 1
assert self._counter > 0

return r


# /////////////////////////////////////////////////////////////////////////////


class LogWarningWrapper2:
_old_method: any
_counter: typing.Optional[int]

# --------------------------------------------------------------------
def __init__(self):
self._old_method = None
self._counter = None

# --------------------------------------------------------------------
def __enter__(self):
assert self._old_method is None
assert self._counter is None

self._old_method = logging.warning
self._counter = 0

logging.warning = self
return self

# --------------------------------------------------------------------
def __exit__(self, exc_type, exc_val, exc_tb):
assert self._old_method is not None
assert self._counter is not None

assert logging.warning is self

logging.warning = self._old_method

self._old_method = None
self._counter = None
return False

# --------------------------------------------------------------------
def __call__(self, *args, **kwargs):
assert self._old_method is not None
assert self._counter is not None

assert type(self._counter) == int # noqa: E721
assert self._counter >= 0

r = self._old_method(*args, **kwargs)

self._counter += 1
assert self._counter > 0

return r


# /////////////////////////////////////////////////////////////////////////////


class SIGNAL_EXCEPTION(Exception):
def __init__(self):
pass


# /////////////////////////////////////////////////////////////////////////////


@pytest.hookimpl(hookwrapper=True)
def pytest_pyfunc_call(pyfuncitem: pytest.Function):
assert pyfuncitem is not None
assert isinstance(pyfuncitem, pytest.Function)

debug__log_error_method = logging.error
assert debug__log_error_method is not None

debug__log_warning_method = logging.warning
assert debug__log_warning_method is not None

pyfuncitem.stash[g_error_msg_count_key] = 0
pyfuncitem.stash[g_warning_msg_count_key] = 0

try:
with LogErrorWrapper2() as logErrorWrapper, LogWarningWrapper2() as logWarningWrapper:
assert type(logErrorWrapper) == LogErrorWrapper2 # noqa: E721
assert logErrorWrapper._old_method is not None
assert type(logErrorWrapper._counter) == int # noqa: E721
assert logErrorWrapper._counter == 0
assert logging.error is logErrorWrapper

assert type(logWarningWrapper) == LogWarningWrapper2 # noqa: E721
assert logWarningWrapper._old_method is not None
assert type(logWarningWrapper._counter) == int # noqa: E721
assert logWarningWrapper._counter == 0
assert logging.warning is logWarningWrapper

r: pluggy.Result = yield

assert r is not None
assert type(r) == pluggy.Result # noqa: E721

assert logErrorWrapper._old_method is not None
assert type(logErrorWrapper._counter) == int # noqa: E721
assert logErrorWrapper._counter >= 0
assert logging.error is logErrorWrapper

assert logWarningWrapper._old_method is not None
assert type(logWarningWrapper._counter) == int # noqa: E721
assert logWarningWrapper._counter >= 0
assert logging.warning is logWarningWrapper

assert g_error_msg_count_key in pyfuncitem.stash
assert g_warning_msg_count_key in pyfuncitem.stash

assert pyfuncitem.stash[g_error_msg_count_key] == 0
assert pyfuncitem.stash[g_warning_msg_count_key] == 0

pyfuncitem.stash[g_error_msg_count_key] = logErrorWrapper._counter
pyfuncitem.stash[g_warning_msg_count_key] = logWarningWrapper._counter

if r.exception is not None:
pass
elif logErrorWrapper._counter == 0:
pass
else:
assert logErrorWrapper._counter > 0
r.force_exception(SIGNAL_EXCEPTION())
finally:
assert logging.error is debug__log_error_method
assert logging.warning is debug__log_warning_method
pass


# /////////////////////////////////////////////////////////////////////////////


def helper__calc_W(n: int) -> int:
assert n > 0

Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp