Skip to content

Support path-based test references in scenario files - #994

Open
shreyaskommuri wants to merge 3 commits into
NVIDIA:mainfrom
shreyaskommuri:issue/path-based-test-references
Open

Support path-based test references in scenario files#994
shreyaskommuri wants to merge 3 commits into
NVIDIA:mainfrom
shreyaskommuri:issue/path-based-test-references

Conversation

@shreyaskommuri

Copy link
Copy Markdown
Contributor

Summary

  • Adds an optional path field on TestRunModel, an alternative to test_name for referencing a test in a scenario file, resolved relative to the scenario file's own directory (confirmed shape in Support relative-path test references and lazy-load only referenced test/hook tomls #985).
  • test_name and path are mutually exclusive, same rules test_name already has with test_template_name.
  • TestScenarioParser._prepare_tdef gets a new branch: when path is set, it loads that toml file directly instead of doing a name lookup against test_mapping, then merges scenario-level overrides the same way the test_name branch already does.
  • Raises a clear TestScenarioParsingError if the resolved path does not exist.
  • This is PR1 of the two-PR plan discussed in Support relative-path test references and lazy-load only referenced test/hook tomls #985. PR2 (skip eager glob-and-parse of --tests-dir/hooks when a scenario's tests are all path-referenced) depends on this one and is not included here, keeping this PR small and reviewable on its own.
  • Fully backward compatible: test_name and fully-inline (test_template_name + name + description) scenarios are unaffected.

Test Plan

7 new tests in tests/test_test_scenario.py (TestPathReference), covering: path/test_name mutual exclusion, path/test_template_name mutual exclusion, relative-path resolution against the scenario file's directory, scenario-level override merging over the referenced file, a missing-file error, and a full scenario TOML parsed end to end with a path reference.

$ uv run pytest tests/test_test_scenario.py -q -k "TestPathReference"
.......
7 passed, 74 deselected in 0.04s

$ uv run pytest -q -m "not ci_only"
1848 passed, 5 skipped, 511 deselected in 4.47s

$ uv run pre-commit run --all-files
check for added large files..............................................Passed
check python ast.........................................................Passed
check for merge conflicts.................................................Passed
check toml................................................................Passed
check yaml.................................................................Passed
debug statements (python)..................................................Passed
fix end of files...........................................................Passed
mixed line ending..........................................................Passed
trim trailing whitespace...................................................Passed
pyright.....................................................................Passed
ruff check...................................................................Passed
ruff format...................................................................Passed
vulture.......................................................................Passed
import-linter..................................................................Passed
taplo...........................................................................Passed

Also updated the wording of two pre-existing validation error messages (in models/scenario.py) that referenced only test_name, so they stay accurate now that path is a second way to satisfy the same requirement. Updated the two existing tests in tests/test_test_scenario.py that asserted on the old wording.

Additional Notes

Design confirmed in #985 before writing any code, per CONTRIBUTING.md's "communicate with the main developers before starting work." Not touching the eager-loading behavior itself, sweeping, or anything unrelated, this PR is purely additive.

Add an optional 'path' field on TestRunModel, mutually exclusive with
'test_name', resolved relative to the scenario file's own directory.
When set, _prepare_tdef loads that file directly instead of doing a
name lookup against test_mapping, with the same scenario-level
override merging test_name already supports.

Ref: NVIDIA#985
Signed-off-by: shreyaskommuri <shreyaskommuri@gmail.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Failed to post review comments.

GitHub was unavailable or timed out while CodeRabbit was posting the review. Please request a new review later if the pull request still needs one. This happened while posting 1 inline comment. Use @coderabbitai full review to retry the review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 3506623d-acc5-486a-915b-457f028d49ce

📥 Commits

Reviewing files that changed from the base of the PR and between 7a17452 and e8e7ac2.

📒 Files selected for processing (2)
  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py

Included review availability: Your plan includes up to 12 reviews per rolling hour; 11 remain after this review.

🧰 Additional context used
🧠 Learnings (11)
📚 Learning: 2025-12-16T19:47:41.994Z
Learnt from: amaslenn
Repo: NVIDIA/cloudai PR: 754
File: src/cloudai/_core/registry.py:226-234
Timestamp: 2025-12-16T19:47:41.994Z
Learning: In this repository, prefer expressing behavioral documentation through tests rather than docstrings. Tests act as living, verified documentation. Reserve docstrings for interfaces or high-level descriptions, and avoid duplicating behavior that is already covered by tests.

