-
Notifications
You must be signed in to change notification settings - Fork 2
tests: Unit Tests for SpanIOProcessor and groq utils #311
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
Open
ivanrj7j
wants to merge
10
commits into
KeyValueSoftwareSystems:develop
Choose a base branch
from
ivanrj7j:tests/Unit-Test
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
57aa2ae
test: Write test for SpanIOProcessor (PRD 4.3)
ivanrj7j bba20c4
test: Write test for groq provider utils
ivanrj7j 8e8bc79
test: Write more tests for groq provider covering every methods
ivanrj7j 54d851b
refactor: Create a base provider class for all utils.py related test …
ivanrj7j 4a80f59
refactor: Move some responsibility back to TestGroqProviderUtils class
ivanrj7j c3d0043
test: Refactor provider utility tests and fix inheritance discovery
ivanrj7j c709203
fix: Naming issues as per PR#311 review
ivanrj7j 375a287
refactor: Remove unnecessary test cases and helper functions
ivanrj7j b3ed8f9
refactor: Remove unnecessary variables
ivanrj7j 3337882
fix: Switch to using plain assert statement instead of assertEqual
ivanrj7j File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from .base_provider_utils import BaseProviderUtils |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| import itertools | ||
| from typing import Callable | ||
| from unittest.mock import MagicMock | ||
|
|
||
| from opentelemetry.semconv_ai import SpanAttributes | ||
|
|
||
|
|
||
| class BaseProviderUtils: | ||
| """Base class to be inherited by test cases that are going to test `utils.py` from `netra/instrumentation/openai/`, `netra/instrumentation/groq/` etc.""" | ||
|
|
||
| ALIASES = { | ||
| "prompt_tokens": ["prompt_tokens", "input_tokens"], | ||
| "completion_tokens": ["completion_tokens", "output_tokens"], | ||
| "prompt_tokens_details": ["prompt_tokens_details", "input_tokens_details"], | ||
| } | ||
|
|
||
| P_TOKEN = 100 | ||
| C_TOKEN = 50 | ||
| P_DETAIL = 10 | ||
| T_TOKEN = 160 | ||
|
|
||
| _set_usage_attributes_method: Callable = None | ||
|
|
||
| def _build_input_data(self): | ||
| keys_groups = [ | ||
| self.ALIASES["prompt_tokens"], | ||
| self.ALIASES["completion_tokens"], | ||
| self.ALIASES["prompt_tokens_details"], | ||
| ] | ||
|
|
||
| for p_token, c_token, p_detail in itertools.product(*keys_groups): | ||
| data = dict() | ||
|
|
||
| data[p_token] = self.P_TOKEN | ||
| data[c_token] = self.C_TOKEN | ||
| data[p_detail] = {"cached_tokens": self.P_DETAIL} | ||
| data["total_tokens"] = self.T_TOKEN | ||
|
|
||
| yield data | ||
|
|
||
| def _build_no_details_data(self): | ||
| keys_group = [self.ALIASES["prompt_tokens"], self.ALIASES["completion_tokens"]] | ||
|
|
||
| for p_token, c_token in itertools.product(*keys_group): | ||
| data = dict() | ||
|
|
||
| data[p_token] = self.P_TOKEN | ||
| data[c_token] = self.C_TOKEN | ||
| data["total_tokens"] = self.T_TOKEN | ||
|
|
||
| yield data | ||
|
|
||
| def test_set_usage_attributes(self): | ||
| """Tests _set_usage_attributes""" | ||
| for i, dummy_data in enumerate(self._build_input_data()): | ||
| with self.subTest(scenario=f"Combination {i}", payload=dummy_data): | ||
| mock_span = MagicMock() | ||
| self._set_usage_attributes_method(mock_span, dummy_data) | ||
|
|
||
| mock_span.set_attribute.assert_any_call(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, self.P_TOKEN) | ||
| mock_span.set_attribute.assert_any_call(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, self.C_TOKEN) | ||
| mock_span.set_attribute.assert_any_call(SpanAttributes.LLM_USAGE_TOTAL_TOKENS, self.T_TOKEN) | ||
| mock_span.set_attribute.assert_any_call(SpanAttributes.LLM_USAGE_CACHE_READ_INPUT_TOKENS, self.P_DETAIL) | ||
|
|
||
| def test_set_usage_attributes_no_prompt_tokens_details(self): | ||
| """Tests _set_usage_attributes without prompt token details""" | ||
| for i, dummy_data in enumerate(self._build_no_details_data()): | ||
| with self.subTest(scenario=f"Combination {i}", payload=dummy_data): | ||
| mock_span = MagicMock() | ||
| self._set_usage_attributes_method(mock_span, dummy_data) | ||
|
|
||
| mock_span.set_attribute.assert_any_call(SpanAttributes.LLM_USAGE_PROMPT_TOKENS, self.P_TOKEN) | ||
| mock_span.set_attribute.assert_any_call(SpanAttributes.LLM_USAGE_COMPLETION_TOKENS, self.C_TOKEN) | ||
| mock_span.set_attribute.assert_any_call(SpanAttributes.LLM_USAGE_TOTAL_TOKENS, self.T_TOKEN) | ||
|
|
||
| def test_empty_dict(self): | ||
| """Tests _set_usage_attributes with empty dictionary""" | ||
| mock_span = MagicMock() | ||
| self._set_usage_attributes_method(mock_span, dict()) | ||
|
|
||
| called_keys = [call[0][0] for call in mock_span.set_attribute.call_args_list] | ||
| assert len(called_keys) == 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| import unittest | ||
|
|
||
| from netra.instrumentation.groq.utils import _set_usage_attributes | ||
|
|
||
| from .fixtures.base_provider_utils import BaseProviderUtils | ||
|
|
||
|
|
||
| class TestGroqProviderUtils(unittest.TestCase, BaseProviderUtils): | ||
| _set_usage_attributes_method = staticmethod(_set_usage_attributes) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import unittest | ||
| from unittest.mock import MagicMock | ||
|
|
||
| from netra.processors.span_io_processor import SpanIOProcessor | ||
|
|
||
|
|
||
| class TestSpanIOProcessor(unittest.TestCase): | ||
| """Test cases for `SpanIOProcessor` as per `4.3` in PRD""" | ||
|
|
||
| _USAGE_INPUT_TOKENS = "gen_ai.usage.input_tokens" | ||
| _USAGE_OUTPUT_TOKENS = "gen_ai.usage.output_tokens" | ||
| _USAGE_PROMPT_TOKENS = "gen_ai.usage.prompt_tokens" | ||
| _USAGE_COMPLETION_TOKENS = "gen_ai.usage.completion_tokens" | ||
|
|
||
| def _get_mocks(self, original_value: str, desired_value: str): | ||
| mock_span = MagicMock() | ||
| mock_original_set_attribute = MagicMock() | ||
| mock_span.set_attribute = mock_original_set_attribute | ||
| # creating fake span | ||
|
|
||
| SpanIOProcessor._wrap_set_attribute(mock_span) | ||
| # adding set_attribute method to span | ||
|
|
||
| mock_span.set_attribute(original_value, 100) | ||
| # setting value | ||
|
|
||
| mock_original_set_attribute.assert_called_with(desired_value, 100) | ||
|
|
||
| def test_alias_to_prompt_tokens(self): | ||
| self._get_mocks(self._USAGE_INPUT_TOKENS, self._USAGE_PROMPT_TOKENS) | ||
|
|
||
| def test_alias_to_completion_tokens(self): | ||
| self._get_mocks(self._USAGE_OUTPUT_TOKENS, self._USAGE_COMPLETION_TOKENS) | ||
|
|
||
| def test_pass_through_prompt_tokens(self): | ||
| self._get_mocks(self._USAGE_PROMPT_TOKENS, self._USAGE_PROMPT_TOKENS) | ||
|
|
||
| def test_pass_through_completion_tokens(self): | ||
| self._get_mocks(self._USAGE_COMPLETION_TOKENS, self._USAGE_COMPLETION_TOKENS) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.