Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
cfb8847
basic integration utility
rodrigobr-msft Oct 21, 2025
4d93a46
Integration test suite factory implementation
rodrigobr-msft Oct 23, 2025
be2fb1c
Implementing core models for integration testing
rodrigobr-msft Oct 23, 2025
0d5539a
AutoClient mockup
rodrigobr-msft Oct 23, 2025
bf4c006
Adding runner starter code
rodrigobr-msft Oct 23, 2025
ebe622d
Adding foundational classes
rodrigobr-msft Oct 25, 2025
45678e9
Drafting AgentClient and ResponseClient implementations
rodrigobr-msft Oct 27, 2025
c2b84cb
Spec test
rodrigobr-msft Oct 27, 2025
2816e68
Filling in more implementation details
rodrigobr-msft Oct 27, 2025
2214827
More files
rodrigobr-msft Oct 27, 2025
c90c8e4
Cleaning up implementations
rodrigobr-msft Oct 29, 2025
36f5c3b
Adding expect replies sending method
rodrigobr-msft Oct 29, 2025
dfdd959
Beginning unit tests
rodrigobr-msft Oct 30, 2025
d4828fb
Adding integration decor from sample test cases
rodrigobr-msft Oct 30, 2025
91b3c44
Integration from service url tests
rodrigobr-msft Oct 31, 2025
1eefe44
_handle_conversation implementation for response_client
rodrigobr-msft Oct 31, 2025
a06da9a
AgentClient tests completed
rodrigobr-msft Oct 31, 2025
d36ec7a
Creating response client tests
rodrigobr-msft Nov 3, 2025
c096048
Hosting server for response client
rodrigobr-msft Nov 3, 2025
5451ddf
Response client tests completed
rodrigobr-msft Nov 3, 2025
c2cdd40
Beginning refactor of aiohttp runner
rodrigobr-msft Nov 3, 2025
7d91ef9
Unit test updates
rodrigobr-msft Nov 3, 2025
87610a5
Fixing issues in refactor
rodrigobr-msft Nov 3, 2025
ddfdd0b
Fixed TestIntegrationFromSample unit test
rodrigobr-msft Nov 3, 2025
dd0a87d
Another commit
rodrigobr-msft Nov 3, 2025
6a4e8ef
Reorganizing files
rodrigobr-msft Nov 3, 2025
7793790
Completed TestIntegrationFromServiceUrl unit tests
rodrigobr-msft Nov 3, 2025
3ebbd44
Reformatting with black
rodrigobr-msft Nov 3, 2025
a6681bf
Quickstart integration test beginning
rodrigobr-msft Nov 3, 2025
1a7264b
Draft of quickstart sample setup
rodrigobr-msft Nov 3, 2025
9ba4a43
Environment config connection
rodrigobr-msft Nov 3, 2025
fab4368
Renaming messaging endpoint to agent url
rodrigobr-msft Nov 4, 2025
a111155
Removing unnecessary files
rodrigobr-msft Nov 4, 2025
a2a1092
Fixing agent client payload sending
rodrigobr-msft Nov 4, 2025
ae8a286
First successful integration test
rodrigobr-msft Nov 4, 2025
9a5a6a8
Beginning foundational test cases
rodrigobr-msft Nov 4, 2025
aad011a
TypingIndicator test
rodrigobr-msft Nov 4, 2025
be0032a
Adding more test cases
rodrigobr-msft Nov 4, 2025
e3f4324
More foundational integration test cases
rodrigobr-msft Nov 4, 2025
a077eed
Reorganizing testing tools into package
rodrigobr-msft Nov 5, 2025
49161c3
Polished the testing framework package
rodrigobr-msft Nov 6, 2025
69d68d4
Adding verbose logging for results with benchmark tool
rodrigobr-msft Nov 6, 2025
3dc3efa
General cleanup
rodrigobr-msft Nov 6, 2025
054a3a2
Adding README
rodrigobr-msft Nov 6, 2025
8a5f22e
Revising README
rodrigobr-msft Nov 6, 2025
4b7c673
Formatting
rodrigobr-msft Nov 6, 2025
01f8f5a
Addressing PR comments
rodrigobr-msft Nov 6, 2025
9cccc1f
Merge branch 'main' of https://github.com/microsoft/Agents-for-python…
rodrigobr-msft Nov 6, 2025
8f87aff
Removing unused import
rodrigobr-msft Nov 6, 2025
e742e00
Update dev/microsoft-agents-testing/microsoft_agents/testing/sdk_conf…
rodrigobr-msft Nov 6, 2025
a6e305a
Update dev/microsoft-agents-testing/pyproject.toml
rodrigobr-msft Nov 6, 2025
c3877a3
Update dev/microsoft-agents-testing/microsoft_agents/testing/auth/gen…
rodrigobr-msft Nov 6, 2025
fb5b76d
Update dev/microsoft-agents-testing/microsoft_agents/testing/integrat…
rodrigobr-msft Nov 6, 2025
5eb9bfb
Removing unused code
rodrigobr-msft Nov 6, 2025
81b5d6b
Merge branch 'users/robrandao/integration' of https://github.com/micr…
rodrigobr-msft Nov 6, 2025
e451459
Adding field assertion helpers
rodrigobr-msft Nov 6, 2025
f241df8
Implementing field assertion types
rodrigobr-msft Nov 6, 2025
cb3c6aa
Adding data driven test foundation
rodrigobr-msft Nov 6, 2025
b8f3304
Separating assertions from checkers
rodrigobr-msft Nov 6, 2025
42b4ea1
Adjusting return values for check_activity with refactor
rodrigobr-msft Nov 6, 2025
2f79824
Fixing package name in pyproject.toml
rodrigobr-msft Nov 12, 2025
cfded79
Assertion test cases
rodrigobr-msft Nov 12, 2025
b6618b2
_parse_assertion unit tests
rodrigobr-msft Nov 12, 2025
1e8f19e
More assertion tests and fixes to data normalization logic
rodrigobr-msft Nov 12, 2025
d9eb5fa
Fixing more test cases with newest refactor
rodrigobr-msft Nov 12, 2025
f02b875
Fixing merge conflicts
rodrigobr-msft Nov 13, 2025
57b87eb
assert_activity tests
rodrigobr-msft Nov 13, 2025
6925093
Reorganizing tests
rodrigobr-msft Nov 13, 2025
6d55b29
Copyright comments
rodrigobr-msft Nov 13, 2025
6866f5d
DDT implementation outline
rodrigobr-msft Nov 13, 2025
1db2bf5
DataDrivenTest class
rodrigobr-msft Nov 13, 2025
e44a2da
select_activity implementation for assertions
rodrigobr-msft Nov 13, 2025
1cf561b
inverted assertions for quantifiers
rodrigobr-msft Nov 13, 2025
e651f92
ActivityAssertion class implementation
rodrigobr-msft Nov 13, 2025
ed7f2f1
DataDrivenTest implementation
rodrigobr-msft Nov 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
25 changes: 25 additions & 0 deletions dev/integration/data_driven_tests/basic_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
parent: ./defaults.yaml
description: A basic data driven test example
defaults:
input:
sleep:
assertion:
test:
- type: input
activity:
type: message
text: "Hello, World!"

