Repository navigation
refactor(e2e): simplify test infrastructure by removing duplication and dead code #587
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,7 +16,7 @@ | |||||||||||||||||||||||||||
| import pytest | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if TYPE_CHECKING: | ||||||||||||||||||||||||||||
| from infra import ModelPool | ||||||||||||||||||||||||||||
| from infra import ModelInstance, ModelPool | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| from .hooks import get_pool_requirements | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
@@ -170,44 +170,60 @@ def model_pool(request: pytest.FixtureRequest) -> ModelPool: | |||||||||||||||||||||||||||
| return _model_pool | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| @pytest.fixture | ||||||||||||||||||||||||||||
| def model_client( | ||||||||||||||||||||||||||||
| request: pytest.FixtureRequest, model_pool: ModelPool | ||||||||||||||||||||||||||||
| ) -> Generator[object, None, None]: | ||||||||||||||||||||||||||||
| """Get OpenAI client for the model specified by @pytest.mark.model(). | ||||||||||||||||||||||||||||
| def _get_model_instance( | ||||||||||||||||||||||||||||
| request: pytest.FixtureRequest, model_pool: ModelPool, fixture_name: str | ||||||||||||||||||||||||||||
| ) -> ModelInstance: | ||||||||||||||||||||||||||||
| """Extract model from marker and acquire instance from pool. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Usage: | ||||||||||||||||||||||||||||
| @pytest.mark.model("meta-llama/Llama-3.1-8B-Instruct") | ||||||||||||||||||||||||||||
| def test_chat(model_client): | ||||||||||||||||||||||||||||
| response = model_client.chat.completions.create(...) | ||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||
| request: Pytest fixture request. | ||||||||||||||||||||||||||||
| model_pool: The model pool. | ||||||||||||||||||||||||||||
| fixture_name: Name of the calling fixture (for error messages). | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||
| Acquired ModelInstance. | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| import openai | ||||||||||||||||||||||||||||
| from infra import PARAM_MODEL | ||||||||||||||||||||||||||||
| from infra import PARAM_MODEL, ConnectionMode | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| marker = request.node.get_closest_marker(PARAM_MODEL) | ||||||||||||||||||||||||||||
| if marker is None: | ||||||||||||||||||||||||||||
| if marker is None or not marker.args: | ||||||||||||||||||||||||||||
| pytest.fail( | ||||||||||||||||||||||||||||
| f"Test must be marked with @pytest.mark.{PARAM_MODEL}('model-id') " | ||||||||||||||||||||||||||||
| "to use model_client fixture" | ||||||||||||||||||||||||||||
| f"to use {fixture_name} fixture" | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| model_id = marker.args[0] | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||
| # get() auto-acquires the returned instance | ||||||||||||||||||||||||||||
| instance = model_pool.get(model_id) | ||||||||||||||||||||||||||||
| return model_pool.get(model_id, ConnectionMode.HTTP) | ||||||||||||||||||||||||||||
| except KeyError: | ||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||
| pytest.skip(f"Model {model_id} not available in model pool") | ||||||||||||||||||||||||||||
|
Comment on lines
197
to
200
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer explicit failure over skip when required model acquisition fails. At Line 200, 💡 Proposed fix try:
return model_pool.get(model_id, ConnectionMode.HTTP)
except KeyError:
- pytest.skip(f"Model {model_id} not available in model pool")
+ pytest.fail(
+ f"Model {model_id} not available in model pool for {fixture_name}; "
+ "check model prelaunch requirements and test markers."
+ )Based on learnings: tests should fail explicitly when required services are unavailable rather than being skipped to catch misconfigurations. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| @pytest.fixture | ||||||||||||||||||||||||||||
| def model_client( | ||||||||||||||||||||||||||||
| request: pytest.FixtureRequest, model_pool: ModelPool | ||||||||||||||||||||||||||||
| ) -> Generator[object, None, None]: | ||||||||||||||||||||||||||||
| """Get OpenAI client for the model specified by @pytest.mark.model(). | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Usage: | ||||||||||||||||||||||||||||
| @pytest.mark.model("meta-llama/Llama-3.1-8B-Instruct") | ||||||||||||||||||||||||||||
| def test_chat(model_client): | ||||||||||||||||||||||||||||
| response = model_client.chat.completions.create(...) | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| import openai | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| instance = _get_model_instance(request, model_pool, "model_client") | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| client = openai.OpenAI( | ||||||||||||||||||||||||||||
| base_url=f"{instance.base_url}/v1", | ||||||||||||||||||||||||||||
| api_key="not-used", | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| yield client | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Release reference to allow eviction | ||||||||||||||||||||||||||||
| instance.release() | ||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||
| yield client | ||||||||||||||||||||||||||||
| finally: | ||||||||||||||||||||||||||||
| instance.release() | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| @pytest.fixture | ||||||||||||||||||||||||||||
|
|
@@ -221,24 +237,9 @@ def model_base_url( | |||||||||||||||||||||||||||
| def test_direct_http(model_base_url): | ||||||||||||||||||||||||||||
| response = httpx.get(f"{model_base_url}/health") | ||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||
| from infra import PARAM_MODEL | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| marker = request.node.get_closest_marker(PARAM_MODEL) | ||||||||||||||||||||||||||||
| if marker is None: | ||||||||||||||||||||||||||||
| pytest.fail( | ||||||||||||||||||||||||||||
| f"Test must be marked with @pytest.mark.{PARAM_MODEL}('model-id') " | ||||||||||||||||||||||||||||
| "to use model_base_url fixture" | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| model_id = marker.args[0] | ||||||||||||||||||||||||||||
| instance = _get_model_instance(request, model_pool, "model_base_url") | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||
| # get() auto-acquires the returned instance | ||||||||||||||||||||||||||||
| instance = model_pool.get(model_id) | ||||||||||||||||||||||||||||
| except KeyError: | ||||||||||||||||||||||||||||
| pytest.skip(f"Model {model_id} not available in model pool") | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| yield instance.base_url | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| # Release reference to allow eviction | ||||||||||||||||||||||||||||
| instance.release() | ||||||||||||||||||||||||||||
| yield instance.base_url | ||||||||||||||||||||||||||||
| finally: | ||||||||||||||||||||||||||||
| instance.release() | ||||||||||||||||||||||||||||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure reserved ports are released even when process spawn fails.
At Line 225 and Line 299,
get_open_port()reserves immediately, butsubprocess.Popen(...)is executed before enteringtry/finally. If spawn fails,release_port()is skipped and reservations leak.💡 Proposed fix
Also applies to: 299-300
🤖 Prompt for AI Agents