diff --git a/src/fake_lib/__init__.py b/src/_testing/fake_lib/__init__.py similarity index 100% rename from src/fake_lib/__init__.py rename to src/_testing/fake_lib/__init__.py diff --git a/src/fake_lib/with_errors.py b/src/_testing/fake_lib/with_errors.py similarity index 100% rename from src/fake_lib/with_errors.py rename to src/_testing/fake_lib/with_errors.py diff --git a/src/fake_lib/with_warnings.py b/src/_testing/fake_lib/with_warnings.py similarity index 100% rename from src/fake_lib/with_warnings.py rename to src/_testing/fake_lib/with_warnings.py diff --git a/src/_testing/http_server.py b/src/_testing/http_server.py new file mode 100644 index 0000000..4036291 --- /dev/null +++ b/src/_testing/http_server.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +import json +import threading +from dataclasses import dataclass, field +from typing import Any + +import flask +from werkzeug.serving import make_server + + +class SpyRequest: + def __init__(self, request: flask.Request) -> None: + self._method = request.method + self._path = request.path + self._query = request.query_string.decode() + self._bytes = request.get_data() + + def method(self) -> str: + return self._method + + def path(self) -> str: + return self._path + + def query_string(self) -> str: + return self._query + + def json(self) -> dict[str, Any]: + return json.loads(self._bytes.decode()) + + def text(self) -> str: + return self._bytes.decode() + + +@dataclass +class Spy: + received: list[SpyRequest] = field(default_factory=list) + + def count_received(self) -> int: + return len(self.received) + + def expect_request(self) -> SpyRequest: + if self.count_received() > 1: + raise AssertionError("Expected only one request") + if self.count_received() == 0: + raise AssertionError("Expected one request") + return self.received[0] + + +class EmbeddedTestServer: + def __init__( + self, + spy: Spy, + path: str = "/webhooks/TestWebhook", + host: str = "127.0.0.1", + port: int = 8000, + ) -> None: + self.spy = spy + self.thread = self.ServerThread(self.create_app(spy, path), host, port) + + def start(self) -> None: + self.thread.start() + + def stop(self) -> None: + self.thread.shutdown() + + def __enter__(self) -> "EmbeddedTestServer": + self.start() + return self + + def __exit__(self, *args: object, **kwargs: object) -> None: + self.stop() + + def create_app(self, spy: Spy, path: str): + app = flask.Flask("test-app") + + @app.route(path, methods=["POST"]) + def _() -> dict[str, str]: + spy.received.append(SpyRequest(request=flask.request)) + return {"status": "OK"} + + return app + + class ServerThread(threading.Thread): + def __init__(self, app: flask.Flask, host: str, port: int): + threading.Thread.__init__(self) + self.server = make_server(host, port, app) + self.ctx = app.app_context() + self.ctx.push() + + def run(self): + self.server.serve_forever() + + def shutdown(self): + self.server.shutdown() diff --git a/tests/collect/_utils.py b/src/_testing/setup.py similarity index 55% rename from tests/collect/_utils.py rename to src/_testing/setup.py index fe230d7..64f9105 100644 --- a/tests/collect/_utils.py +++ b/src/_testing/setup.py @@ -35,37 +35,53 @@ def make_testfile(self, filename: str, content: str) -> Path: else: raise ValueError("Filename must end with '.py'") kwargs = {filename: content} - return self.test_dir.makepyfile(**kwargs) + return self.test_dir.makepyfile(**kwargs) # pyright: ignore[reportUnknownMemberType] - def filter_traceback( - self, data: dict[str, Any] | list[Any] - ) -> dict[str, Any] | list[Any]: - return self._filter_traceback(deepcopy(data)) + def sanitize(self, data: dict[str, Any] | list[Any]) -> dict[str, Any] | list[Any]: + return self._sanitize(deepcopy(data)) - def _filter_traceback( + def _sanitize( self, data: Any, ) -> Any: if isinstance(data, dict): - for key, value in data.items(): + for key, value in data.items(): # pyright: ignore[reportUnknownVariableType] if key == "traceback": data[key] = { **data[key], "entries": [ line - for line in value["entries"] + for line in value["entries"] # pyright: ignore[reportUnknownVariableType] if ( "importlib" not in line["path"] and "pytest_asyncio" not in line["path"] ) ], } + elif key == "duration": + data[key] = "omitted" + elif key == "total_duration": + data[key] = "omitted" + elif key == "start_timestamp": + data[key] = "omitted" + elif key == "stop_timestamp": + data[key] = "omitted" + elif key == "timestamp": + data[key] = "omitted" + elif key == "platform": + data[key] = "omitted" + elif key == "processor": + data[key] = "omitted" + elif key == "session_id": + data[key] = "omitted" + elif key == "packages": + data[key] = {} elif isinstance(value, dict): - data[key] = self._filter_traceback(value) + data[key] = self._sanitize(value) elif isinstance(value, list): - data[key] = self._filter_traceback(value) + data[key] = self._sanitize(value) elif isinstance(data, list): - data = [self._filter_traceback(item) for item in data] + data = [self._sanitize(item) for item in data] # pyright: ignore[reportUnknownVariableType] else: return data - return data + return data # pyright: ignore[reportUnknownVariableType] diff --git a/src/pytest_broadcaster/_internal/_fields.py b/src/pytest_broadcaster/_internal/_fields.py index 67afeb2..d45af6c 100644 --- a/src/pytest_broadcaster/_internal/_fields.py +++ b/src/pytest_broadcaster/_internal/_fields.py @@ -1,11 +1,23 @@ from __future__ import annotations import datetime +import importlib.metadata +import platform +import sys +from uuid import uuid4 from warnings import WarningMessage import pytest from _pytest._code.code import ReprTraceback +from pytest_broadcaster.models.python_distribution import ( + Package, + Platform, + PythonDistribution, + Releaselevel, + Version, +) + from ._utils import ( NodeID, TracebackLine, @@ -19,6 +31,10 @@ ) +def make_session_id() -> str: + return str(uuid4()) + + def make_node_id( item: pytest.Item | pytest.Directory | pytest.Module | pytest.Class, ) -> NodeID: @@ -59,6 +75,45 @@ def field_parameters(item: pytest.Item) -> dict[str, str]: return {k: type(v).__name__ for k, v in sorted(get_test_args(item).items())} +def field_python() -> PythonDistribution: + packages = [ + Package(name=x.metadata.get("Name"), version=x.version) + for x in importlib.metadata.distributions() + ] + platform_os = platform.system() + if platform_os == "Linux": + platform_os = Platform.linux + elif platform_os == "Darwin": + platform_os = Platform.darwin + elif platform_os == "Windows": + platform_os = Platform.windows + elif platform_os == "Java": + platform_os = Platform.java + else: + platform_os = Platform.unknown + processor_architecture = platform.processor() + level = sys.version_info.releaselevel + if level == "final": + level = Releaselevel.final + elif level == "beta": + level = Releaselevel.beta + elif level == "alpha": + level = Releaselevel.alpha + else: + level = Releaselevel.candidate + return PythonDistribution( + version=Version( + major=sys.version_info.major, + minor=sys.version_info.minor, + micro=sys.version_info.micro, + releaselevel=level, + ), + packages=packages, + platform=platform_os, + processor=processor_architecture, + ) + + def make_warning_message(warning: WarningMessage) -> str: if isinstance(warning.message, str): return warning.message @@ -69,6 +124,10 @@ def make_timestamp(epoch: float) -> str: return datetime.datetime.fromtimestamp(epoch).isoformat() +def make_timestamp_from_datetime(dt: datetime.datetime) -> str: + return dt.astimezone(datetime.timezone.utc).isoformat() + + def make_traceback(report: pytest.TestReport) -> list[TracebackLine]: return make_traceback_from_reprtraceback(report.longrepr.reprtraceback) # type: ignore diff --git a/src/pytest_broadcaster/_internal/_reporter.py b/src/pytest_broadcaster/_internal/_reporter.py index 77342d8..5dcce11 100644 --- a/src/pytest_broadcaster/_internal/_reporter.py +++ b/src/pytest_broadcaster/_internal/_reporter.py @@ -1,8 +1,9 @@ from __future__ import annotations +import datetime import warnings from pathlib import Path -from typing import TYPE_CHECKING, Any, Literal +from typing import TYPE_CHECKING, Any, Callable, Literal import pytest @@ -31,10 +32,22 @@ class DefaultReporter(Reporter): - def __init__(self) -> None: + def __init__( + self, + session_id: str | None = None, + clock: Callable[[], datetime.datetime] | None = None, + ) -> None: + self._clock = clock or (lambda: datetime.datetime.now(tz=datetime.timezone.utc)) + self._session_id = session_id or api.make_session_id() + self._python = api.field_python() self._roots: dict[str, str] = {} self._pending_report: TestCaseReport | None = None + self._start_timestamp = api.make_timestamp_from_datetime(self._clock()) self._result = SessionResult( + session_id=self._session_id, + start_timestamp=self._start_timestamp, + stop_timestamp=self._start_timestamp, # will be replaced later + python=self._python, pytest_version=pytest.__version__, plugin_version=__version__, exit_status=0, @@ -66,13 +79,23 @@ def make_session_result(self) -> SessionResult | None: def make_session_start(self) -> SessionStart: return SessionStart( - pytest_version=pytest.__version__, plugin_version=__version__ + session_id=self._session_id, + timestamp=self._start_timestamp, + python=self._python, + pytest_version=pytest.__version__, + plugin_version=__version__, ) def make_session_finish(self, exit_status: int) -> SessionFinish: + stop_timestamp = api.make_timestamp_from_datetime(self._clock()) + self._result.stop_timestamp = stop_timestamp self._result.exit_status = exit_status self._done = True - return SessionFinish(exit_status=exit_status) + return SessionFinish( + session_id=self._session_id, + timestamp=stop_timestamp, + exit_status=exit_status, + ) def make_warning_message( self, @@ -179,8 +202,10 @@ def make_collect_report(self, report: pytest.CollectReport) -> CollectReport: items.append(item) # Generate a collect report event. collect_report = CollectReport( - items=items, + session_id=self._session_id, + timestamp=api.make_timestamp_from_datetime(self._clock()), node_id=report.nodeid or "", + items=items, ) self._result.collect_reports.append(collect_report) return collect_report @@ -206,12 +231,13 @@ def make_test_case_step( step: TestCaseSetup | TestCaseCall | TestCaseTeardown if report.when == "setup": step = TestCaseSetup( + session_id=self._session_id, node_id=report.nodeid, - outcome=outcome, + start_timestamp=api.make_timestamp(report.start), + stop_timestamp=api.make_timestamp(report.stop), duration=report.duration, + outcome=outcome, error=error, - start=api.make_timestamp(report.start), - stop=api.make_timestamp(report.stop), ) self._pending_report = TestCaseReport( node_id=report.nodeid, @@ -225,12 +251,13 @@ def make_test_case_step( if outcome == Outcome.skipped and hasattr(report, "wasxfail"): outcome = Outcome.xfailed step = TestCaseCall( + session_id=self._session_id, node_id=report.nodeid, - outcome=outcome, + start_timestamp=api.make_timestamp(report.start), + stop_timestamp=api.make_timestamp(report.stop), duration=report.duration, + outcome=outcome, error=error, - start=api.make_timestamp(report.start), - stop=api.make_timestamp(report.stop), ) assert ( self._pending_report @@ -239,12 +266,13 @@ def make_test_case_step( elif report.when == "teardown": step = TestCaseTeardown( + session_id=self._session_id, node_id=report.nodeid, outcome=outcome, duration=report.duration, error=error, - start=api.make_timestamp(report.start), - stop=api.make_timestamp(report.stop), + start_timestamp=api.make_timestamp(report.start), + stop_timestamp=api.make_timestamp(report.stop), ) assert ( self._pending_report @@ -288,17 +316,18 @@ def make_test_case_finished(self, node_id: str) -> TestCaseFinished: duration = sum(report.duration for report in reports) # Create the finished event finished = TestCaseFinished( + session_id=self._session_id, node_id=node_id, + start_timestamp=pending_report.setup.start_timestamp, + stop_timestamp=pending_report.teardown.stop_timestamp, + total_duration=duration, outcome=outcome, - duration=duration, - start=pending_report.setup.start, - stop=pending_report.teardown.stop, ) # Create the report report = TestCaseReport( node_id=node_id, outcome=finished.outcome, - duration=finished.duration, + duration=finished.total_duration, finished=finished, setup=pending_report.setup, call=pending_report.call, @@ -310,4 +339,4 @@ def make_test_case_finished(self, node_id: str) -> TestCaseFinished: if TYPE_CHECKING: # Make sure that the class implements the interface - DefaultReporter() + DefaultReporter("fake-id", datetime.datetime.now) diff --git a/src/pytest_broadcaster/models/collect_report.py b/src/pytest_broadcaster/models/collect_report.py index 4ef8ef6..fcf60bc 100644 --- a/src/pytest_broadcaster/models/collect_report.py +++ b/src/pytest_broadcaster/models/collect_report.py @@ -15,10 +15,18 @@ class CollectReport: A report of collected items. """ + session_id: str + """ + The unique if of this test session used to aggregate events together. + """ node_id: str """ The node id of the node for which items were collected (the top level root directory has an empty node id). """ + timestamp: str + """ + The date and time when the report was generated in ISO 8601 format. + """ items: List[ Union[ test_directory.TestDirectory, diff --git a/src/pytest_broadcaster/models/python_distribution.py b/src/pytest_broadcaster/models/python_distribution.py new file mode 100644 index 0000000..e5989ce --- /dev/null +++ b/src/pytest_broadcaster/models/python_distribution.py @@ -0,0 +1,91 @@ +# generated by datamodel-codegen: +# filename: python_distribution.json + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum +from typing import List, Optional + + +class Releaselevel(Enum): + """ + The release level of the python interpreter. + """ + + alpha = "alpha" + beta = "beta" + candidate = "candidate" + final = "final" + + +@dataclass +class Version: + """ + The version of the python interpreter being used to run the tests. + """ + + major: int + """ + The major version of the python interpreter. + """ + minor: int + """ + The minor version of the python interpreter. + """ + micro: int + """ + The micro version of the python interpreter. + """ + releaselevel: Releaselevel + """ + The release level of the python interpreter. + """ + + +class Platform(Enum): + """ + The platform of the python interpreter. + """ + + linux = "linux" + darwin = "darwin" + java = "java" + windows = "windows" + unknown = "unknown" + + +@dataclass +class Package: + name: Optional[str] = None + """ + The name of the package. + """ + version: Optional[str] = None + """ + The version of the package. + """ + + +@dataclass +class PythonDistribution: + """ + Metadata about the python interpreter being used to run the tests. + """ + + version: Version + """ + The version of the python interpreter being used to run the tests. + """ + processor: str + """ + The processor architecture of the python interpreter. + """ + platform: Platform + """ + The platform of the python interpreter. + """ + packages: List[Package] + """ + The packages installed in the python interpreter. + """ diff --git a/src/pytest_broadcaster/models/session_finish.py b/src/pytest_broadcaster/models/session_finish.py index d0a9b50..81a74d1 100644 --- a/src/pytest_broadcaster/models/session_finish.py +++ b/src/pytest_broadcaster/models/session_finish.py @@ -12,6 +12,14 @@ class SessionFinish: Event emitted when the session is finished. """ + session_id: str + """ + The unique if of this test session used to aggregate events together. + """ + timestamp: str + """ + The time when the session finished in ISO 8601 format. + """ exit_status: int """ The status which pytest will return to the system. 0 means success, 1 means test failure, anything else is an error. diff --git a/src/pytest_broadcaster/models/session_result.py b/src/pytest_broadcaster/models/session_result.py index 757b8ba..dd0600d 100644 --- a/src/pytest_broadcaster/models/session_result.py +++ b/src/pytest_broadcaster/models/session_result.py @@ -6,7 +6,13 @@ from dataclasses import dataclass from typing import List -from . import collect_report, error_message, test_case_report, warning_message +from . import ( + collect_report, + error_message, + python_distribution, + test_case_report, + warning_message, +) @dataclass @@ -15,6 +21,22 @@ class SessionResult: Result of a pytest session, including collect reports and test reports. """ + session_id: str + """ + The unique if of this test session. + """ + start_timestamp: str + """ + The start time of the pytest session in ISO 8601 format. + """ + stop_timestamp: str + """ + The stop time of the pytest session in ISO 8601 format. + """ + python: python_distribution.PythonDistribution + """ + The Python distribution that ran the tests. + """ pytest_version: str """ The version of pytest that generated the report. diff --git a/src/pytest_broadcaster/models/session_start.py b/src/pytest_broadcaster/models/session_start.py index 14f49ed..79dc7e3 100644 --- a/src/pytest_broadcaster/models/session_start.py +++ b/src/pytest_broadcaster/models/session_start.py @@ -5,6 +5,8 @@ from dataclasses import dataclass +from . import python_distribution + @dataclass class SessionStart: @@ -12,6 +14,18 @@ class SessionStart: Event emitted when the test session is started. """ + session_id: str + """ + The unique if of this test session used to aggregate events together. + """ + timestamp: str + """ + The date and time when the test session was started in ISO 8601 format. + """ + python: python_distribution.PythonDistribution + """ + The Python distribution that is running the tests. + """ pytest_version: str """ The version of pytest that is running the tests. diff --git a/src/pytest_broadcaster/models/test_case_call.py b/src/pytest_broadcaster/models/test_case_call.py index 4bfe4d9..88de76b 100644 --- a/src/pytest_broadcaster/models/test_case_call.py +++ b/src/pytest_broadcaster/models/test_case_call.py @@ -19,23 +19,27 @@ class TestCaseCall: """ The node ID of the test case. """ - outcome: outcome.Outcome + session_id: str """ - Outcome of the call step. + The unique if of this test session used to aggregate events together. """ - duration: float - """ - Duration of the call step in seconds. - """ - start: str + start_timestamp: str """ Start time of the call step in ISO 8601 format. """ - stop: str + stop_timestamp: str """ Stop time of the call step in ISO 8601 format. """ - event_type: str = "case_call" + duration: float + """ + Duration of the call step in seconds. + """ + outcome: outcome.Outcome + """ + Outcome of the call step. + """ + event: str = "case_call" """ The event type. Always set to 'case_call'. """ diff --git a/src/pytest_broadcaster/models/test_case_finished.py b/src/pytest_broadcaster/models/test_case_finished.py index 8ff12c8..a5c9a42 100644 --- a/src/pytest_broadcaster/models/test_case_finished.py +++ b/src/pytest_broadcaster/models/test_case_finished.py @@ -14,27 +14,31 @@ class TestCaseFinished: Event emitted when a test case is finished (meaning all of setup, call and teardown steps are finished). """ + session_id: str + """ + The unique if of this test session used to aggregate events together. + """ node_id: str """ The node ID of the test case. """ - outcome: outcome.Outcome + start_timestamp: str """ - Outcome of the test case. + Start time of the test case (including setup). """ - duration: float + stop_timestamp: str """ - Duration of the test case in seconds (including setup and teardown). + Stop time of the test case (including teardown). """ - start: str + total_duration: float """ - Start time of the test case (including setup). + Total duration of the test case in seconds (including setup and teardown). """ - stop: str + outcome: outcome.Outcome """ - Stop time of the test case (including teardown). + Outcome of the test case. """ - event_type: str = "case_finished" + event: str = "case_finished" """ The event type. Always set to 'case_finished'. """ diff --git a/src/pytest_broadcaster/models/test_case_setup.py b/src/pytest_broadcaster/models/test_case_setup.py index 00d67a1..bd6c455 100644 --- a/src/pytest_broadcaster/models/test_case_setup.py +++ b/src/pytest_broadcaster/models/test_case_setup.py @@ -15,27 +15,31 @@ class TestCaseSetup: Pytest Test Case Setup """ + session_id: str + """ + The unique if of this test session used to aggregate events together. + """ node_id: str """ The node ID of the test case. """ - outcome: outcome.Outcome + start_timestamp: str """ - Outcome of the setup step. + Start time of the setup step in ISO 8601 format. """ - duration: float + stop_timestamp: str """ - Duration of the setup step in seconds. + Stop time of the setup step in ISO 8601 format. """ - start: str + duration: float """ - Start time of the setup step in ISO 8601 format. + Duration of the setup step in seconds. """ - stop: str + outcome: outcome.Outcome """ - Stop time of the setup step in ISO 8601 format. + Outcome of the setup step. """ - event_type: str = "case_setup" + event: str = "case_setup" """ The event type. Always set to 'case_setup'. """ diff --git a/src/pytest_broadcaster/models/test_case_teardown.py b/src/pytest_broadcaster/models/test_case_teardown.py index 62f0f4f..65c814b 100644 --- a/src/pytest_broadcaster/models/test_case_teardown.py +++ b/src/pytest_broadcaster/models/test_case_teardown.py @@ -15,27 +15,31 @@ class TestCaseTeardown: Pytest Test Case Teardown """ + session_id: str + """ + The unique if of this test session used to aggregate events together. + """ node_id: str """ The node ID of the test case. """ - outcome: outcome.Outcome + start_timestamp: str """ - Outcome of the teardown step. + Start time of the teardown step in ISO 8601 format. """ - duration: float + stop_timestamp: str """ - Duration of the teardown step in seconds. + Stop time of the teardown step in ISO 8601 format. """ - start: str + duration: float """ - Start time of the teardown step in ISO 8601 format. + Duration of the teardown step in seconds. """ - stop: str + outcome: outcome.Outcome """ - Stop time of the teardown step in ISO 8601 format. + Outcome of the teardown step. """ - event_type: str = "case_teardown" + event: str = "case_teardown" """ The event type. Always set to 'case_teardown'. """ diff --git a/src/schemas/collect_report.json b/src/schemas/collect_report.json index da395f5..8f85246 100644 --- a/src/schemas/collect_report.json +++ b/src/schemas/collect_report.json @@ -6,7 +6,9 @@ "type": "object", "required": [ "event", + "session_id", "node_id", + "timestamp", "items" ], "properties": { @@ -14,10 +16,19 @@ "const": "collect_report", "description": "The event type. Always set to 'collect_report'." }, + "session_id": { + "type": "string", + "description": "The unique if of this test session used to aggregate events together." + }, "node_id": { "type": "string", "description": "The node id of the node for which items were collected (the top level root directory has an empty node id)." }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The date and time when the report was generated in ISO 8601 format." + }, "items": { "type": "array", "description": "An array of collected items. Each collected item is a test directory, test module, test suite, or test case. Top level directory is always first element in the array, followed by test cases, then test suites, then test modules, then test directories for each level of nesting.", diff --git a/src/schemas/python_distribution.json b/src/schemas/python_distribution.json new file mode 100644 index 0000000..8d6f177 --- /dev/null +++ b/src/schemas/python_distribution.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "python_distribution.json", + "title": "Python Distribution", + "description": "Metadata about the python interpreter being used to run the tests.", + "required": [ + "version", + "processor", + "packages", + "platform" + ], + "properties": { + "version": { + "type": "object", + "description": "The version of the python interpreter being used to run the tests.", + "required": [ + "major", + "minor", + "micro", + "releaselevel" + ], + "properties": { + "major": { + "type": "integer", + "description": "The major version of the python interpreter." + }, + "minor": { + "type": "integer", + "description": "The minor version of the python interpreter." + }, + "micro": { + "type": "integer", + "description": "The micro version of the python interpreter." + }, + "releaselevel": { + "type": "string", + "description": "The release level of the python interpreter.", + "enum": ["alpha", "beta", "candidate", "final"] + } + } + }, + "processor": { + "type": "string", + "description": "The processor architecture of the python interpreter." + }, + "platform": { + "enum": ["linux", "darwin", "java", "windows", "unknown"], + "description": "The platform of the python interpreter." + }, + "packages": { + "type": "array", + "description": "The packages installed in the python interpreter.", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the package." + }, + "version": { + "type": "string", + "description": "The version of the package." + } + } + } + } + } +} \ No newline at end of file diff --git a/src/schemas/session_finish.json b/src/schemas/session_finish.json index 82592ce..f4b9181 100644 --- a/src/schemas/session_finish.json +++ b/src/schemas/session_finish.json @@ -6,6 +6,8 @@ "type": "object", "required": [ "event", + "session_id", + "timestamp", "exit_status" ], "properties": { @@ -13,6 +15,15 @@ "const": "session_finish", "description": "The event type. Always set to 'session_finish'." }, + "session_id": { + "type": "string", + "description": "The unique if of this test session used to aggregate events together." + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The time when the session finished in ISO 8601 format." + }, "exit_status": { "type": "integer", "description": "The status which pytest will return to the system. 0 means success, 1 means test failure, anything else is an error." diff --git a/src/schemas/session_result.json b/src/schemas/session_result.json index 57644b9..3a10334 100644 --- a/src/schemas/session_result.json +++ b/src/schemas/session_result.json @@ -5,6 +5,10 @@ "description": "Result of a pytest session, including collect reports and test reports.", "type": "object", "required": [ + "session_id", + "start_timestamp", + "stop_timestamp", + "python", "pytest_version", "plugin_version", "exit_status", @@ -14,6 +18,24 @@ "test_reports" ], "properties": { + "session_id": { + "type": "string", + "description": "The unique if of this test session." + }, + "start_timestamp": { + "type": "string", + "format": "date-time", + "description": "The start time of the pytest session in ISO 8601 format." + }, + "stop_timestamp": { + "type": "string", + "format": "date-time", + "description": "The stop time of the pytest session in ISO 8601 format." + }, + "python": { + "$ref": "python_distribution.json", + "description": "The Python distribution that ran the tests." + }, "pytest_version": { "type": "string", "description": "The version of pytest that generated the report." diff --git a/src/schemas/session_start.json b/src/schemas/session_start.json index fb49aa0..7232f4b 100644 --- a/src/schemas/session_start.json +++ b/src/schemas/session_start.json @@ -6,6 +6,9 @@ "type": "object", "required": [ "event", + "session_id", + "timestamp", + "python", "pytest_version", "plugin_version" ], @@ -14,6 +17,19 @@ "const": "session_start", "description": "The event type. Always set to `session_start`." }, + "session_id": { + "type": "string", + "description": "The unique if of this test session used to aggregate events together." + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The date and time when the test session was started in ISO 8601 format." + }, + "python": { + "$ref": "python_distribution.json/#", + "description": "The Python distribution that is running the tests." + }, "pytest_version": { "type": "string", "description": "The version of pytest that is running the tests." diff --git a/src/schemas/test_case_call.json b/src/schemas/test_case_call.json index f9b06eb..5ea4711 100644 --- a/src/schemas/test_case_call.json +++ b/src/schemas/test_case_call.json @@ -5,40 +5,45 @@ "description": "Event emitted when a call step has been executed in a test case.", "type": "object", "required": [ + "event", "node_id", - "event_type", - "outcome", + "session_id", + "start_timestamp", + "stop_timestamp", "duration", - "start", - "stop" + "outcome" ], "properties": { - "node_id": { - "type": "string", - "description": "The node ID of the test case." - }, - "event_type": { + "event": { "const": "case_call", "description": "The event type. Always set to 'case_call'." }, - "outcome": { - "$ref": "outcome.json/#", - "description": "Outcome of the call step." + "node_id": { + "type": "string", + "description": "The node ID of the test case." }, - "duration": { - "type": "number", - "description": "Duration of the call step in seconds." + "session_id": { + "type": "string", + "description": "The unique if of this test session used to aggregate events together." }, - "start": { + "start_timestamp": { "type": "string", "format": "date-time", "description": "Start time of the call step in ISO 8601 format." }, - "stop": { + "stop_timestamp": { "type": "string", "format": "date-time", "description": "Stop time of the call step in ISO 8601 format." }, + "duration": { + "type": "number", + "description": "Duration of the call step in seconds." + }, + "outcome": { + "$ref": "outcome.json/#", + "description": "Outcome of the call step." + }, "error": { "$ref": "test_case_error.json/#", "description": "Error details if the call step failed." diff --git a/src/schemas/test_case_finished.json b/src/schemas/test_case_finished.json index 64c9b8a..98bfb31 100644 --- a/src/schemas/test_case_finished.json +++ b/src/schemas/test_case_finished.json @@ -5,40 +5,44 @@ "description": "Event emitted when a test case is finished (meaning all of setup, call and teardown steps are finished).", "type": "object", "required": [ + "event", + "session_id", "node_id", - "event_type", - "outcome", - "finished", - "duration", - "start", - "stop" + "start_timestamp", + "stop_timestamp", + "total_duration", + "outcome" ], "properties": { - "node_id": { - "type": "string", - "description": "The node ID of the test case." - }, - "event_type": { + "event": { "const": "case_finished", "description": "The event type. Always set to 'case_finished'." }, - "outcome": { - "$ref": "outcome.json/#", - "description": "Outcome of the test case." + "session_id": { + "type": "string", + "description": "The unique if of this test session used to aggregate events together." }, - "duration": { - "type": "number", - "description": "Duration of the test case in seconds (including setup and teardown)." + "node_id": { + "type": "string", + "description": "The node ID of the test case." }, - "start": { + "start_timestamp": { "type": "string", "format": "date-time", "description": "Start time of the test case (including setup)." }, - "stop": { + "stop_timestamp": { "type": "string", "format": "date-time", "description": "Stop time of the test case (including teardown)." + }, + "total_duration": { + "type": "number", + "description": "Total duration of the test case in seconds (including setup and teardown)." + }, + "outcome": { + "$ref": "outcome.json/#", + "description": "Outcome of the test case." } } } \ No newline at end of file diff --git a/src/schemas/test_case_setup.json b/src/schemas/test_case_setup.json index 99d2bc6..8d58cb9 100644 --- a/src/schemas/test_case_setup.json +++ b/src/schemas/test_case_setup.json @@ -5,40 +5,45 @@ "description": "Pytest Test Case Setup", "type": "object", "required": [ + "event", "node_id", - "event_type", - "outcome", + "session_id", + "start_timestamp", + "stop_timestamp", "duration", - "start", - "stop" + "outcome" ], "properties": { - "node_id": { - "type": "string", - "description": "The node ID of the test case." - }, - "event_type": { + "event": { "const": "case_setup", "description": "The event type. Always set to 'case_setup'." }, - "outcome": { - "$ref": "outcome.json/#", - "description": "Outcome of the setup step." + "session_id": { + "type": "string", + "description": "The unique if of this test session used to aggregate events together." }, - "duration": { - "type": "number", - "description": "Duration of the setup step in seconds." + "node_id": { + "type": "string", + "description": "The node ID of the test case." }, - "start": { + "start_timestamp": { "type": "string", "format": "date-time", "description": "Start time of the setup step in ISO 8601 format." }, - "stop": { + "stop_timestamp": { "type": "string", "format": "date-time", "description": "Stop time of the setup step in ISO 8601 format." }, + "duration": { + "type": "number", + "description": "Duration of the setup step in seconds." + }, + "outcome": { + "$ref": "outcome.json/#", + "description": "Outcome of the setup step." + }, "error": { "$ref": "test_case_error.json/#", "description": "Error details if the setup step failed." diff --git a/src/schemas/test_case_teardown.json b/src/schemas/test_case_teardown.json index d4aaa4e..7e7a251 100644 --- a/src/schemas/test_case_teardown.json +++ b/src/schemas/test_case_teardown.json @@ -5,40 +5,45 @@ "description": "Pytest Test Case Teardown", "type": "object", "required": [ + "event", + "session_id", "node_id", - "event_type", - "outcome", + "start_timestamp", + "stop_timestamp", "duration", - "start", - "stop" + "outcome" ], "properties": { - "node_id": { - "type": "string", - "description": "The node ID of the test case." - }, - "event_type": { + "event": { "const": "case_teardown", "description": "The event type. Always set to 'case_teardown'." }, - "outcome": { - "$ref": "outcome.json/#", - "description": "Outcome of the teardown step." + "session_id": { + "type": "string", + "description": "The unique if of this test session used to aggregate events together." }, - "duration": { - "type": "number", - "description": "Duration of the teardown step in seconds." + "node_id": { + "type": "string", + "description": "The node ID of the test case." }, - "start": { + "start_timestamp": { "type": "string", "format": "date-time", "description": "Start time of the teardown step in ISO 8601 format." }, - "stop": { + "stop_timestamp": { "type": "string", "format": "date-time", "description": "Stop time of the teardown step in ISO 8601 format." }, + "duration": { + "type": "number", + "description": "Duration of the teardown step in seconds." + }, + "outcome": { + "$ref": "outcome.json/#", + "description": "Outcome of the teardown step." + }, "error": { "$ref": "test_case_error.json/#", "description": "Error details if the teardown step failed." diff --git a/tests/call/_utils.py b/tests/call/_utils.py deleted file mode 100644 index 6ac3bd8..0000000 --- a/tests/call/_utils.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import annotations - -import json -from copy import deepcopy -from pathlib import Path -from typing import Any - -import pytest - - -class CommonTestSetup: - @pytest.fixture(autouse=True) - def setup( - self, pytester: pytest.Pytester, tmp_path: Path, pytestconfig: pytest.Config - ): - self.tmp_path = tmp_path - self.test_dir = pytester - self.pytestconfig = pytestconfig - self.json_file = self.tmp_path.joinpath("collect.json") - self.json_lines_file = self.tmp_path.joinpath("collect.jsonl") - - def read_json_file(self) -> dict[str, Any]: - return json.loads(self.json_file.read_text()) - - def read_json_lines_file(self) -> list[dict[str, Any]]: - return [ - json.loads(line.strip()) - for line in self.json_lines_file.read_text().splitlines() - if line.strip() - ] - - def make_testfile(self, filename: str, content: str) -> Path: - if filename.endswith(".py"): - filename = filename[:-3] - else: - raise ValueError("Filename must end with '.py'") - kwargs = {filename: content} - return self.test_dir.makepyfile(**kwargs) - - def omit_durations_and_times( - self, data: dict[str, Any] | list[Any] - ) -> dict[str, Any] | list[Any]: - return self._omit_durations_and_times(deepcopy(data)) - - def _omit_durations_and_times( - self, - data: Any, - ) -> Any: - if isinstance(data, dict): - for key, value in data.items(): - if isinstance(value, dict): - data[key] = self._omit_durations_and_times(value) - elif isinstance(value, list): - data[key] = self._omit_durations_and_times(value) - elif key == "duration": - data[key] = "omitted" - elif key == "start": - data[key] = "omitted" - elif key == "stop": - data[key] = "omitted" - elif isinstance(data, list): - data = [self._omit_durations_and_times(item) for item in data] - else: - return data - return data diff --git a/tests/call/test_basic.py b/tests/call/test_basic.py index 05271d7..6977b51 100644 --- a/tests/call/test_basic.py +++ b/tests/call/test_basic.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestBasic(CommonTestSetup): @@ -15,24 +15,22 @@ class TestBasic(CommonTestSetup): def test_omit_duration(self) -> None: data = {} - assert self.omit_durations_and_times(data) == {} + assert self.sanitize(data) == {} data = {"duration": 0.123} - assert self.omit_durations_and_times(data) == {"duration": "omitted"} + assert self.sanitize(data) == {"duration": "omitted"} data = {"test": {"duration": 0.123}} - assert self.omit_durations_and_times(data) == {"test": {"duration": "omitted"}} + assert self.sanitize(data) == {"test": {"duration": "omitted"}} data = {"test": {"duration": 0.123, "nested": {"duration": 0.456}}} - assert self.omit_durations_and_times(data) == { + assert self.sanitize(data) == { "test": {"duration": "omitted", "nested": {"duration": "omitted"}} } data = [{"duration": 0.123}, {"duration": 0.456}] - assert self.omit_durations_and_times(data) == [ + assert self.sanitize(data) == [ {"duration": "omitted"}, {"duration": "omitted"}, ] data = [{"test": {"nested": [{"duration": 0.123}]}}] - assert self.omit_durations_and_times(data) == [ - {"test": {"nested": [{"duration": "omitted"}]}} - ] + assert self.sanitize(data) == [{"test": {"nested": [{"duration": "omitted"}]}}] def make_test_directory(self) -> Path: return self.make_testfile( @@ -54,7 +52,21 @@ def test_json(self): assert result.ret == 0 assert self.json_file.exists() report = self.read_json_file() - assert self.omit_durations_and_times(report) == { + assert self.sanitize(report) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -66,46 +78,52 @@ def test_json(self): "outcome": "passed", "duration": "omitted", "setup": { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "call": { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "teardown": { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "finished": { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", }, } ], "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -117,7 +135,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py::test_ok", @@ -137,7 +157,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py", @@ -169,15 +191,30 @@ def test_jsonl_basic(self): assert result.ret == 0 assert self.json_lines_file.exists() lines = self.read_json_lines_file() - assert self.omit_durations_and_times(lines) == [ + assert self.sanitize(lines) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -189,7 +226,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py::test_ok", @@ -209,7 +248,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py", @@ -224,39 +265,48 @@ def test_jsonl_basic(self): ], }, { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + }, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", }, - {"exit_status": 0, "event": "session_finish"}, ] diff --git a/tests/call/test_basic_failure.py b/tests/call/test_basic_failure.py index de8e49c..1a4dda0 100644 --- a/tests/call/test_basic_failure.py +++ b/tests/call/test_basic_failure.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestBasicFailure(CommonTestSetup): @@ -32,7 +32,21 @@ def test_json(self): result = self.test_dir.runpytest("--collect-report", self.json_file.as_posix()) assert result.ret == 1 assert self.json_file.exists() - assert self.omit_durations_and_times(self.read_json_file()) == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 1, @@ -44,21 +58,23 @@ def test_json(self): "outcome": "failed", "duration": "omitted", "setup": { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "call": { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "failed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": { "message": "def test_failure():\n '''This is a test docstring.'''\n> raise ValueError(\"BOOM\")\nE ValueError: BOOM\n\ntest_basic_failure.py:5: ValueError", "traceback": { @@ -73,28 +89,32 @@ def test_json(self): }, }, "teardown": { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "finished": { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "failed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "total_duration": "omitted", }, } ], "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -106,7 +126,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_failure.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_failure.py::test_failure", @@ -126,7 +148,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_failure.py", @@ -152,15 +176,30 @@ def test_jsonl_basic(self): ) assert result.ret == 1 assert self.json_lines_file.exists() - assert self.omit_durations_and_times(self.read_json_lines_file()) == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "event": "session_start", + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, - "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -172,7 +211,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_failure.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_failure.py::test_failure", @@ -192,7 +233,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_failure.py", @@ -207,21 +250,23 @@ def test_jsonl_basic(self): ], }, { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "failed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": { "message": "def test_failure():\n '''This is a test docstring.'''\n> raise ValueError(\"BOOM\")\nE ValueError: BOOM\n\ntest_basic_failure.py:5: ValueError", "traceback": { @@ -236,21 +281,28 @@ def test_jsonl_basic(self): }, }, { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_failure.py::test_failure", "outcome": "failed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + }, + { + "exit_status": 1, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", }, - {"exit_status": 1, "event": "session_finish"}, ] diff --git a/tests/call/test_basic_skip.py b/tests/call/test_basic_skip.py index 2c96577..0695cbc 100644 --- a/tests/call/test_basic_skip.py +++ b/tests/call/test_basic_skip.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestBasicSkip(CommonTestSetup): @@ -34,7 +34,21 @@ def test_json(self): result = self.test_dir.runpytest("--collect-report", self.json_file.as_posix()) assert result.ret == 0 assert self.json_file.exists() - assert self.omit_durations_and_times(self.read_json_file()) == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -46,38 +60,43 @@ def test_json(self): "outcome": "skipped", "duration": "omitted", "setup": { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "call": None, "teardown": { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "finished": { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", }, } ], "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -89,7 +108,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_skipped.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py::test_skipped", @@ -109,7 +130,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py", @@ -135,15 +158,30 @@ def test_jsonl_basic(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.omit_durations_and_times(self.read_json_lines_file()) == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -155,7 +193,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_skipped.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py::test_skipped", @@ -175,7 +215,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py", @@ -190,30 +232,38 @@ def test_jsonl_basic(self): ], }, { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + }, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", }, - {"exit_status": 0, "event": "session_finish"}, ] diff --git a/tests/call/test_basic_xfail.py b/tests/call/test_basic_xfail.py index e61c81c..6b2e663 100644 --- a/tests/call/test_basic_xfail.py +++ b/tests/call/test_basic_xfail.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestBasicxFail(CommonTestSetup): @@ -44,7 +44,21 @@ def test_json(self): result = self.test_dir.runpytest("--collect-report", self.json_file.as_posix()) assert result.ret == 0 assert self.json_file.exists() - assert self.omit_durations_and_times(self.read_json_file()) == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -56,39 +70,43 @@ def test_json(self): "outcome": "passed", "duration": "omitted", "setup": { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "call": { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "teardown": { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "finished": { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", }, }, { @@ -96,46 +114,52 @@ def test_json(self): "outcome": "xfailed", "duration": "omitted", "setup": { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "call": { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "xfailed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "teardown": { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "finished": { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "xfailed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", }, }, ], "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -147,7 +171,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py::test_ok", @@ -167,7 +193,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_xfail.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_xfail.py::test_xfail", @@ -187,7 +215,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py", @@ -223,15 +253,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.omit_durations_and_times(self.read_json_lines_file()) == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -243,7 +288,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py::test_ok", @@ -263,7 +310,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_xfail.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_xfail.py::test_xfail", @@ -283,7 +332,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py", @@ -308,74 +359,87 @@ def test_jsonl(self): ], }, { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic.py::test_ok", "outcome": "passed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", }, { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "xfailed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_xfail.py::test_xfail", "outcome": "xfailed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + }, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", }, - {"exit_status": 0, "event": "session_finish"}, ] diff --git a/tests/call/test_skip_within_test.py b/tests/call/test_skip_within_test.py index 059469a..4df44c6 100644 --- a/tests/call/test_skip_within_test.py +++ b/tests/call/test_skip_within_test.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestSkipWithinTest(CommonTestSetup): @@ -34,7 +34,21 @@ def test_json(self): result = self.test_dir.runpytest("--collect-report", self.json_file.as_posix()) assert result.ret == 0 assert self.json_file.exists() - assert self.omit_durations_and_times(self.read_json_file()) == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -46,46 +60,52 @@ def test_json(self): "outcome": "skipped", "duration": "omitted", "setup": { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "call": { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "teardown": { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "finished": { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", }, } ], "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -97,7 +117,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_skipped.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py::test_skipped", @@ -117,7 +139,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py", @@ -143,15 +167,30 @@ def test_jsonl_basic(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.omit_durations_and_times(self.read_json_lines_file()) == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -163,7 +202,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_skipped.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py::test_skipped", @@ -183,7 +224,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_skipped.py", @@ -198,39 +241,48 @@ def test_jsonl_basic(self): ], }, { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_basic_skipped.py::test_skipped", "outcome": "skipped", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + }, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", }, - {"exit_status": 0, "event": "session_finish"}, ] diff --git a/tests/call/test_xfail_within_test.py b/tests/call/test_xfail_within_test.py index c4bd2d5..e04292d 100644 --- a/tests/call/test_xfail_within_test.py +++ b/tests/call/test_xfail_within_test.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestxFailWithinTest(CommonTestSetup): @@ -34,7 +34,21 @@ def test_json(self): result = self.test_dir.runpytest("--collect-report", self.json_file.as_posix()) assert result.ret == 0 assert self.json_file.exists() - assert self.omit_durations_and_times(self.read_json_file()) == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -46,46 +60,52 @@ def test_json(self): "outcome": "xfailed", "duration": "omitted", "setup": { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "call": { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "xfailed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "teardown": { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, "finished": { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "xfailed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", }, } ], "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -97,7 +117,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_xfail_within_test.py", + "timestamp": "omitted", "items": [ { "node_id": "test_xfail_within_test.py::test_xfail", @@ -117,7 +139,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_xfail_within_test.py", @@ -143,15 +167,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.omit_durations_and_times(self.read_json_lines_file()) == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "event": "session_start", + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, - "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -163,7 +202,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_xfail_within_test.py", + "timestamp": "omitted", "items": [ { "node_id": "test_xfail_within_test.py::test_xfail", @@ -183,7 +224,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_xfail_within_test.py", @@ -198,39 +241,48 @@ def test_jsonl(self): ], }, { - "event_type": "case_setup", + "event": "case_setup", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_call", + "event": "case_call", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "xfailed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_teardown", + "event": "case_teardown", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "passed", "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", "error": None, }, { - "event_type": "case_finished", + "event": "case_finished", + "session_id": "omitted", "node_id": "test_xfail_within_test.py::test_xfail", "outcome": "xfailed", - "duration": "omitted", - "start": "omitted", - "stop": "omitted", + "total_duration": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + }, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", }, - {"exit_status": 0, "event": "session_finish"}, ] diff --git a/tests/collect/test_basic.py b/tests/collect/test_basic.py index 5706f28..723490e 100644 --- a/tests/collect/test_basic.py +++ b/tests/collect/test_basic.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestBasic(CommonTestSetup): @@ -34,7 +34,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -44,7 +58,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -56,7 +72,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py::test_ok", @@ -76,7 +94,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py", @@ -102,15 +122,30 @@ def test_jsonl_basic(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "event": "session_start", + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, - "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -122,7 +157,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py::test_ok", @@ -142,7 +179,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic.py", @@ -156,5 +195,10 @@ def test_jsonl_basic(self): } ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_basic_marker.py b/tests/collect/test_basic_marker.py index 8bbab5c..47fadbe 100644 --- a/tests/collect/test_basic_marker.py +++ b/tests/collect/test_basic_marker.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic @pytest.mark.markers @@ -35,7 +35,21 @@ def test_json_basic_marker(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -45,7 +59,9 @@ def test_json_basic_marker(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -57,7 +73,9 @@ def test_json_basic_marker(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_marker.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_marker.py::test_ok", @@ -77,7 +95,9 @@ def test_json_basic_marker(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_marker.py", @@ -103,15 +123,30 @@ def test_jsonl_basic_marker(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -123,7 +158,9 @@ def test_jsonl_basic_marker(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_marker.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_marker.py::test_ok", @@ -143,7 +180,9 @@ def test_jsonl_basic_marker(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_marker.py", @@ -157,5 +196,10 @@ def test_jsonl_basic_marker(self): } ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_basic_parametrization.py b/tests/collect/test_basic_parametrization.py index 759f303..4db384c 100644 --- a/tests/collect/test_basic_parametrization.py +++ b/tests/collect/test_basic_parametrization.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic @pytest.mark.parametrization @@ -35,7 +35,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -45,7 +59,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -57,7 +73,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_parametrization.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_parametrization.py::test_ok[1]", @@ -105,7 +123,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_parametrization.py", @@ -131,15 +151,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -150,6 +185,10 @@ def test_jsonl(self): ], }, { + "event": "collect_report", + "session_id": "omitted", + "node_id": "test_basic_parametrization.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_parametrization.py::test_ok[1]", @@ -194,12 +233,12 @@ def test_jsonl(self): "function": "test_ok", }, ], - "event": "collect_report", - "node_id": "test_basic_parametrization.py", }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_parametrization.py", @@ -213,5 +252,10 @@ def test_jsonl(self): } ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_basic_suite.py b/tests/collect/test_basic_suite.py index 7b7bfa4..880a57d 100644 --- a/tests/collect/test_basic_suite.py +++ b/tests/collect/test_basic_suite.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.suites @pytest.mark.basic @@ -39,7 +39,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -49,7 +63,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -61,7 +77,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_suite.py::TestOk", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_suite.py::TestOk::test_1", @@ -95,7 +113,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_suite.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_suite.py::TestOk", @@ -112,7 +132,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_suite.py", @@ -138,15 +160,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -158,7 +195,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_suite.py::TestOk", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_suite.py::TestOk::test_1", @@ -192,7 +231,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_basic_suite.py", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_suite.py::TestOk", @@ -209,7 +250,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_basic_suite.py", @@ -223,5 +266,10 @@ def test_jsonl(self): } ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_errors.py b/tests/collect/test_errors.py index 01b5985..68ae0b0 100644 --- a/tests/collect/test_errors.py +++ b/tests/collect/test_errors.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestErrors(CommonTestSetup): @@ -19,7 +19,7 @@ def test_filter_traceback(self) -> None: "entries": [{"path": "importlib"}, {"path": "something/else"}] } } - assert self.filter_traceback(data) == { + assert self.sanitize(data) == { "traceback": {"entries": [{"path": "something/else"}]} } @@ -46,7 +46,21 @@ def test_json(self): ) assert result.ret == 3 assert self.json_file.exists() - assert self.filter_traceback(self.read_json_file()) == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 3, @@ -83,7 +97,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -105,15 +121,30 @@ def test_jsonl(self): ) assert result.ret == 3 assert self.json_lines_file.exists() - assert self.filter_traceback(self.read_json_lines_file()) == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -149,5 +180,10 @@ def test_jsonl(self): "exception_type": "RuntimeError", "exception_value": "BOOM", }, - {"exit_status": 3, "event": "session_finish"}, + { + "exit_status": 3, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_errors_third_party.py b/tests/collect/test_errors_third_party.py index 0142f61..f6e5f02 100644 --- a/tests/collect/test_errors_third_party.py +++ b/tests/collect/test_errors_third_party.py @@ -1,14 +1,14 @@ from __future__ import annotations +import sys from pathlib import Path import pytest -from fake_lib import filename +from _testing.fake_lib import filename +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestErrorsThirdParty(CommonTestSetup): @@ -21,7 +21,7 @@ def make_basic_test(self) -> Path: "test_errors.py", """ '''This is a module docstring.''' - import fake_lib.with_errors + import _testing.fake_lib.with_errors """, ).parent @@ -34,7 +34,21 @@ def test_json(self): ) assert result.ret == 3 assert self.json_file.exists() - assert self.filter_traceback(self.read_json_file()) == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 3, @@ -65,7 +79,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -87,15 +103,30 @@ def test_jsonl(self): ) assert result.ret == 3 assert self.json_lines_file.exists() - assert self.filter_traceback(self.read_json_lines_file()) == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -125,5 +156,10 @@ def test_jsonl(self): "exception_type": "RuntimeError", "exception_value": "BOOM", }, - {"exit_status": 3, "event": "session_finish"}, + { + "exit_status": 3, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_multi_cases.py b/tests/collect/test_multi_cases.py index 0d13e55..d171a96 100644 --- a/tests/collect/test_multi_cases.py +++ b/tests/collect/test_multi_cases.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestMultiCases(CommonTestSetup): @@ -36,7 +36,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -46,7 +60,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -58,7 +74,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_multi_cases.py", + "timestamp": "omitted", "items": [ { "node_id": "test_multi_cases.py::test_1", @@ -92,7 +110,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_multi_cases.py", @@ -118,15 +138,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -137,6 +172,10 @@ def test_jsonl(self): ], }, { + "event": "collect_report", + "session_id": "omitted", + "node_id": "test_multi_cases.py", + "timestamp": "omitted", "items": [ { "node_id": "test_multi_cases.py::test_1", @@ -167,12 +206,12 @@ def test_jsonl(self): "function": "test_2", }, ], - "event": "collect_report", - "node_id": "test_multi_cases.py", }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_multi_cases.py", @@ -186,5 +225,10 @@ def test_jsonl(self): } ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_multi_files.py b/tests/collect/test_multi_files.py index fe17cfe..b4def91 100644 --- a/tests/collect/test_multi_files.py +++ b/tests/collect/test_multi_files.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic @pytest.mark.filetree @@ -49,7 +49,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -59,7 +73,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -71,7 +87,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::test_1", @@ -105,7 +123,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::test_3", @@ -139,7 +159,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py", @@ -175,15 +197,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -195,7 +232,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::test_1", @@ -229,7 +268,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::test_3", @@ -263,7 +304,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py", @@ -287,5 +330,10 @@ def test_jsonl(self): }, ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_multi_suite.py b/tests/collect/test_multi_suite.py index 100cb39..7db6ae8 100644 --- a/tests/collect/test_multi_suite.py +++ b/tests/collect/test_multi_suite.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.suites @pytest.mark.filetree @@ -67,7 +67,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -77,7 +91,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -89,7 +105,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py::TestSuite1", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::TestSuite1::test_1", @@ -123,7 +141,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py::TestSuite2", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::TestSuite2::test_3", @@ -157,7 +177,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::TestSuite1", @@ -185,7 +207,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py::TestSuite3", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::TestSuite3::test_5", @@ -219,7 +243,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py::TestSuite4", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::TestSuite4::test_7", @@ -253,7 +279,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::TestSuite3", @@ -281,7 +309,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py", @@ -317,15 +347,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -337,7 +382,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py::TestSuite1", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::TestSuite1::test_1", @@ -371,7 +418,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py::TestSuite2", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::TestSuite2::test_3", @@ -405,7 +454,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_1.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py::TestSuite1", @@ -433,7 +484,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py::TestSuite3", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::TestSuite3::test_5", @@ -467,7 +520,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py::TestSuite4", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::TestSuite4::test_7", @@ -501,7 +556,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_module_2.py", + "timestamp": "omitted", "items": [ { "node_id": "test_module_2.py::TestSuite3", @@ -529,7 +586,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_module_1.py", @@ -553,5 +612,10 @@ def test_jsonl(self): }, ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_nested_directories.py b/tests/collect/test_nested_directories.py index 78bfc54..06f01cb 100644 --- a/tests/collect/test_nested_directories.py +++ b/tests/collect/test_nested_directories.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestBasic(CommonTestSetup): @@ -46,7 +46,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -56,7 +70,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -68,7 +84,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_1/test_module_1.py", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_1/test_module_1.py::test_1", @@ -90,7 +108,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_1", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_1/test_module_1.py", @@ -108,7 +128,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_2/test_module_2.py", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_2/test_module_2.py::test_2", @@ -130,7 +152,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_2", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_2/test_module_2.py", @@ -147,7 +171,10 @@ def test_json(self): ], }, { + "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_1", @@ -166,7 +193,6 @@ def test_json(self): "node_type": "directory", }, ], - "event": "collect_report", }, ], } @@ -180,15 +206,30 @@ def test_jsonl_basic(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -200,7 +241,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_1/test_module_1.py", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_1/test_module_1.py::test_1", @@ -220,7 +263,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_1", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_1/test_module_1.py", @@ -236,7 +281,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_2/test_module_2.py", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_2/test_module_2.py::test_2", @@ -256,7 +303,9 @@ def test_jsonl_basic(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "subdirectory_2", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_2/test_module_2.py", @@ -271,7 +320,10 @@ def test_jsonl_basic(self): ], }, { + "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "subdirectory_1", @@ -290,7 +342,11 @@ def test_jsonl_basic(self): "node_type": "directory", }, ], - "event": "collect_report", }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_nested_markers.py b/tests/collect/test_nested_markers.py index 1733906..853fadc 100644 --- a/tests/collect/test_nested_markers.py +++ b/tests/collect/test_nested_markers.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.markers class TestNestedMarker(CommonTestSetup): @@ -36,7 +36,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -46,7 +60,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -58,7 +74,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_markers.py::TestMarked", + "timestamp": "omitted", "items": [ { "node_id": "test_markers.py::TestMarked::test_marked", @@ -78,7 +96,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_markers.py", + "timestamp": "omitted", "items": [ { "node_id": "test_markers.py::TestMarked", @@ -95,7 +115,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_markers.py", @@ -121,15 +143,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -141,7 +178,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_markers.py::TestMarked", + "timestamp": "omitted", "items": [ { "node_id": "test_markers.py::TestMarked::test_marked", @@ -161,7 +200,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_markers.py", + "timestamp": "omitted", "items": [ { "node_id": "test_markers.py::TestMarked", @@ -178,7 +219,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_markers.py", @@ -192,5 +235,10 @@ def test_jsonl(self): } ], }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_warnings.py b/tests/collect/test_warnings.py index ec3822e..a36909b 100644 --- a/tests/collect/test_warnings.py +++ b/tests/collect/test_warnings.py @@ -1,13 +1,13 @@ from __future__ import annotations +import sys from pathlib import Path import pytest +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestWarnings(CommonTestSetup): @@ -39,7 +39,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.tmp_path, self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -75,20 +89,24 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", - "node_id": "test_warnings.py", + "session_id": "omitted", + "node_id": "", + "timestamp": "omitted", "items": [ { - "event": "collect_report", - "node_id": "", - "items": [ - { - "node_id": ".", - "node_type": "directory", - "name": directory.name, - "path": directory.name, - } - ], - }, + "node_id": ".", + "node_type": "directory", + "name": directory.name, + "path": directory.name, + } + ], + }, + { + "event": "collect_report", + "session_id": "omitted", + "node_id": "test_warnings.py", + "timestamp": "omitted", + "items": [ { "node_id": "test_warnings.py::test_warn", "node_type": "case", @@ -107,7 +125,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_warnings.py", @@ -122,6 +142,7 @@ def test_json(self): ], }, ], + "test_reports": [], } def test_jsonl(self): @@ -133,15 +154,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -153,7 +189,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_warnings.py", + "timestamp": "omitted", "items": [ { "node_id": "test_warnings.py::test_warn", @@ -173,7 +211,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_warnings.py", @@ -213,5 +253,10 @@ def test_jsonl(self): "event": "warning_message", "category": "UserWarning", }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/collect/test_warnings_third_party.py b/tests/collect/test_warnings_third_party.py index 7920751..64d24be 100644 --- a/tests/collect/test_warnings_third_party.py +++ b/tests/collect/test_warnings_third_party.py @@ -1,14 +1,14 @@ from __future__ import annotations +import sys from pathlib import Path import pytest -from fake_lib import filename +from _testing.fake_lib import filename +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -from ._utils import CommonTestSetup - @pytest.mark.basic class TestWarningsThirdParty(CommonTestSetup): @@ -20,7 +20,7 @@ def make_basic_test(self) -> Path: return self.make_testfile( "test_warnings.py", """ - import fake_lib.with_warnings + import _testing.fake_lib.with_warnings def test_warn(): '''This is a test docstring.''' @@ -37,7 +37,21 @@ def test_json(self): ) assert result.ret == 0 assert self.json_file.exists() - assert self.tmp_path, self.read_json_file() == { + assert self.sanitize(self.read_json_file()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "exit_status": 0, @@ -69,7 +83,9 @@ def test_json(self): "collect_reports": [ { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -81,7 +97,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_warnings.py", + "timestamp": "omitted", "items": [ { "node_id": "test_warnings.py::test_warn", @@ -101,7 +119,9 @@ def test_json(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_warnings.py", @@ -116,6 +136,7 @@ def test_json(self): ], }, ], + "test_reports": [], } def test_jsonl(self): @@ -127,15 +148,30 @@ def test_jsonl(self): ) assert result.ret == 0 assert self.json_lines_file.exists() - assert self.read_json_lines_file() == [ + assert self.sanitize(self.read_json_lines_file()) == [ { + "session_id": "omitted", + "timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, "pytest_version": pytest.__version__, "plugin_version": __version__, "event": "session_start", }, { "event": "collect_report", + "session_id": "omitted", "node_id": "", + "timestamp": "omitted", "items": [ { "node_id": ".", @@ -147,7 +183,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": "test_warnings.py", + "timestamp": "omitted", "items": [ { "node_id": "test_warnings.py::test_warn", @@ -167,7 +205,9 @@ def test_jsonl(self): }, { "event": "collect_report", + "session_id": "omitted", "node_id": ".", + "timestamp": "omitted", "items": [ { "node_id": "test_warnings.py", @@ -203,5 +243,10 @@ def test_jsonl(self): "event": "warning_message", "category": "UserWarning", }, - {"exit_status": 0, "event": "session_finish"}, + { + "exit_status": 0, + "event": "session_finish", + "session_id": "omitted", + "timestamp": "omitted", + }, ] diff --git a/tests/destination/test_http_webhook.py b/tests/destination/test_http_webhook.py index 2cbaaa5..9f23eab 100644 --- a/tests/destination/test_http_webhook.py +++ b/tests/destination/test_http_webhook.py @@ -1,87 +1,16 @@ from __future__ import annotations -import threading -from dataclasses import dataclass, field +import sys from pathlib import Path -from typing import Any -import flask import pytest -from werkzeug.serving import make_server +from _testing.http_server import EmbeddedTestServer, Spy +from _testing.setup import CommonTestSetup from pytest_broadcaster import __version__ -@dataclass -class SpyRequest: - method: str - path: str - query: str - json: Any - - -@dataclass -class Spy: - received: list[SpyRequest] = field(default_factory=list) - - -class EmbeddedTestServer: - def __init__( - self, - spy: Spy, - path: str = "/webhooks/TestWebhook", - host: str = "127.0.0.1", - port: int = 8000, - ) -> None: - self.spy = spy - self.thread = self.ServerThread(self.create_app(spy, path), host, port) - - def start(self) -> None: - self.thread.start() - - def stop(self) -> None: - self.thread.shutdown() - - def __enter__(self) -> "EmbeddedTestServer": - self.start() - return self - - def __exit__(self, *args: object, **kwargs: object) -> None: - self.stop() - - @staticmethod - def create_app(spy: Spy, path: str): - app = flask.Flask("test-app") - - @app.route(path, methods=["POST"]) - def webhook() -> dict[str, str]: - spy.received.append( - SpyRequest( - method=flask.request.method, - path=flask.request.path, - query=flask.request.query_string.decode(), - json=flask.request.get_json(), - ) - ) - return {"status": "OK"} - - return app - - class ServerThread(threading.Thread): - def __init__(self, app: flask.Flask, host: str, port: int): - threading.Thread.__init__(self) - self.server = make_server(host, port, app) - self.ctx = app.app_context() - self.ctx.push() - - def run(self): - self.server.serve_forever() - - def shutdown(self): - self.server.shutdown() - - -class TestHttpDestination: +class TestHttpDestination(CommonTestSetup): @pytest.fixture(autouse=True) def setup( self, pytester: pytest.Pytester, tmp_path: Path, pytestconfig: pytest.Config @@ -98,14 +27,6 @@ def setup( ) as server: yield server - def make_testfile(self, filename: str, content: str) -> Path: - if filename.endswith(".py"): - filename = filename[:-3] - else: - raise ValueError("Filename must end with '.py'") - kwargs = {filename: content} - return self.test_dir.makepyfile(**kwargs) - def make_test_directory(self) -> Path: self.test_dir.makeconftest(""" from pytest_broadcaster import HTTPWebhook @@ -129,68 +50,85 @@ def test_webhook(self): directory = self.make_test_directory() result = self.test_dir.runpytest("--collect-only") assert result.ret == 0 - assert self.spy.received == [ - SpyRequest( - method="POST", - path="/webhooks/TestWebhook", - query="", - json={ - "pytest_version": pytest.__version__, - "plugin_version": __version__, - "exit_status": 0, - "errors": [], - "warnings": [], - "test_reports": [], - "collect_reports": [ + request = self.spy.expect_request() + assert request.method() == "POST" + assert request.path() == "/webhooks/TestWebhook" + assert request.query_string() == "" + assert self.sanitize(request.json()) == { + "session_id": "omitted", + "start_timestamp": "omitted", + "stop_timestamp": "omitted", + "python": { + "version": { + "major": sys.version_info.major, + "minor": sys.version_info.minor, + "micro": sys.version_info.micro, + "releaselevel": sys.version_info.releaselevel, + }, + "platform": "omitted", + "processor": "omitted", + "packages": {}, + }, + "pytest_version": pytest.__version__, + "plugin_version": __version__, + "exit_status": 0, + "errors": [], + "warnings": [], + "test_reports": [], + "collect_reports": [ + { + "event": "collect_report", + "session_id": "omitted", + "node_id": "", + "timestamp": "omitted", + "items": [ { - "event": "collect_report", - "node_id": "", - "items": [ - { - "node_id": ".", - "node_type": "directory", - "name": directory.name, - "path": directory.name, - } - ], - }, + "node_id": ".", + "node_type": "directory", + "name": directory.name, + "path": directory.name, + } + ], + }, + { + "event": "collect_report", + "session_id": "omitted", + "node_id": "test_basic.py", + "timestamp": "omitted", + "items": [ { - "event": "collect_report", - "node_id": "test_basic.py", - "items": [ - { - "node_id": "test_basic.py::test_ok", - "node_type": "case", - "name": "test_ok", - "doc": "This is a test docstring.", - "markers": [], - "parameters": {}, - "path": directory.joinpath("test_basic.py") - .relative_to(directory.parent) - .as_posix(), - "module": "test_basic", - "suite": None, - "function": "test_ok", - } - ], - }, + "node_id": "test_basic.py::test_ok", + "node_type": "case", + "name": "test_ok", + "doc": "This is a test docstring.", + "markers": [], + "parameters": {}, + "path": directory.joinpath("test_basic.py") + .relative_to(directory.parent) + .as_posix(), + "module": "test_basic", + "suite": None, + "function": "test_ok", + } + ], + }, + { + "event": "collect_report", + "session_id": "omitted", + "node_id": ".", + "timestamp": "omitted", + "items": [ { - "event": "collect_report", - "node_id": ".", - "items": [ - { - "node_id": "test_basic.py", - "name": "test_basic.py", - "path": directory.joinpath("test_basic.py") - .relative_to(directory.parent) - .as_posix(), - "doc": "This is a module docstring.", - "markers": [], - "node_type": "module", - } - ], - }, + "node_id": "test_basic.py", + "name": "test_basic.py", + "path": directory.joinpath("test_basic.py") + .relative_to(directory.parent) + .as_posix(), + "doc": "This is a module docstring.", + "markers": [], + "node_type": "module", + } ], }, - ), - ] + ], + }