Skip to content

Commit 81c792e

Browse files
Fix test cases
1 parent d0db36b commit 81c792e

File tree

2 files changed

+143
-206
lines changed

2 files changed

+143
-206
lines changed

tests/runtime/test_environment_utils.py

Lines changed: 26 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,69 +4,39 @@
44
"""Unit tests for environment_utils module."""
55

66
import os
7-
import unittest
7+
import pytest
88

99
from microsoft_agents_a365.runtime.environment_utils import (
10-
DEVELOPMENT_ENVIRONMENT_NAME,
11-
PROD_OBSERVABILITY_CLUSTER_CATEGORY,
1210
PROD_OBSERVABILITY_SCOPE,
13-
PRODUCTION_ENVIRONMENT_NAME,
1411
get_observability_authentication_scope,
1512
is_development_environment,
1613
)
1714

1815

19-
class TestEnvironmentUtils(unittest.TestCase):
20-
"""Test cases for environment utility functions.
16+
def test_get_observability_authentication_scope():
17+
"""Test get_observability_authentication_scope returns production scope."""
18+
result = get_observability_authentication_scope()
19+
assert result == [PROD_OBSERVABILITY_SCOPE]
2120

22-
Tests: Constants validation, observability scope retrieval, and environment detection logic.
23-
"""
2421

25-
def tearDown(self):
26-
"""Clean up environment variables after each test."""
27-
if "PYTHON_ENVIRONMENT" in os.environ:
28-
del os.environ["PYTHON_ENVIRONMENT"]
29-
30-
def test_constants(self):
31-
"""Test that environment constants have expected values."""
32-
self.assertEqual(PROD_OBSERVABILITY_SCOPE, "https://api.powerplatform.com/.default")
33-
self.assertEqual(PROD_OBSERVABILITY_CLUSTER_CATEGORY, "prod")
34-
self.assertEqual(PRODUCTION_ENVIRONMENT_NAME, "production")
35-
self.assertEqual(DEVELOPMENT_ENVIRONMENT_NAME, "Development")
36-
37-
def test_get_observability_authentication_scope_returns_prod_scope(self):
38-
"""Test that get_observability_authentication_scope returns production scope."""
39-
result = get_observability_authentication_scope()
40-
41-
self.assertIsInstance(result, list)
42-
self.assertEqual(len(result), 1)
43-
self.assertEqual(result[0], PROD_OBSERVABILITY_SCOPE)
44-
45-
def test_is_development_environment_with_no_env_var(self):
46-
"""Test is_development_environment returns False when no environment variable is set."""
47-
if "PYTHON_ENVIRONMENT" in os.environ:
48-
del os.environ["PYTHON_ENVIRONMENT"]
49-
50-
result = is_development_environment()
51-
52-
self.assertFalse(result)
53-
54-
def test_is_development_environment_with_development_env_var(self):
55-
"""Test is_development_environment returns True when PYTHON_ENVIRONMENT is 'Development'."""
56-
os.environ["PYTHON_ENVIRONMENT"] = "Development"
57-
58-
result = is_development_environment()
59-
60-
self.assertTrue(result)
61-
62-
def test_is_development_environment_with_production_env_var(self):
63-
"""Test is_development_environment returns False when PYTHON_ENVIRONMENT is 'production'."""
64-
os.environ["PYTHON_ENVIRONMENT"] = "production"
65-
66-
result = is_development_environment()
67-
68-
self.assertFalse(result)
69-
70-
71-
if __name__ == "__main__":
72-
unittest.main()
22+
@pytest.mark.parametrize(
23+
"env_value,expected",
24+
[
25+
(None, False),
26+
("Development", True),
27+
("production", False),
28+
("staging", False),
29+
],
30+
)
31+
def test_is_development_environment(env_value, expected):
32+
"""Test is_development_environment returns correct value based on PYTHON_ENVIRONMENT."""
33+
if env_value is None:
34+
os.environ.pop("PYTHON_ENVIRONMENT", None)
35+
else:
36+
os.environ["PYTHON_ENVIRONMENT"] = env_value
37+
38+
result = is_development_environment()
39+
assert result == expected
40+
41+
# Cleanup
42+
os.environ.pop("PYTHON_ENVIRONMENT", None)

tests/runtime/test_utility.py

Lines changed: 117 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,126 @@
1-
# Copyright (c) Microsoft. All rights reserved.
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
"""Unit tests for Utility class."""
25

3-
import unittest
46
import uuid
5-
import jwt
7+
from unittest.mock import Mock
68

9+
import jwt
10+
import pytest
711
from microsoft_agents_a365.runtime.utility import Utility
812

913

10-
class TestUtility(unittest.TestCase):
11-
"""Test cases for the Utility class."""
14+
# Fixtures (Mocks and Helpers)
15+
@pytest.fixture
16+
def create_test_jwt():
17+
"""Fixture to create test JWT tokens."""
1218

13-
def setUp(self):
14-
"""Set up test fixtures."""
15-
self.test_app_id = "12345678-1234-1234-1234-123456789abc"
16-
self.test_azp_id = "87654321-4321-4321-4321-cba987654321"
17-
18-
def create_test_jwt(self, claims: dict) -> str:
19-
"""Create a test JWT token with the given claims."""
20-
# Use PyJWT to create a proper JWT token (unsigned for testing)
19+
def _create(claims: dict) -> str:
2120
return jwt.encode(claims, key="", algorithm="none")
2221

23-
def test_get_app_id_from_token_with_none_token(self):
24-
"""Test get_app_id_from_token with None token."""
25-
result = Utility.get_app_id_from_token(None)
26-
self.assertEqual(result, str(uuid.UUID(int=0)))
27-
28-
def test_get_app_id_from_token_with_empty_token(self):
29-
"""Test get_app_id_from_token with empty token."""
30-
result = Utility.get_app_id_from_token("")
31-
self.assertEqual(result, str(uuid.UUID(int=0)))
32-
33-
result = Utility.get_app_id_from_token(" ")
34-
self.assertEqual(result, str(uuid.UUID(int=0)))
35-
36-
def test_get_app_id_from_token_with_appid_claim(self):
37-
"""Test get_app_id_from_token with appid claim."""
38-
token = self.create_test_jwt({"appid": self.test_app_id, "other": "value"})
39-
result = Utility.get_app_id_from_token(token)
40-
self.assertEqual(result, self.test_app_id)
41-
42-
def test_get_app_id_from_token_with_azp_claim(self):
43-
"""Test get_app_id_from_token with azp claim."""
44-
token = self.create_test_jwt({"azp": self.test_azp_id, "other": "value"})
45-
result = Utility.get_app_id_from_token(token)
46-
self.assertEqual(result, self.test_azp_id)
47-
48-
def test_get_app_id_from_token_with_both_claims(self):
49-
"""Test get_app_id_from_token with both appid and azp claims (appid takes precedence)."""
50-
token = self.create_test_jwt({"appid": self.test_app_id, "azp": self.test_azp_id})
51-
result = Utility.get_app_id_from_token(token)
52-
self.assertEqual(result, self.test_app_id)
53-
54-
def test_get_app_id_from_token_without_app_claims(self):
55-
"""Test get_app_id_from_token with token containing no app claims."""
56-
token = self.create_test_jwt({"sub": "user123", "iss": "issuer"})
57-
result = Utility.get_app_id_from_token(token)
58-
self.assertEqual(result, "")
59-
60-
def test_get_app_id_from_token_with_invalid_token(self):
61-
"""Test get_app_id_from_token with invalid token formats."""
62-
# Invalid token format
63-
result = Utility.get_app_id_from_token("invalid.token")
64-
self.assertEqual(result, "")
65-
66-
# Token with only two parts
67-
result = Utility.get_app_id_from_token("header.payload")
68-
self.assertEqual(result, "")
69-
70-
# Token with invalid base64
71-
result = Utility.get_app_id_from_token("invalid.!!!invalid!!!.signature")
72-
self.assertEqual(result, "")
73-
74-
75-
class MockActivity:
76-
"""Mock activity class for testing."""
77-
78-
def __init__(self, is_agentic: bool = False, agentic_id: str = ""):
79-
self._is_agentic = is_agentic
80-
self._agentic_id = agentic_id
81-
82-
def is_agentic_request(self) -> bool:
83-
return self._is_agentic
84-
85-
def get_agentic_instance_id(self) -> str:
86-
return self._agentic_id
87-
88-
89-
class MockContext:
90-
"""Mock context class for testing."""
91-
92-
def __init__(self, activity=None):
93-
self.activity = activity
94-
95-
96-
class TestUtilityResolveAgentIdentity(unittest.TestCase):
97-
"""Test cases for the resolve_agent_identity method."""
98-
99-
def setUp(self):
100-
"""Set up test fixtures."""
101-
self.test_app_id = "token-app-id-123"
102-
self.agentic_id = "agentic-id-456"
103-
104-
# Create a test token with PyJWT
105-
claims = {"appid": self.test_app_id}
106-
self.test_token = jwt.encode(claims, key="", algorithm="none")
107-
108-
def test_resolve_agent_identity_with_agentic_request(self):
109-
"""Test resolve_agent_identity with agentic request."""
110-
activity = MockActivity(is_agentic=True, agentic_id=self.agentic_id)
111-
context = MockContext(activity)
112-
113-
result = Utility.resolve_agent_identity(context, self.test_token)
114-
self.assertEqual(result, self.agentic_id)
115-
116-
def test_resolve_agent_identity_with_non_agentic_request(self):
117-
"""Test resolve_agent_identity with non-agentic request."""
118-
activity = MockActivity(is_agentic=False)
119-
context = MockContext(activity)
120-
121-
result = Utility.resolve_agent_identity(context, self.test_token)
122-
self.assertEqual(result, self.test_app_id)
123-
124-
def test_resolve_agent_identity_with_context_without_activity(self):
125-
"""Test resolve_agent_identity with context that has no activity."""
126-
context = MockContext()
127-
128-
result = Utility.resolve_agent_identity(context, self.test_token)
129-
self.assertEqual(result, self.test_app_id)
130-
131-
def test_resolve_agent_identity_with_none_context(self):
132-
"""Test resolve_agent_identity with None context."""
133-
result = Utility.resolve_agent_identity(None, self.test_token)
134-
self.assertEqual(result, self.test_app_id)
135-
136-
def test_resolve_agent_identity_with_agentic_but_empty_id(self):
137-
"""Test resolve_agent_identity with agentic request but empty agentic ID."""
138-
activity = MockActivity(is_agentic=True, agentic_id="")
139-
context = MockContext(activity)
140-
141-
result = Utility.resolve_agent_identity(context, self.test_token)
142-
self.assertEqual(result, "")
143-
144-
def test_resolve_agent_identity_fallback_on_exception(self):
145-
"""Test resolve_agent_identity falls back to token when context access fails."""
146-
147-
# Create a context that will raise an exception when accessed
148-
class FaultyContext:
149-
@property
150-
def activity(self):
151-
raise RuntimeError("Context access failed")
152-
153-
context = FaultyContext()
154-
result = Utility.resolve_agent_identity(context, self.test_token)
155-
self.assertEqual(result, self.test_app_id)
156-
157-
158-
if __name__ == "__main__":
159-
unittest.main()
22+
return _create
23+
24+
25+
@pytest.fixture
26+
def mock_activity():
27+
"""Fixture to create mock activity."""
28+
29+
def _create(is_agentic=False, agentic_id=""):
30+
activity = Mock()
31+
activity.is_agentic_request.return_value = is_agentic
32+
activity.get_agentic_instance_id.return_value = agentic_id
33+
return activity
34+
35+
return _create
36+
37+
38+
@pytest.fixture
39+
def mock_context():
40+
"""Fixture to create mock context."""
41+
42+
def _create(activity=None):
43+
context = Mock()
44+
context.activity = activity
45+
return context
46+
47+
return _create
48+
49+
50+
# Tests for get_app_id_from_token
51+
@pytest.mark.parametrize(
52+
"token,expected",
53+
[
54+
(None, str(uuid.UUID(int=0))),
55+
("", str(uuid.UUID(int=0))),
56+
(" ", str(uuid.UUID(int=0))),
57+
("invalid.token", ""),
58+
],
59+
)
60+
def test_get_app_id_from_token_invalid(token, expected):
61+
"""Test get_app_id_from_token handles invalid tokens correctly."""
62+
result = Utility.get_app_id_from_token(token)
63+
assert result == expected
64+
65+
66+
@pytest.mark.parametrize(
67+
"claims,expected",
68+
[
69+
({"appid": "test-app-id"}, "test-app-id"),
70+
({"azp": "azp-app-id"}, "azp-app-id"),
71+
({"appid": "appid-value", "azp": "azp-value"}, "appid-value"),
72+
({"sub": "user123"}, ""),
73+
],
74+
)
75+
def test_get_app_id_from_token_valid_tokens(create_test_jwt, claims, expected):
76+
"""Test get_app_id_from_token with valid tokens and various claims."""
77+
token = create_test_jwt(claims)
78+
result = Utility.get_app_id_from_token(token)
79+
assert result == expected
80+
81+
82+
# Tests for resolve_agent_identity
83+
@pytest.mark.parametrize(
84+
"is_agentic,agentic_id,expected",
85+
[
86+
(True, "agentic-id", "agentic-id"),
87+
(True, "", ""),
88+
(False, "", "token-app-id"),
89+
(False, "ignored-id", "token-app-id"),
90+
],
91+
)
92+
def test_resolve_agent_identity_with_context(
93+
create_test_jwt, mock_activity, mock_context, is_agentic, agentic_id, expected
94+
):
95+
"""Test resolve_agent_identity returns correct ID based on context."""
96+
token = create_test_jwt({"appid": "token-app-id"})
97+
activity = mock_activity(is_agentic=is_agentic, agentic_id=agentic_id)
98+
context = mock_context(activity)
99+
100+
result = Utility.resolve_agent_identity(context, token)
101+
assert result == expected
102+
103+
104+
@pytest.mark.parametrize(
105+
"context",
106+
[
107+
None,
108+
Mock(activity=None),
109+
],
110+
)
111+
def test_resolve_agent_identity_fallback(create_test_jwt, context):
112+
"""Test resolve_agent_identity falls back to token when context is invalid."""
113+
token = create_test_jwt({"appid": "token-app-id"})
114+
result = Utility.resolve_agent_identity(context, token)
115+
assert result == "token-app-id"
116+
117+
118+
def test_resolve_agent_identity_exception_handling(create_test_jwt, mock_context):
119+
"""Test resolve_agent_identity falls back to token when activity methods raise exceptions."""
120+
token = create_test_jwt({"appid": "token-app-id"})
121+
activity = Mock()
122+
activity.is_agentic_request.side_effect = AttributeError("Method not available")
123+
context = mock_context(activity)
124+
125+
result = Utility.resolve_agent_identity(context, token)
126+
assert result == "token-app-id"

0 commit comments

Comments
 (0)