Applied to files:

  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py
📚 Learning: 2026-03-16T14:10:11.280Z
Learnt from: amaslenn
Repo: NVIDIA/cloudai PR: 836
File: tests/workloads/test_llm_serving.py:35-83
Timestamp: 2026-03-16T14:10:11.280Z
Learning: In the NVIDIA/cloudai repository, require meaningful docstrings for non-test Python classes (production/library code) to improve readability and maintainability. Test doubles, test helper classes, and other classes defined inside test files (e.g., Fake*, Plain*, stub classes) are exempt from the docstring requirement. Enforce via automated checks (e.g., a docstring style/quality gate using CI) that validate presence and quality of class docstrings for production code while skipping test-only classes within test files.

Applied to files:

  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py
📚 Learning: 2026-03-24T23:24:17.668Z
Learnt from: podkidyshev
Repo: NVIDIA/cloudai PR: 846
File: src/cloudai/reporter.py:168-168
Timestamp: 2026-03-24T23:24:17.668Z
Learning: In the NVIDIA/cloudai repository, follow the project-wide logging convention: use root/global logging calls like `logging.info(...)` and `logging.warning(...)` rather than creating module-level loggers via `logging.getLogger(__name__)`. When reviewing Python code, do not flag or reference LOG015 for this reason and do not suggest switching to module-level loggers. Separately, Ruff’s formatting rule (e.g., G004 f-string vs %-style) is independent and may still be raised if applicable.

Applied to files:

  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py
📚 Learning: 2026-04-14T11:05:59.444Z
Learnt from: podkidyshev
Repo: NVIDIA/cloudai PR: 869
File: src/cloudai/_core/test_scenario.py:23-23
Timestamp: 2026-04-14T11:05:59.444Z
Learning: In the NVIDIA/cloudai repository, do not surface or fail code-review findings for Ruff UP035 warnings about deprecated typing aliases (e.g., typing.List, typing.Set, typing.Type) on individual files. This deprecation cleanup is planned for a dedicated whole-repo modernization bump, so UP035 should be treated as an expected/known issue rather than something reviewers should block at the per-file level.

Applied to files:

  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py
📚 Learning: 2026-06-07T12:01:43.285Z
Learnt from: orbalayla-nvidia
Repo: NVIDIA/cloudai PR: 899
File: src/cloudai/_core/grading_strategy.py:2-2
Timestamp: 2026-06-07T12:01:43.285Z
Learning: In the NVIDIA/cloudai repo, copyright headers’ year formatting must match the test logic enforced by tests/test_check_copyright_headers.py (via collect_years_same_file and _format_years_to_ranges): use comma-separated year lists for non-consecutive “touched” years (e.g., "2024, 2026") and use hyphen ranges only for consecutive years (e.g., "2024-2026"). Do not “normalize” "YYYY, YYYY" into "YYYY-YYYY" unless the missing years are actually present in git history; otherwise the copyright header check will fail.

Applied to files:

  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py
📚 Learning: 2026-06-24T01:05:39.500Z
Learnt from: rutayan-nv
Repo: NVIDIA/cloudai PR: 901
File: src/cloudai/cli/handlers.py:147-162
Timestamp: 2026-06-24T01:05:39.500Z
Learning: For NVIDIA/cloudai: Ruff rule G004 (logging-f-string) is not enabled in this repo’s Ruff configuration, and CI Ruff checks pass even with f-string usage in logging calls. During code reviews, do not flag or request changes specifically for Ruff G004 violations; leave logging f-strings as-is in .py files unless CI or other enabled rules fail.

Applied to files:

  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py
📚 Learning: 2026-02-10T13:29:25.671Z
Learnt from: amaslenn
Repo: NVIDIA/cloudai PR: 799
File: src/cloudai/workloads/vllm/report_generation_strategy.py:47-48
Timestamp: 2026-02-10T13:29:25.671Z
Learning: In src/cloudai/workloads/vllm/report_generation_strategy.py, it is acceptable to annotate parse_vllm_bench_output with a caching decorator (e.g., functools.cache) because benchmark result files are immutable after creation in typical usage. This improves repeated calls by avoiding re-parsing unchanged data. Ensure the function is side-effect free and that cache invalidation is not needed for these inputs. If inputs include non-file-state variability, consider cache keys on file path or content hash.

Applied to files:

  • src/cloudai/models/scenario.py