- type: sleep
duration: 1

- type: assertion
quantifier: ONE
selector:
index: -1
quantifier: ONE
activity:
type: message
activity:
type: message
text: "Hello, World!"
10 changes: 10 additions & 0 deletions dev/integration/data_driven_tests/defaults.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defaults:
all:
channel_id: "test_channel"
service_url: "http://localhost:3978"
locale: "en-US"
conversation_id: "test_conversation"
input:
user_id: "test_user"
output:
user_id: "test_bot"
2 changes: 2 additions & 0 deletions dev/integration/integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Microsoft 365 Agents SDK for Python Integration Testing Framework

Empty file.
Empty file.
16 changes: 16 additions & 0 deletions dev/integration/integration/integration/foundational/_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import json

from microsoft_agents.activity import Activity


def load_activity(channel: str, name: str) -> Activity:

with open(
"./dev/integration/src/tests/integration/foundational/activities/{}/{}.json".format(
channel, name
),
"r",
) as f:
activity = json.load(f)

return Activity.model_validate(activity)
141 changes: 141 additions & 0 deletions dev/integration/integration/integration/foundational/test_suite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import json
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Syntax Error (in Python 3).

Copilot uses AI. Check for mistakes.
import pytest
import asyncio

from microsoft_agents.activity import (
ActivityTypes,
)

