Skip to content

Commit 853d8cd

Browse files
Gemini Testing via VCR (#1770)
* Delete old replay files * Replace Gemini test setup with VCR * Improve behavior of Gemini tests * Add additional logic to VCR setup * Record new Gemini responses with VCR * Improved megalinter filtering * User helper to drop recorded headers * Clean up comment --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 5734092 commit 853d8cd

104 files changed

Lines changed: 2667 additions & 73361 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.mega-linter.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,15 @@ CLEAR_REPORT_FOLDER: true
2525
VALIDATE_ALL_CODEBASE: true
2626
IGNORE_GITIGNORED_FILES: true
2727
FAIL_IF_MISSING_LINTER_IN_FLAVOR: true
28-
FILTER_REGEX_EXCLUDE: "(.*/?packages/.*)" # Ignore packages directories
28+
FILTER_REGEX_EXCLUDE: "(.*cassette.*\\.ya?ml)" # Ignore recorded cassette.yaml files
29+
ADDITIONAL_EXCLUDED_DIRECTORIES:
30+
- .pytest_cache
31+
- .ruff_cache
32+
- .tox
33+
- .venv
34+
- megalinter-reports
35+
- newrelic.egg-info
36+
- newrelic/packages
2937

3038
ENABLE_LINTERS: # If you use ENABLE_LINTERS variable, all other linters will be disabled by default
3139
- ACTION_ACTIONLINT

tests/mlmodel_gemini/cassette.yaml

Lines changed: 2441 additions & 0 deletions
Large diffs are not rendered by default.

tests/mlmodel_gemini/conftest.py

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import google.genai
1919
import pytest
2020
from testing_support.fixture.event_loop import event_loop as loop
21+
from testing_support.fixture.vcr import * # noqa: F403
2122
from testing_support.fixtures import (
2223
collector_agent_registration_fixture,
2324
collector_available_fixture,
@@ -46,61 +47,27 @@
4647

4748

4849
@pytest.fixture
49-
def gemini_client(replay_id, is_vertex):
50+
def gemini_client(vcr_recording, is_vertex):
5051
"""
51-
This configures the Gemini client to use a ReplayApiClient which will either record or replay responses depending
52-
on the mode. The mode can be controlled by setting NEW_RELIC_TESTING_RECORD_GEMINI_RESPONSES=1 as an environment
53-
variable to run using the real Gemini backend. (Default: mocking)
54-
"""
55-
from newrelic.core.config import _environ_as_bool
52+
This configures the Gemini client to use a fake API key when replaying responses through VCR.
5653
57-
record_mode = _environ_as_bool("NEW_RELIC_TESTING_RECORD_GEMINI_RESPONSES", False)
58-
# Auto mode will record any missing files, but still replay existing files.
59-
# This allows us to add new tests without having to re-record everything.
60-
# If you need to re-record everything, you can delete the existing replays completely.
61-
replay_client_mode = "auto" if record_mode else "replay"
54+
To record new responses, set a valid API key and run pytest with the flag --record-mode=new_episodes.
55+
"""
6256

63-
if record_mode:
57+
if vcr_recording:
6458
google_api_key = os.environ.get("GOOGLE_API_KEY")
6559
if not google_api_key:
6660
raise RuntimeError("GOOGLE_API_KEY environment variable required.")
6761
else:
68-
google_api_key = os.environ["GOOGLE_API_KEY"] = "GEMINI_API_KEY"
69-
70-
# Set the replay directory to a location in this test suite.
71-
replay_dir = Path(__file__).parent / "replays"
72-
replay_dir.mkdir(exist_ok=True) # Recreate this directory if it's missing for recording purposes
73-
os.environ["GOOGLE_GENAI_REPLAYS_DIRECTORY"] = str(replay_dir)
62+
google_api_key = os.environ["GOOGLE_API_KEY"] = "FAKE_GEMINI_API_KEY"
7463

75-
# Monkeypatch the Gemini client to use the replay client which will either record or replay responses depending on the mode.
76-
replay_client = google.genai._replay_api_client.ReplayApiClient(mode=replay_client_mode, replay_id=replay_id)
77-
google.genai.client.Client._get_api_client = lambda self, *args, **kwargs: replay_client
7864
gemini_client = google.genai.Client(api_key=google_api_key, vertexai=is_vertex)
7965

8066
yield gemini_client
8167

82-
gemini_client._api_client.close()
8368
gemini_client.close()
8469

8570

86-
@pytest.fixture
87-
def replay_id():
88-
pytest_name = os.environ.get("PYTEST_CURRENT_TEST").split("::")
89-
test_module = Path(pytest_name[0]).with_suffix("").name
90-
test_name, test_params = pytest_name[-1].split(" ")[0].split("[")
91-
92-
# Don't use the actual parameter string in the replay ID to avoid having different replays for certain parameters
93-
# like is_async and to avoid issues with sorting. We also can't directly use the fixtures or we will cause the
94-
# embedding tests to run despite not having streaming or chat parameters. Instead we will just infer the info
95-
# from the test names and reproduce it in a standardized format.
96-
is_streaming = "stream" in test_params
97-
is_chat = "chat" in test_params
98-
is_vertex = "vertex" in test_params
99-
test_params_suffix = f"{'streaming' if is_streaming else 'invoke'}-{'chat' if is_chat else 'model'}-{'vertex' if is_vertex else 'standard'}"
100-
101-
return f"{test_module}/{test_name}/{test_params_suffix}"
102-
103-
10471
@pytest.fixture(scope="session", params=["standard", "vertex"])
10572
def is_vertex(request):
10673
return request.param == "vertex"

0 commit comments

Comments
 (0)