📚 Learning: 2026-03-10T11:01:25.158Z
Learnt from: podkidyshev
Repo: NVIDIA/cloudai PR: 821
File: src/cloudai/workloads/megatron_bridge/slurm_command_gen_strategy.py:87-97
Timestamp: 2026-03-10T11:01:25.158Z
Learning: In NVIDIA/cloudai repository, there is no secrets management infrastructure; environment variable values (including tokens/secrets) are serialized as literal strings into generated commands and run artifacts (e.g., cloudai_generated_command.sh). This is an architectural limitation acknowledged by the maintainer (podkidyshev). During code reviews for this repo, do not flag secret-serialization issues unless a secrets management solution is available. If a future change introduces proper secrets handling, update this guideline accordingly.

Applied to files:

  • src/cloudai/models/scenario.py
📚 Learning: 2026-03-17T20:01:53.137Z
Learnt from: amaslenn
Repo: NVIDIA/cloudai PR: 839
File: src/cloudai/workloads/sglang/slurm_command_gen_strategy.py:41-41
Timestamp: 2026-03-17T20:01:53.137Z
Learning: In src/cloudai/workloads/sglang/slurm_command_gen_strategy.py, 0.0.0.0 bindings (default prefill_host/decode_host in get_serve_commands and --host 0.0.0.0 in get_helper_command) are intentional for in-cluster serving. Ruff S104 warnings on these lines should not be flagged or require suppression comments, as the maintainer (amaslenn) has explicitly confirmed this is the intended behavior.

Applied to files:

  • src/cloudai/models/scenario.py
📚 Learning: 2026-02-12T13:47:34.298Z
Learnt from: podkidyshev
Repo: NVIDIA/cloudai PR: 803
File: tests/test_check_copyright_headers.py:127-141
Timestamp: 2026-02-12T13:47:34.298Z
Learning: In pytest, rely on assertion introspection for failure details and avoid including explicit values in the assertion message (e.g., avoid f"expected {x!r}, got {y!r}"). Let pytest show actual vs expected. You may add concise context messages only when the assertion is not easily understandable from the expression alone.

Applied to files:

  • tests/test_test_scenario.py
📚 Learning: 2026-03-24T14:24:38.412Z
Learnt from: amaslenn
Repo: NVIDIA/cloudai PR: 845
File: tests/workloads/nixl_ep/test_job_status_retrieval_strategy.py:196-220
Timestamp: 2026-03-24T14:24:38.412Z
Learning: For pytest tests in this repo, when using `pytest.mark.parametrize`, use the idiomatic comma-separated string form for the argument names (e.g., `"log_content, expected_fragment"`) instead of the tuple form, matching the team’s preference and pytest documentation. Do not flag Ruff PT006 for this style in `pytest.mark.parametrize`.

Applied to files:

  • tests/test_test_scenario.py
🪛 Ruff (0.16.1)
src/cloudai/models/scenario.py

[warning] 157-158: Use elif instead of else then if, to reduce indentation

Convert to elif

(PLR5501)

📝 Walkthrough

Walkthrough

TestRunModel now accepts a scenario-relative TOML path as an alternative test reference. The parser resolves the path, loads the definition, applies scenario overrides, and reports missing files. Tests cover validation, loading, merging, and end-to-end parsing.

Changes

Scenario test path references

Layer / File(s) Summary
Test reference contract
src/cloudai/models/scenario.py, tests/test_test_scenario.py
TestRunModel adds the optional path field. Validation prevents conflicting references and updates inline-definition and template-name rules. Tests cover the updated validation behavior.
Path loading and validation
src/cloudai/test_scenario_parser.py, tests/test_test_scenario.py
TestScenarioParser resolves and loads scenario-relative test TOML files, merges overrides, and raises TestScenarioParsingError for missing files. Tests cover path resolution, merging, errors, and full scenario parsing.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🔵 Low · up to e8e7a

The change is localized and backward-compatible, but an absolute path may bypass the documented scenario-file-relative resolution and load a file outside that directory; confirm or restrict this behavior before merging.

