Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔨 Adds more diagnostics info when pytest fails #159

Merged
merged 6 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ target/
#Ipython Notebook
.ipynb_checkpoints

# vscode config
# IDEs config (except templates)
.vscode/*
!.vscode/*.template.json


# docs output
site
Expand Down
5 changes: 5 additions & 0 deletions .vscode/settings.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"pylint.args": [
"--rcfile=clients/python/.pylintrc"
]
}
64 changes: 63 additions & 1 deletion clients/python/.pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,69 @@ confidence=HIGH,
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=R,C,W
disable=raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
too-few-public-methods,
trailing-whitespace,
duplicate-code,
too-many-locals,
bad-file-encoding,
unnecessary-dunder-call,
unneeded-not,
consider-using-enumerate,
consider-iterating-dictionary,
consider-using-dict-items,
use-maxsplit-arg,
use-sequence-for-iteration,
consider-using-f-string,
use-implicit-booleaness-not-len,
use-implicit-booleaness-not-comparison,
wrong-spelling-in-comment,
wrong-spelling-in-docstring,
invalid-characters-in-docstring,
line-too-long,
too-many-lines,
missing-final-newline,
trailing-newlines,
multiple-statements,
superfluous-parens,
mixed-line-endings,
unexpected-line-ending-format,
non-ascii-name,
non-ascii-module-import,
unnecessary-lambda-assignment,
unnecessary-direct-lambda-call,
multiple-imports,
wrong-import-order,
ungrouped-imports,
wrong-import-position,
useless-import-alias,
import-outside-toplevel,
invalid-name,
disallowed-name,
typevar-name-incorrect-variance,
typevar-double-variance,
typevar-name-mismatch,
empty-docstring,
missing-module-docstring,
missing-class-docstring,
missing-function-docstring,
singleton-comparison,
unidiomatic-typecheck,
bad-classmethod-argument,
bad-mcs-method-argument,
bad-mcs-classmethod-argument,
single-string-used-for-slots,
fixme,
import-error,
unspecified-encoding,
use-dict-literal

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
Expand Down
2 changes: 1 addition & 1 deletion clients/python/client/osparc/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ParentProjectInfo(BaseSettings):

@field_validator("x_simcore_parent_project_uuid", "x_simcore_parent_node_id")
@classmethod
def validate_uuids(cls, v: Optional[str]) -> str:
def _validate_uuids(cls, v: Optional[str]) -> str:
if v is not None:
_ = UUID(v)
return v
69 changes: 67 additions & 2 deletions clients/python/test/e2e/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import logging
import os
from pathlib import Path
Expand All @@ -14,6 +15,70 @@
_GB: ByteSize = ByteSize(_MB * 1024) # in bytes


# Dictionary to store start times of tests
_test_start_times = {}


def _utc_now():
return datetime.datetime.now(tz=datetime.timezone.utc)


def _construct_graylog_url(api_host, start_time, end_time):
"""
Construct a Graylog URL for the given time interval.
"""
base_url = api_host.replace("api.", "monitoring.", 1).rstrip("/")
url = f"{base_url}/graylog/search"
start_time_str = start_time.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
end_time_str = end_time.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
query = f"from={start_time_str}&to={end_time_str}"
return f"{url}?{query}"


def pytest_runtest_setup(item):
"""
Hook to capture the start time of each test.
"""
_test_start_times[item.name] = _utc_now()


def pytest_runtest_makereport(item, call):
"""
Hook to add extra information when a test fails.
"""
if call.when == "call":

# Check if the test failed
if call.excinfo is not None:
test_name = item.name
test_location = item.location
api_host = os.environ.get("OSPARC_API_HOST", "")

diagnostics = {
"test_name": test_name,
"test_location": test_location,
"api_host": api_host,
}

# Get the start and end times of the test
start_time = _test_start_times.get(test_name)
end_time = _utc_now()

if start_time:
diagnostics["graylog_url"] = _construct_graylog_url(api_host, start_time, end_time)

# Print the diagnostics
print(f"\nDiagnostics for {test_name}:")
for key, value in diagnostics.items():
print(" ", key, ":", value)


@pytest.hookimpl(tryfirst=True)
def pytest_configure(config):
config.pluginmanager.register(pytest_runtest_setup, "osparc_test_times_plugin")
config.pluginmanager.register(pytest_runtest_makereport, "osparc_makereport_plugin")


@pytest.fixture
def configuration() -> Iterable[osparc.Configuration]:
assert (host := os.environ.get("OSPARC_API_HOST"))
Expand Down Expand Up @@ -60,9 +125,9 @@ def tmp_file(tmp_path: Path, caplog) -> Path:


@pytest.fixture
def sleeper(api_client: osparc.ApiClient) -> Iterable[osparc.Solver]:
def sleeper(api_client: osparc.ApiClient) -> osparc.Solver:
solvers_api = osparc.SolversApi(api_client=api_client)
sleeper: osparc.Solver = solvers_api.get_solver_release(
"simcore/services/comp/itis/sleeper", "2.0.2"
) # type: ignore
yield sleeper
return sleeper
6 changes: 4 additions & 2 deletions clients/python/test/e2e/test_solvers_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ async def test_logstreaming(
solvers_api.start_job(sleeper.id, sleeper.version, job.id)

nloglines: int = 0
print("starting logstreaming...")
url = f"/v0/solvers/{sleeper.id}/releases/{sleeper.version}/jobs/{job.id}/logstream"
print(f"starting logstreaming from {url}...")

async with async_client.stream(
"GET",
f"/v0/solvers/{sleeper.id}/releases/{sleeper.version}/jobs/{job.id}/logstream",
url,
timeout=DEFAULT_TIMEOUT_SECONDS,
) as response:
async for line in response.aiter_lines():
Expand Down
Loading