from src.core import integration, IntegrationFixtures, AiohttpEnvironment
from src.samples import QuickstartSample

from ._common import load_activity

DIRECTLINE = "directline"

@integration()
class TestFoundation(IntegrationFixtures):

def load_activity(self, activity_name) -> Activity:
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import statement. The Activity class is used on line 19 but is not imported in this file.

Copilot uses AI. Check for mistakes.
return load_activity(DIRECTLINE, activity_name)

@pytest.mark.asyncio
async def test__send_activity__sends_hello_world__returns_hello_world(self, agent_client):
activity = load_activity(DIRECTLINE, "hello_world.json")
result = await agent_client.send_activity(activity)
assert result is not None
last = result[-1]
assert last.type == ActivityTypes.message
assert last.text.lower() == "you said: {activity.text}".lower()

@pytest.mark.asyncio
async def test__send_invoke__send_basic_invoke_activity__receive_invoke_response(self, agent_client):
activity = load_activity(DIRECTLINE, "basic_invoke.json")
result = await agent_client.send_activity(activity)
assert result
data = json.loads(result)
message = data.get("message", {})
assert "Invoke received." in message
assert "data" in data
assert data["parameters"] and len(data["parameters"]) > 0
assert "hi" in data["value"]

@pytest.mark.asyncio
async def test__send_activity__sends_message_activity_to_ac_submit__return_valid_response(self, agent_client):
activity = load_activity(DIRECTLINE, "ac_submit.json")
result = await agent_client.send_activity(activity)
assert result is not None
last = result[-1]
assert last.type == ActivityTypes.message
assert "doStuff" in last.text
assert "Action.Submit" in last.text
assert "hello" in last.text

@pytest.mark.asyncio
async def test__send_invoke_sends_invoke_activity_to_ac_execute__returns_valid_adaptive_card_invoke_response(self, agent_client):
activity = load_activity(DIRECTLINE, "ac_execute.json")
result = await agent_client.send_invoke(activity)

result = json.loads(result)

assert result.status == 200
assert result.value

assert "application/vnd.microsoft.card.adaptive" in result.type

activity_data = json.loads(activity.value)
assert activity_data.get("action")
user_text = activity_data.get("usertext")
assert user_text in result.value

@pytest.mark.asyncio
async def test__send_activity_sends_text__returns_poem(self, agent_client):
pass

@pytest.mark.asyncio
async def test__send_expected_replies_activity__sends_text__returns_poem(self, agent_client):
activity = self.load_activity("expected_replies.json")
result = await agent_client.send_expected_replies(activity)
last = result[-1]
assert last.type == ActivityTypes.message
assert "Apollo" in last.text
assert "\n" in last.text

@pytest.mark.asyncio
async def test__send_invoke__query_link__returns_text(self, agent_client):
activity = self.load_activity("query_link.json")
result = await agent_client.send_invoke(activity)
pass # TODO

@pytest.mark.asyncio
async def test__send_invoke__select_item__receive_item(self, agent_client):
activity = self.load_activity("select_item.json")
result = await agent_client.send_invoke(activity)
pass # TODO

@pytest.mark.asyncio
async def test__send_activity__conversation_update__returns_welcome_message(self, agent_client):
activity = self.load_activity("conversation_update.json")
result = await agent_client.send_activity(activity)
last = result[-1]
assert "Hello and Welcome!" in last.text