Suggested reviewers: jj10306

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding path-based test references in scenario files.
Description check ✅ Passed The description accurately explains the path field, validation rules, parser behavior, tests, and backward compatibility.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cloudai/models/scenario.py`:
- Around line 74-80: Update the Optional path field in TestRunModel to enforce
min_length=1, rejecting empty strings during validation while preserving None as
valid. Add a regression test covering path="" and verify validation fails before
_prepare_tdef is reached.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 5c512b3e-96c4-4630-84b6-898ffd08b847

📥 Commits

Reviewing files that changed from the base of the PR and between 5b5c0f7 and 1b62b6c.

📒 Files selected for processing (3)
  • src/cloudai/models/scenario.py
  • src/cloudai/test_scenario_parser.py
  • tests/test_test_scenario.py

Comment thread src/cloudai/models/scenario.py
Field(min_length=1) rejects path="" at validation time instead of
letting it through as a truthy-looking value that would otherwise
resolve to the scenario file's own directory.

Signed-off-by: shreyaskommuri <shreyaskommuri@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
tests/test_test_scenario.py (1)

1006-1032: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Exercise the public scenario parser in the end-to-end test.

At Lines 1027-1030, the test manually validates the TOML and calls private _prepare_tdef(). This verifies the helper and the model, but not the parser's public scenario-loading flow. If this test must provide end-to-end coverage, use the public parser entry point and assert the resulting scenario test. Otherwise, rename the test to indicate helper-level coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_test_scenario.py` around lines 1006 - 1032, Update
test_full_scenario_toml_with_path_reference to exercise TestScenarioParser’s
public scenario-loading entry point instead of manually calling
TestScenarioModel.model_validate and private _prepare_tdef. Assert the resulting
parsed scenario test still has name "nccl", preserving end-to-end coverage of
the path reference flow.
src/cloudai/models/scenario.py (1)

159-159: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject an empty test_template_name with a path.

if self.test_template_name treats "" as unset. Therefore, TestRunModel(id="1", path="nccl.toml", test_template_name="") passes validation, although path and test_template_name are mutually exclusive. tdef_model_dump() retains the empty string, so _prepare_tdef() can merge it over the referenced definition. Use an is not None check and add a regression test.

Proposed validation fix
         else:
-            if self.test_template_name:
+            if self.test_template_name is not None:
                 raise ValueError("'test_template_name' must not be set if 'test_name' or 'path' is set.")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cloudai/models/scenario.py` at line 159, Update the validation involving
test_template_name in TestRunModel so an empty string is treated as explicitly
set when path or test_name is provided, using an is not None check rather than
truthiness; add a regression test covering path with test_template_name="".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_test_scenario.py`:
- Around line 944-947: Update test_empty_path_is_rejected to pass the expected
error-message pattern directly via pytest.raises, and remove the separate
exc_info.match assertion.

---

Outside diff comments:
In `@src/cloudai/models/scenario.py`:
- Line 159: Update the validation involving test_template_name in TestRunModel
so an empty string is treated as explicitly set when path or test_name is
provided, using an is not None check rather than truthiness; add a regression
test covering path with test_template_name="".

In `@tests/test_test_scenario.py`:
- Around line 1006-1032: Update test_full_scenario_toml_with_path_reference to
exercise TestScenarioParser’s public scenario-loading entry point instead of
manually calling TestScenarioModel.model_validate and private _prepare_tdef.
Assert the resulting parsed scenario test still has name "nccl", preserving
end-to-end coverage of the path reference flow.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 171803a1-2257-46ce-b0ea-5491d6e62d78

📥 Commits

Reviewing files that changed from the base of the PR and between 1b62b6c and 7a17452.

📒 Files selected for processing (2)
  • src/cloudai/models/scenario.py
  • tests/test_test_scenario.py

Comment thread tests/test_test_scenario.py Outdated
@shreyaskommuri

Copy link
Copy Markdown
Contributor Author

@podkidyshev the empty-path issue from CodeRabbit is resolved, min_length=1 pushed and confirmed rejecting "" while still allowing None/real paths (see reply on the review thread above), plus a regression test. All CI green on the latest commit. Let me know if there's anything else you'd like changed.

- 'test_template_name' must not be set if 'test_name' or 'path' is
  set now checks `is not None` instead of truthiness, so an explicit
  empty string no longer slips past the mutual-exclusion check.
- test_empty_path_is_rejected and the new empty-test_template_name
  test pass their match pattern directly to pytest.raises instead of
  a separate exc_info.match() call.
- test_full_scenario_toml_with_path_reference now calls the public
  TestScenarioParser.parse() instead of the private _prepare_tdef(),
  exercising the actual end-to-end scenario-parsing path.

Signed-off-by: shreyaskommuri <shreyaskommuri@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants