From 49d21bf7a81635b6c36147cc122bad4b4909e2a5 Mon Sep 17 00:00:00 2001 From: Didier Durand Date: Sun, 14 Dec 2025 07:12:40 +0100 Subject: [PATCH 1/5] test: adding tests for id_generator.py --- tests/server/tasks/test_id_generator.py | 112 ++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 tests/server/tasks/test_id_generator.py diff --git a/tests/server/tasks/test_id_generator.py b/tests/server/tasks/test_id_generator.py new file mode 100644 index 00000000..b3450ae3 --- /dev/null +++ b/tests/server/tasks/test_id_generator.py @@ -0,0 +1,112 @@ +import uuid + +import pytest + +from pydantic import ValidationError + +from a2a.server.id_generator import ( + IDGenerator, + IDGeneratorContext, + UUIDGenerator, +) + + +class TestIDGeneratorContext: + """Tests for IDGeneratorContext.""" + + def test_context_creation_with_all_fields(self): + """Test creating context with all fields populated.""" + context = IDGeneratorContext( + task_id='task_123', context_id='context_456' + ) + assert context.task_id == 'task_123' + assert context.context_id == 'context_456' + + def test_context_creation_with_defaults(self): + """Test creating context with default None values.""" + context = IDGeneratorContext() + assert context.task_id is None + assert context.context_id is None + + def test_context_creation_with_partial_fields(self): + """Test creating context with only some fields populated.""" + context = IDGeneratorContext(task_id='task_123') + assert context.task_id == 'task_123' + assert context.context_id is None + context = IDGeneratorContext(context_id='context_456') + assert context.task_id is None + assert context.context_id == 'context_456' + + def test_context_mutability(self): + """Test that context fields can be updated (Pydantic models are mutable by default).""" + context = IDGeneratorContext(task_id='task_123') + context.task_id = 'task_456' + assert context.task_id == 'task_456' + + def test_context_validation(self): + """Test that context raises validation error for invalid types.""" + with pytest.raises(ValidationError): + IDGeneratorContext(task_id={'not': 'a string'}) + + class TestIDGenerator: + """Tests for IDGenerator abstract base class.""" + + def test_cannot_instantiate_abstract_class(self): + """Test that IDGenerator cannot be instantiated directly.""" + with pytest.raises(TypeError): + IDGenerator() + + def test_subclass_must_implement_generate(self): + """Test that subclasses must implement the generate method.""" + + class IncompleteGenerator(IDGenerator): + pass + + with pytest.raises(TypeError): + IncompleteGenerator() + + def test_valid_subclass_implementation(self): + """Test that a valid subclass can be instantiated.""" + + class ValidGenerator(IDGenerator): # pylint: disable=C0115,R0903 + def generate(self, context: IDGeneratorContext) -> str: + return 'test_id' + + generator = ValidGenerator() + assert generator.generate(IDGeneratorContext()) == 'test_id' + + +class TestUUIDGenerator: + """Tests for UUIDGenerator implementation.""" + + def test_generate_returns_string(self): + """Test that generate returns a valid v4 UUID string.""" + generator = UUIDGenerator() + context = IDGeneratorContext() + result = generator.generate(context) + assert isinstance(result, str) + parsed_uuid = uuid.UUID(result) + assert parsed_uuid.version == 4 + + def test_generate_produces_unique_ids(self): + """Test that multiple calls produce unique IDs.""" + generator = UUIDGenerator() + context = IDGeneratorContext() + ids = [generator.generate(context) for _ in range(100)] + # All IDs should be unique + assert len(ids) == len(set(ids)) + + def test_generate_with_none_context(self): + """Test that generate works with context set to None.""" + generator = UUIDGenerator() + result = generator.generate(None) + assert isinstance(result, str) + uuid.UUID(result) + + def test_generate_with_empty_context(self): + """Test that generate works with an empty context.""" + generator = UUIDGenerator() + context = IDGeneratorContext() + result = generator.generate(context) + assert isinstance(result, str) + uuid.UUID(result) From daa6a7fff18e2213f8e49b6d1ef0c5bfb0cee7cb Mon Sep 17 00:00:00 2001 From: Didier Durand <2927957+didier-durand@users.noreply.github.com> Date: Sun, 14 Dec 2025 07:17:27 +0100 Subject: [PATCH 2/5] Update tests/server/tasks/test_id_generator.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- tests/server/tasks/test_id_generator.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/server/tasks/test_id_generator.py b/tests/server/tasks/test_id_generator.py index b3450ae3..72c72702 100644 --- a/tests/server/tasks/test_id_generator.py +++ b/tests/server/tasks/test_id_generator.py @@ -96,17 +96,20 @@ def test_generate_produces_unique_ids(self): # All IDs should be unique assert len(ids) == len(set(ids)) - def test_generate_with_none_context(self): - """Test that generate works with context set to None.""" + @pytest.mark.parametrize( + 'context_arg', + [ + None, + IDGeneratorContext(), + ], + ids=[ + 'none_context', + 'empty_context', + ], + ) + def test_generate_works_with_various_contexts(self, context_arg): + """Test that generate works with various context inputs.""" generator = UUIDGenerator() - result = generator.generate(None) - assert isinstance(result, str) - uuid.UUID(result) - - def test_generate_with_empty_context(self): - """Test that generate works with an empty context.""" - generator = UUIDGenerator() - context = IDGeneratorContext() - result = generator.generate(context) + result = generator.generate(context_arg) assert isinstance(result, str) uuid.UUID(result) From b027bd62f314ca98b0dd51bb90e70ce88fe15aee Mon Sep 17 00:00:00 2001 From: Didier Durand <2927957+didier-durand@users.noreply.github.com> Date: Sun, 14 Dec 2025 07:17:39 +0100 Subject: [PATCH 3/5] Update tests/server/tasks/test_id_generator.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- tests/server/tasks/test_id_generator.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/server/tasks/test_id_generator.py b/tests/server/tasks/test_id_generator.py index 72c72702..da7dc839 100644 --- a/tests/server/tasks/test_id_generator.py +++ b/tests/server/tasks/test_id_generator.py @@ -28,14 +28,20 @@ def test_context_creation_with_defaults(self): assert context.task_id is None assert context.context_id is None - def test_context_creation_with_partial_fields(self): + @pytest.mark.parametrize( + 'kwargs, expected_task_id, expected_context_id', + [ + ({'task_id': 'task_123'}, 'task_123', None), + ({'context_id': 'context_456'}, None, 'context_456'), + ], + ) + def test_context_creation_with_partial_fields( + self, kwargs, expected_task_id, expected_context_id + ): """Test creating context with only some fields populated.""" - context = IDGeneratorContext(task_id='task_123') - assert context.task_id == 'task_123' - assert context.context_id is None - context = IDGeneratorContext(context_id='context_456') - assert context.task_id is None - assert context.context_id == 'context_456' + context = IDGeneratorContext(**kwargs) + assert context.task_id == expected_task_id + assert context.context_id == expected_context_id def test_context_mutability(self): """Test that context fields can be updated (Pydantic models are mutable by default).""" From c4a4864f4075c3413526c2a07928aef1316dd7cd Mon Sep 17 00:00:00 2001 From: Didier Durand Date: Sun, 14 Dec 2025 07:26:15 +0100 Subject: [PATCH 4/5] test: implementing fixtures to simplify test code --- tests/server/tasks/test_id_generator.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/server/tasks/test_id_generator.py b/tests/server/tasks/test_id_generator.py index da7dc839..d6428d36 100644 --- a/tests/server/tasks/test_id_generator.py +++ b/tests/server/tasks/test_id_generator.py @@ -82,22 +82,30 @@ def generate(self, context: IDGeneratorContext) -> str: assert generator.generate(IDGeneratorContext()) == 'test_id' +@pytest.fixture +def generator(): + """Returns a UUIDGenerator instance.""" + return UUIDGenerator() + + +@pytest.fixture +def context(): + """Returns a IDGeneratorContext instance.""" + return IDGeneratorContext() + + class TestUUIDGenerator: """Tests for UUIDGenerator implementation.""" - def test_generate_returns_string(self): + def test_generate_returns_string(self, generator, context): """Test that generate returns a valid v4 UUID string.""" - generator = UUIDGenerator() - context = IDGeneratorContext() result = generator.generate(context) assert isinstance(result, str) parsed_uuid = uuid.UUID(result) assert parsed_uuid.version == 4 - def test_generate_produces_unique_ids(self): + def test_generate_produces_unique_ids(self, generator, context): """Test that multiple calls produce unique IDs.""" - generator = UUIDGenerator() - context = IDGeneratorContext() ids = [generator.generate(context) for _ in range(100)] # All IDs should be unique assert len(ids) == len(set(ids)) @@ -118,4 +126,5 @@ def test_generate_works_with_various_contexts(self, context_arg): generator = UUIDGenerator() result = generator.generate(context_arg) assert isinstance(result, str) - uuid.UUID(result) + parsed_uuid = uuid.UUID(result) + assert parsed_uuid.version == 4 From fd121f0ab89c3a37c5edf64e0aa957f9abd27344 Mon Sep 17 00:00:00 2001 From: Didier Durand Date: Tue, 16 Dec 2025 10:07:47 +0100 Subject: [PATCH 5/5] test: applying review suggestion --- tests/server/tasks/test_id_generator.py | 39 +++++++++++++------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/server/tasks/test_id_generator.py b/tests/server/tasks/test_id_generator.py index d6428d36..11bfff2b 100644 --- a/tests/server/tasks/test_id_generator.py +++ b/tests/server/tasks/test_id_generator.py @@ -54,32 +54,33 @@ def test_context_validation(self): with pytest.raises(ValidationError): IDGeneratorContext(task_id={'not': 'a string'}) - class TestIDGenerator: - """Tests for IDGenerator abstract base class.""" - def test_cannot_instantiate_abstract_class(self): - """Test that IDGenerator cannot be instantiated directly.""" - with pytest.raises(TypeError): - IDGenerator() +class TestIDGenerator: + """Tests for IDGenerator abstract base class.""" - def test_subclass_must_implement_generate(self): - """Test that subclasses must implement the generate method.""" + def test_cannot_instantiate_abstract_class(self): + """Test that IDGenerator cannot be instantiated directly.""" + with pytest.raises(TypeError): + IDGenerator() - class IncompleteGenerator(IDGenerator): - pass + def test_subclass_must_implement_generate(self): + """Test that subclasses must implement the generate method.""" - with pytest.raises(TypeError): - IncompleteGenerator() + class IncompleteGenerator(IDGenerator): + pass - def test_valid_subclass_implementation(self): - """Test that a valid subclass can be instantiated.""" + with pytest.raises(TypeError): + IncompleteGenerator() - class ValidGenerator(IDGenerator): # pylint: disable=C0115,R0903 - def generate(self, context: IDGeneratorContext) -> str: - return 'test_id' + def test_valid_subclass_implementation(self): + """Test that a valid subclass can be instantiated.""" - generator = ValidGenerator() - assert generator.generate(IDGeneratorContext()) == 'test_id' + class ValidGenerator(IDGenerator): # pylint: disable=C0115,R0903 + def generate(self, context: IDGeneratorContext) -> str: + return 'test_id' + + generator = ValidGenerator() + assert generator.generate(IDGeneratorContext()) == 'test_id' @pytest.fixture