Skip to content

Commit 682b8e1

Browse files
committed
test: add stream delivery integ tests and TESTING.md
1 parent 98100d7 commit 682b8e1

3 files changed

Lines changed: 134 additions & 0 deletions

File tree

.github/workflows/integration-testing.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ jobs:
117117
timeout: 10
118118
extra-deps: ""
119119
ignore: ""
120+
# TODO: expand to full tests_integ/memory once test stability is addressed
121+
- group: memory
122+
path: tests_integ/memory/test_memory_client.py -k "TestMemoryClient"
123+
timeout: 10
124+
extra-deps: ""
125+
ignore: ""
120126
- group: evaluation
121127
path: tests_integ/evaluation
122128
timeout: 15
@@ -151,6 +157,8 @@ jobs:
151157
env:
152158
AWS_REGION: us-west-2
153159
PYTHONUNBUFFERED: 1
160+
MEMORY_KINESIS_ARN: ${{ secrets.MEMORY_KINESIS_ARN }}
161+
MEMORY_ROLE_ARN: ${{ secrets.MEMORY_ROLE_ARN }}
154162
id: tests
155163
timeout-minutes: ${{ matrix.timeout }}
156164
run: |

TESTING.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Integration Tests
2+
3+
See [CONTRIBUTING.md](CONTRIBUTING.md) for initial setup (Python, `uv sync`, etc).
4+
5+
All integration tests require AWS credentials with `bedrock-agentcore:*` and `bedrock-agentcore-control:*` permissions.
6+
7+
```bash
8+
export AWS_PROFILE=<your-profile>
9+
export BEDROCK_TEST_REGION=us-west-2
10+
```
11+
12+
## Runtime
13+
14+
```bash
15+
uv run pytest tests_integ/runtime -xvs --log-cli-level=INFO
16+
```
17+
18+
## Memory
19+
20+
```bash
21+
# Control plane (CRUD on memories/strategies, 5-10 min due to provisioning)
22+
uv run pytest tests_integ/memory/test_controlplane.py -xvs -k "integration"
23+
24+
# Stream delivery (requires env vars below, fails if unset)
25+
export MEMORY_KINESIS_ARN=<Kinesis Data Stream ARN>
26+
export MEMORY_ROLE_ARN=<IAM role ARN trusted by bedrock-agentcore.amazonaws.com with kinesis:PutRecord/PutRecords permissions>
27+
uv run pytest tests_integ/memory/test_memory_client.py -xvs -k "TestMemoryClient"
28+
29+
# Client and developer experience
30+
uv run pytest tests_integ/memory/test_memory_client.py -xvs
31+
uv run pytest tests_integ/memory/test_devex.py -xvs
32+
```
33+
34+
## Identity
35+
36+
```bash
37+
uv run pytest tests_integ/identity -xvs
38+
```
39+
40+
## Tools (Code Interpreter, Browser)
41+
42+
```bash
43+
uv run pytest tests_integ/tools -xvs
44+
```
45+
46+
## CI
47+
48+
Integration tests run via `integration-testing.yml` on PRs to main. The workflow runs runtime, memory (stream delivery only), and evaluation tests in parallel.
49+
50+
Stream delivery tests fail in CI unless `MEMORY_KINESIS_ARN` and `MEMORY_ROLE_ARN` secrets are configured on the repo. Other memory integration tests are not yet run in CI due to provisioning times and flaky LLM-dependent assertions — CI support is planned once test stability is addressed.
51+
52+
## Conventions
53+
54+
- Each test file should map 1:1 to a source code file when possible.
55+
- Each feature area should correspond to a single test class named after the class under test (e.g. `TestMemoryClient`).
56+
- Expensive resources (e.g. memories) should be created the minimum number of times, ideally once in `setup_class`.
57+
- All resources created during tests must be cleaned up in `teardown_class`.
58+
- Use `self.__class__.memory_ids` to track resources for cleanup across test methods.

tests_integ/memory/test_memory_client.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import logging
44
import os
55
import time
6+
import uuid
67
from datetime import datetime
78

9+
import pytest
10+
811
from bedrock_agentcore.memory import MemoryClient
912

1013
# Use INFO level logging for cleaner output
@@ -408,5 +411,70 @@ def main():
408411
logger.error("Failed to delete test memory: %s", e)
409412

410413

414+
@pytest.mark.integration
415+
class TestMemoryClient:
416+
"""Integration tests for streamDeliveryResources on MemoryClient."""
417+
418+
@classmethod
419+
def setup_class(cls):
420+
cls.kinesis_stream_arn = os.environ.get("MEMORY_KINESIS_ARN")
421+
cls.execution_role_arn = os.environ.get("MEMORY_ROLE_ARN")
422+
423+
if not cls.kinesis_stream_arn or not cls.execution_role_arn:
424+
pytest.fail("MEMORY_KINESIS_ARN and MEMORY_ROLE_ARN must be set")
425+
426+
cls.region = os.environ.get("BEDROCK_TEST_REGION", "us-west-2")
427+
cls.client = MemoryClient(region_name=cls.region)
428+
cls.test_prefix = f"test_stream_{int(time.time())}"
429+
cls.memory_ids = []
430+
431+
@classmethod
432+
def teardown_class(cls):
433+
for memory_id in cls.memory_ids:
434+
try:
435+
cls.client.delete_memory(memory_id)
436+
except Exception as e:
437+
print(f"Failed to delete memory {memory_id}: {e}")
438+
439+
def _make_delivery_config(self, level="FULL_CONTENT"):
440+
return {
441+
"resources": [
442+
{
443+
"kinesis": {
444+
"dataStreamArn": self.kinesis_stream_arn,
445+
"contentConfigurations": [{"type": "MEMORY_RECORDS", "level": level}],
446+
}
447+
}
448+
]
449+
}
450+
451+
def test_stream_delivery_create_and_update(self):
452+
"""Create memory with FULL_CONTENT delivery, update to METADATA_ONLY via passthrough."""
453+
delivery_config = self._make_delivery_config("FULL_CONTENT")
454+
455+
memory = self.client.create_memory_and_wait(
456+
name=f"{self.test_prefix}_stream",
457+
strategies=[],
458+
memory_execution_role_arn=self.execution_role_arn,
459+
stream_delivery_resources=delivery_config,
460+
)
461+
462+
memory_id = memory["id"]
463+
self.__class__.memory_ids.append(memory_id)
464+
465+
assert memory["streamDeliveryResources"] == delivery_config
466+
467+
# Test update via MemoryClient.__getattr__ passthrough to boto3 client.
468+
# Uses camelCase params because the passthrough forwards directly to boto3
469+
# without the snake_case translation that explicit SDK methods provide.
470+
updated_config = self._make_delivery_config("METADATA_ONLY")
471+
response = self.client.update_memory(
472+
memoryId=memory_id,
473+
clientToken=str(uuid.uuid4()),
474+
streamDeliveryResources=updated_config,
475+
)
476+
assert response["memory"]["streamDeliveryResources"] == updated_config
477+
478+
411479
if __name__ == "__main__":
412480
main()

0 commit comments

Comments
 (0)