Skip to content

Commit 5e5f226

Browse files
committed
Add minimal tests for async, streaming cases.
1 parent 44f5081 commit 5e5f226

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed

instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/generate_content/test_async_nonstreaming.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#!./run_with_env.sh
2+
13
# Copyright The OpenTelemetry Authors
24
#
35
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,3 +13,58 @@
1113
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1214
# See the License for the specific language governing permissions and
1315
# limitations under the License.
16+
17+
import asyncio
18+
import logging
19+
import unittest
20+
import sys
21+
sys.path.append('../')
22+
23+
from common.base import TestCase
24+
25+
def create_valid_response(response_text='The model response', input_tokens=10, output_tokens=20):
26+
return {
27+
'modelVersion': 'gemini-2.0-flash-test123',
28+
'usageMetadata': {
29+
'promptTokenCount': input_tokens,
30+
'candidatesTokenCount': output_tokens,
31+
'totalTokenCount': input_tokens + output_tokens,
32+
},
33+
'candidates': [{
34+
'content': {
35+
'role': 'model',
36+
'parts': [{
37+
'text': response_text,
38+
}],
39+
}
40+
}]
41+
}
42+
43+
class TestGenerateContentAsyncNonstreaming(TestCase):
44+
45+
def setUp(self):
46+
super().setUp()
47+
48+
def configure_valid_response(self, response_text='The model_response', input_tokens=10, output_tokens=20):
49+
self.requests.add_response(create_valid_response(
50+
response_text=response_text,
51+
input_tokens=input_tokens,
52+
output_tokens=output_tokens))
53+
54+
def generate_content(self, *args, **kwargs):
55+
return asyncio.run(self.client.aio.models.generate_content(*args, **kwargs))
56+
57+
def test_async_generate_content_not_broken_by_instrumentation(self):
58+
self.configure_valid_response(response_text='Yep, it works!')
59+
response = self.generate_content(
60+
model='gemini-2.0-flash',
61+
contents='Does this work?')
62+
self.assertEqual(response.text, 'Yep, it works!')
63+
64+
def main():
65+
logging.basicConfig(level=logging.DEBUG)
66+
unittest.main()
67+
68+
69+
if __name__ == '__main__':
70+
main()

instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/generate_content/test_async_streaming.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#!./run_with_env.sh
2+
13
# Copyright The OpenTelemetry Authors
24
#
35
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,3 +13,65 @@
1113
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1214
# See the License for the specific language governing permissions and
1315
# limitations under the License.
16+
17+
import asyncio
18+
import logging
19+
import unittest
20+
import sys
21+
sys.path.append('../')
22+
23+
from common.base import TestCase
24+
25+
def create_valid_response(response_text='The model response', input_tokens=10, output_tokens=20):
26+
return {
27+
'modelVersion': 'gemini-2.0-flash-test123',
28+
'usageMetadata': {
29+
'promptTokenCount': input_tokens,
30+
'candidatesTokenCount': output_tokens,
31+
'totalTokenCount': input_tokens + output_tokens,
32+
},
33+
'candidates': [{
34+
'content': {
35+
'role': 'model',
36+
'parts': [{
37+
'text': response_text,
38+
}],
39+
}
40+
}]
41+
}
42+
43+
class TestGenerateContentAsyncStreaming(TestCase):
44+
45+
def setUp(self):
46+
super().setUp()
47+
48+
def configure_valid_response(self, response_text='The model_response', input_tokens=10, output_tokens=20):
49+
self.requests.add_response(create_valid_response(
50+
response_text=response_text,
51+
input_tokens=input_tokens,
52+
output_tokens=output_tokens))
53+
54+
async def _generate_content_helper(self, *args, **kwargs):
55+
result = []
56+
async for response in await self.client.aio.models.generate_content_stream(*args, **kwargs):
57+
result.append(response)
58+
return result
59+
60+
def generate_content(self, *args, **kwargs):
61+
return asyncio.run(self._generate_content_helper(*args, **kwargs))
62+
63+
def test_async_generate_content_not_broken_by_instrumentation(self):
64+
self.configure_valid_response(response_text='Yep, it works!')
65+
responses = self.generate_content(
66+
model='gemini-2.0-flash',
67+
contents='Does this work?')
68+
self.assertEqual(len(responses), 1)
69+
self.assertEqual(responses[0].text, 'Yep, it works!')
70+
71+
def main():
72+
logging.basicConfig(level=logging.DEBUG)
73+
unittest.main()
74+
75+
76+
if __name__ == '__main__':
77+
main()
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!./run_with_env.sh
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import asyncio
18+
import logging
19+
import unittest
20+
import sys
21+
sys.path.append('../')
22+
23+
from common.base import TestCase
24+
25+
def create_valid_response(response_text='The model response', input_tokens=10, output_tokens=20):
26+
return {
27+
'modelVersion': 'gemini-2.0-flash-test123',
28+
'usageMetadata': {
29+
'promptTokenCount': input_tokens,
30+
'candidatesTokenCount': output_tokens,
31+
'totalTokenCount': input_tokens + output_tokens,
32+
},
33+
'candidates': [{
34+
'content': {
35+
'role': 'model',
36+
'parts': [{
37+
'text': response_text,
38+
}],
39+
}
40+
}]
41+
}
42+
43+
class TestGenerateContentSyncStreaming(TestCase):
44+
45+
def setUp(self):
46+
super().setUp()
47+
48+
def configure_valid_response(self, response_text='The model_response', input_tokens=10, output_tokens=20):
49+
self.requests.add_response(create_valid_response(
50+
response_text=response_text,
51+
input_tokens=input_tokens,
52+
output_tokens=output_tokens))
53+
54+
def generate_content(self, *args, **kwargs):
55+
result = []
56+
for response in self.client.models.generate_content_stream(*args, **kwargs):
57+
result.append(response)
58+
return result
59+
60+
def test_async_generate_content_not_broken_by_instrumentation(self):
61+
self.configure_valid_response(response_text='Yep, it works!')
62+
responses = self.generate_content(
63+
model='gemini-2.0-flash',
64+
contents='Does this work?')
65+
self.assertEqual(len(responses), 1)
66+
self.assertEqual(responses[0].text, 'Yep, it works!')
67+
68+
def main():
69+
logging.basicConfig(level=logging.DEBUG)
70+
unittest.main()
71+
72+
73+
if __name__ == '__main__':
74+
main()

0 commit comments

Comments
 (0)