@pytest.mark.asyncio
async def test__send_activity__send_heart_message_reaction__returns_message_reaction_heart(self, agent_client):
activity = self.load_activity("message_reaction_heart.json")
result = await agent_client.send_activity(activity)
last = result[-1]
assert last.type == ActivityTypes.message
assert "Message Reaction Added: heart" in last.text

@pytest.mark.asyncio
async def test__send_activity__remove_heart_message_reaction__returns_message_reaction_heart(self, agent_client):
activity = self.load_activity
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete code on line 113. The expression activity = self.load_activity is missing a function call - it should be self.load_activity("some_file.json") to actually load an activity.

Suggested change
activity = self.load_activity
activity = self.load_activity("message_reaction_heart.json")

Copilot uses AI. Check for mistakes.
result = await agent_client.send_activity(activity)
last = result[-1]
assert last.type == ActivityTypes.message
assert "Message Reaction Removed: heart" in last.text

@pytest.mark.asyncio
async def test__send_expected_replies_activity__send_seattle_today_weather__returns_weather(self, agent_client):
activity = self.load_activity("expected_replies_seattle_weather.json")
result = await agent_client.send_expected_replies(activity)
last = result[-1]
assert last.type == ActivityTypes.message
assert last.attachments and len(last.attachments) > 0

adaptive_card = last.attachments.first()
assert adaptive_card
assert "application/vnd.microsoft.card.adaptive" == adaptive_card.content_type
assert adaptive_card.content

assert \
"�" in adaptive_card.content or \
"\\u00B0" in adaptive_card.content or \
f"Missing temperature inside adaptive card: {adaptive_card.content}" in adaptive_card.content
Comment on lines +132 to +135
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion message on lines 132-135 is malformed. The assertion logic appears to be checking if a degree symbol exists in the content, but the error message itself is embedded within the OR conditions using the in operator, which will always evaluate to False. The message should be separate from the condition being asserted.

Suggested change
assert \
"�" in adaptive_card.content or \
"\\u00B0" in adaptive_card.content or \
f"Missing temperature inside adaptive card: {adaptive_card.content}" in adaptive_card.content
assert (
"�" in adaptive_card.content or
"\\u00B0" in adaptive_card.content
), f"Missing temperature inside adaptive card: {adaptive_card.content}"

Copilot uses AI. Check for mistakes.

@pytest.mark.asyncio
async def test__send_activity__simulate_message_loop__expect_question_about_time_and_returns_weather(self, agent_client):
activities = self.load_activity("message_loop_1.json")
fresult = await agent_client.send_activity(activities[0])
assert
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete test method. The test ends abruptly at line 141 with assert keyword but no condition or expression to assert, resulting in a syntax error.

Suggested change
assert
pytest.skip("Test not yet implemented")

Copilot uses AI. Check for mistakes.
21 changes: 21 additions & 0 deletions dev/integration/integration/integration/test_quickstart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# import pytest
# import asyncio

# from src.core import IntegrationFixtures, AiohttpEnvironment
# from src.samples import QuickstartSample

# class TestQuickstart(Integration):
# _sample_cls = QuickstartSample
# _environment_cls = AiohttpEnvironment

# @pytest.mark.asyncio
# async def test_welcome_message(self, agent_client, response_client):
# res = await agent_client.send_expect_replies("hi")
# await asyncio.sleep(1) # Wait for processing
# responses = await response_client.pop()

# assert len(responses) == 0

# first_non_typing = next((r for r in res if r.type != "typing"), None)
# assert first_non_typing is not None
# assert first_non_typing.text == "you said: hi"
1 change: 1 addition & 0 deletions dev/integration/integration/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aioresponses
8 changes: 8 additions & 0 deletions dev/integration/test_basics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from microsoft_agents.testing import DataDrivenTester


