Skip to content

Commit 6498765

Browse files
feat(xtest): --scenario and --instance flags for conftest (DSPX-3302)
Adds two new pytest CLI options so xtest can be driven by a scenarios.yaml and run against a specific otdf-local instance. --scenario PATH When set, defaults --sdks-encrypt, --sdks-decrypt, and --containers from the scenario's `sdks` and `suite` blocks. Options explicitly passed on the CLI always override. --instance NAME Propagated to OTDF_LOCAL_INSTANCE_NAME so child `otdf-local` invocations within the test see the same instance the scenario expects. If otdf-sdk-mgr is not installed (minimal pytest environments), the --scenario flag silently no-ops via an ImportError guard. The flag shape is invariant either way so CI configs don't fork. This is the consumer side of the PR 3 / scenario-driven flow: the authoritative entry point remains `otdf-local scenario run <path>`, which sets these flags for you; this PR lets pytest accept them directly when running scenario-aware sessions outside the wrapper. Refs: https://virtru.atlassian.net/browse/DSPX-3302 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 78b2ca6 commit 6498765

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

xtest/conftest.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ def sdk_spec_type(v: str) -> str:
7878

7979
def pytest_addoption(parser: pytest.Parser):
8080
"""Add custom CLI options for pytest."""
81+
parser.addoption(
82+
"--scenario",
83+
help="path to scenarios.yaml; --sdks-encrypt/--sdks-decrypt/--containers default from it",
84+
type=Path,
85+
)
86+
parser.addoption(
87+
"--instance",
88+
help="otdf-local instance name; sets OTDF_LOCAL_INSTANCE_NAME for child tooling",
89+
type=str,
90+
)
8191
parser.addoption(
8292
"--audit-log-dir",
8393
help="directory to write audit logs on test failure (default: tmp/audit-logs)",
@@ -130,6 +140,57 @@ def pytest_addoption(parser: pytest.Parser):
130140
)
131141

132142

143+
def pytest_configure(config: pytest.Config) -> None:
144+
"""Apply --scenario defaults and --instance env-var threading.
145+
146+
When `--scenario PATH` is given, missing `--sdks-encrypt`, `--sdks-decrypt`,
147+
and `--containers` options are populated from the scenario file. Options
148+
explicitly passed on the CLI always win. `--instance NAME` is propagated
149+
via `OTDF_LOCAL_INSTANCE_NAME` so any child `otdf-local` invocation sees
150+
the same instance.
151+
"""
152+
import os
153+
154+
instance = config.getoption("--instance")
155+
if instance:
156+
os.environ["OTDF_LOCAL_INSTANCE_NAME"] = instance
157+
158+
scenario_path = config.getoption("--scenario")
159+
if not scenario_path:
160+
return
161+
try:
162+
from otdf_sdk_mgr.schema import (
163+
installed_json_for,
164+
load_scenario,
165+
scenario_to_pytest_sdks,
166+
)
167+
except ImportError:
168+
# otdf-sdk-mgr may not be installed in a minimal pytest env.
169+
return
170+
scenario = load_scenario(scenario_path)
171+
# `sdk@<version>` tokens come from the install record so they match the
172+
# dist directories #446's parser walks under `xtest/sdk/<lang>/dist/`.
173+
# If the user passed --sdks-encrypt / --sdks-decrypt explicitly, their
174+
# tokens win and we skip the resolution step entirely.
175+
need_resolve = (
176+
(not config.getoption("--sdks-encrypt") and scenario.sdks.encrypt)
177+
or (not config.getoption("--sdks-decrypt") and scenario.sdks.decrypt)
178+
)
179+
if need_resolve:
180+
try:
181+
tokens = scenario_to_pytest_sdks(scenario, installed_json_for(scenario_path))
182+
except FileNotFoundError as e:
183+
raise pytest.UsageError(str(e)) from e
184+
if not config.getoption("--sdks-encrypt") and tokens["encrypt"]:
185+
config.option.sdks_encrypt = " ".join(tokens["encrypt"])
186+
if not config.getoption("--sdks-decrypt") and tokens["decrypt"]:
187+
config.option.sdks_decrypt = " ".join(tokens["decrypt"])
188+
if not config.getoption("--containers") and scenario.suite.containers:
189+
config.option.containers = scenario.suite.containers
190+
if not instance and scenario.instance.metadata.name:
191+
os.environ["OTDF_LOCAL_INSTANCE_NAME"] = scenario.instance.metadata.name
192+
193+
133194
def pytest_generate_tests(metafunc: pytest.Metafunc):
134195
"""Dynamically parametrize test functions based on CLI options.
135196

0 commit comments

Comments
 (0)