Comment on lines +1 to +3
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import statement. The DataDrivenTester class is imported and used on lines 1 and 4, but this class doesn't appear to be exported from microsoft_agents.testing based on the __init__.py file shown in the PR.

Suggested change
from microsoft_agents.testing import DataDrivenTester
# Minimal DataDrivenTester base class definition
class DataDrivenTester:
def _run_data_driven_test(self, filename):
# Placeholder implementation
pass

Copilot uses AI. Check for mistakes.
class TestBasics(DataDrivenTester):
_input_dir = "./data_driven_tests"

Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undefined method _run_data_driven_test. The method is called on line 8 but is not defined in the shown code or in the DataDrivenTester base class (which doesn't appear to exist based on the imports shown).

Suggested change
def _run_data_driven_test(self, filename):
# Stub implementation: print the filename
print(f"Running data driven test with {filename}")

Copilot uses AI. Check for mistakes.
def test(self):
self._run_data_driven_test("input_file.json")
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from .sdk_config import SDKConfig

from .auth import generate_token, generate_token_from_config
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from .activity_assertion import ActivityAssertion
from .assertions import (
assert_activity,
assert_field,
)
from .check_activity import check_activity
from .check_field import check_field
from .type_defs import FieldAssertionType, SelectorQuantifier, AssertionQuantifier

__all__ = [
"assert_activity",
"assert_field",
"check_activity",
"check_field",
"FieldAssertionType",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from typing import Optional
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing copyright header. This file should include the standard copyright and license header like other files in the project.

Copilot uses AI. Check for mistakes.

from microsoft_agents.activity import Activity

from .select_activity import select_activities
from .check_activity import check_activity_verbose
from .type_defs import AssertionQuantifier, AssertionErrorData


class ActivityAssertion:

def __init__(self, config: dict) -> None:
"""Initializes the ActivityAssertion with the given configuration.

:param config: The configuration dictionary containing quantifier, selector, and assertion.
"""
quantifier_name = config.get("quantifier", AssertionQuantifier.ALL)
self._quantifier = AssertionQuantifier(quantifier_name)

self._selector = config.get("selector", {})
self._assertion = config.get("assertion", {})

@staticmethod
def _combine_assertion_errors(errors: list[AssertionErrorData]) -> str:
"""Combines multiple assertion errors into a single string representation.

:param errors: The list of assertion errors to be combined.
:return: A string representation of the combined assertion errors.
"""
return "\n".join(str(error) for error in errors)

def check(self, activities: list[Activity]) -> tuple[bool, Optional[str]]:
"""Asserts that the given activities match the assertion criteria.

:param activities: The list of activities to be tested.
:return: A tuple containing a boolean indicating if the assertion passed and an optional error message.
"""

activities = select_activities(activities, self._selector)

count = 0
for activity in activities:
res, assertion_error_data = check_activity_verbose(
activity, self._assertion
)
if self._quantifier == AssertionQuantifier.ALL and not res:
return (
False,
f"Activity did not match the assertion: {activity}\nError: {assertion_error_data}",
)
if self._quantifier == AssertionQuantifier.NONE and res:
return (
False,
f"Activity matched the assertion when none were expected: {activity}",
)
count += 1
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect logic on line 56. The count variable is incremented regardless of whether the assertion passes or fails. This should only increment when assertions pass (for quantifiers like ONE or ANY), otherwise the count will be incorrect.

Suggested change
count += 1
if res:
count += 1

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable count. The variable is incremented on line 56 but is only checked for the ONE quantifier case on line 59. For the ALL and NONE quantifiers, the count is never used, making the increment on line 56 unnecessary in those cases.

Suggested change
count += 1
if self._quantifier == AssertionQuantifier.ONE:
count += 1

Copilot uses AI. Check for mistakes.

passes = True
if self._quantifier == AssertionQuantifier.ONE and count != 1:
return (
False,
f"Expected exactly one activity to match the assertion, but found {count}.",
)

return passes, None
Comment on lines +32 to +65
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing implementation for AssertionQuantifier.ANY quantifier. The code handles ALL, NONE, and ONE quantifiers, but doesn't implement logic for the ANY quantifier which is defined in the AssertionQuantifier enum (line 42 in type_defs.py).

Copilot uses AI. Check for mistakes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from typing import Any

from microsoft_agents.activity import Activity

from .type_defs import FieldAssertionType, AssertionQuantifier
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'AssertionQuantifier' is not used.

Suggested change
from .type_defs import FieldAssertionType, AssertionQuantifier
from .type_defs import FieldAssertionType

Copilot uses AI. Check for mistakes.
from .check_activity import check_activity_verbose
from .check_field import check_field_verbose


def assert_field(
actual_value: Any, assertion: Any, assertion_type: FieldAssertionType
) -> None:
"""Asserts that a specific field in the target matches the baseline.

:param key_in_baseline: The key of the field to be tested.
:param target: The target dictionary containing the actual values.
:param assertion: The baseline dictionary containing the expected values.
"""
res, assertion_error_message = check_field_verbose(
actual_value, assertion, assertion_type
)
assert res, assertion_error_message


def assert_activity(activity: Activity, assertion: Activity | dict) -> None:
"""Asserts that the given activity matches the baseline activity.

:param activity: The activity to be tested.
:param assertion: The baseline activity or a dictionary representing the expected activity data.
"""
res, assertion_error_data = check_activity_verbose(activity, assertion)
assert res, str(assertion_error_data)


def assert_activities(activities: list[Activity], assertion_config: dict) -> None:
"""Asserts that the given list of activities matches the baseline activities.

:param activities: The list of activities to be tested.
:param assertion: The baseline dictionary representing the expected activities data.
"""

quantifier = assertion_config.get(
"quantifier",
)
selector = assertion_config.get("selector", {})

for activity in activities:
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable selector is not used.

Suggested change
for activity in activities:
def matches_selector(activity, selector):
# Assume activity is either an object with attributes or a dict
for key, value in selector.items():
# Try attribute first, then dict key
if hasattr(activity, key):
if getattr(activity, key) != value:
return False
elif isinstance(activity, dict):
if activity.get(key) != value:
return False
else:
return False
return True
filtered_activities = [
activity for activity in activities if matches_selector(activity, selector)
] if selector else activities
for activity in filtered_activities:

Copilot uses AI. Check for mistakes.
res, assertion_error_data = check_activity_verbose(activity, assertion)
assert res, str(assertion_error_data)
Comment on lines +49 to +52
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quantifier variable is retrieved on lines 45-47 but never used in the function. The function iterates over all activities and checks them against assertion (which should be from assertion_config), but doesn't apply any quantifier logic. This appears to be incomplete implementation.

Suggested change
for activity in activities:
res, assertion_error_data = check_activity_verbose(activity, assertion)
assert res, str(assertion_error_data)
assertion = assertion_config.get("assertion", {})
match_results = []
error_messages = []
for activity in activities:
res, assertion_error_data = check_activity_verbose(activity, assertion)
match_results.append(res)
if not res:
error_messages.append(str(assertion_error_data))
# Default quantifier is "all"
if quantifier is None or quantifier == "all":
if not all(match_results):
raise AssertionError(
f"Not all activities matched assertion. Errors: {error_messages}"
)
elif quantifier == "any":
if not any(match_results):
raise AssertionError(
f"No activities matched assertion. Errors: {error_messages}"
)
elif quantifier == "none":
if any(match_results):
raise AssertionError(
f"Some activities matched assertion when none were expected."
)
elif isinstance(quantifier, int):
count = match_results.count(True)
if count != quantifier:
raise AssertionError(
f"Expected exactly {quantifier} activities to match assertion, but got {count}. Errors: {error_messages}"
)
else:
raise ValueError(f"Unknown quantifier: {quantifier}")

Copilot uses AI. Check for mistakes.
Loading
Loading