Skip to content

Commit 0baac8f

Browse files
committed
perf(test): Speed up unit test suite via parallelism and dedup
Enable pytest-xdist (-n auto) in CI so the ~7300-test suite runs in parallel instead of single-threaded. Measured locally: 121s -> 72s (~40% faster wall-clock); larger gains expected on multi-core runners. Also remove the dead `llm_backend` parametrize (GOOGLE_AI/VERTEX) from 26 tests in test_instructions.py and test_llm_request.py. The param was never read by any test body and no fixture consumed it, so each test ran twice over identical code under the same env. Verified the full call surface (instructions/contents request processors and LlmRequest.append_instructions) has no backend branching; real dual-backend FD-prep coverage remains in test_agent_tool.py via the env_variables fixture. Change-Id: I585f2621863edadee2b9f3b224b980aef7df79fb
1 parent 7cae06e commit 0baac8f

3 files changed

Lines changed: 27 additions & 62 deletions

File tree

.github/workflows/python-unit-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ jobs:
3939
run: |
4040
source .venv/bin/activate
4141
pytest tests/unittests \
42+
-n auto \
4243
--ignore=tests/unittests/artifacts/test_artifact_service.py \
4344
--ignore=tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py

tests/unittests/flows/llm_flows/test_instructions.py

Lines changed: 24 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -541,8 +541,7 @@ async def test_string_global_instruction_respects_bypass_state_injection():
541541
# Static Instruction Tests (moved from test_static_instructions.py)
542542

543543

544-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
545-
def test_static_instruction_field_exists(llm_backend):
544+
def test_static_instruction_field_exists():
546545
"""Test that static_instruction field exists and works with types.Content."""
547546
static_content = types.Content(
548547
role="user", parts=[types.Part(text="This is a static instruction")]
@@ -551,35 +550,31 @@ def test_static_instruction_field_exists(llm_backend):
551550
assert agent.static_instruction == static_content
552551

553552

554-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
555-
def test_static_instruction_supports_string(llm_backend):
553+
def test_static_instruction_supports_string():
556554
"""Test that static_instruction field supports simple strings."""
557555
static_str = "This is a static instruction as a string"
558556
agent = LlmAgent(name="test_agent", static_instruction=static_str)
559557
assert agent.static_instruction == static_str
560558
assert isinstance(agent.static_instruction, str)
561559

562560

563-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
564-
def test_static_instruction_supports_part(llm_backend):
561+
def test_static_instruction_supports_part():
565562
"""Test that static_instruction field supports types.Part."""
566563
static_part = types.Part(text="This is a static instruction as Part")
567564
agent = LlmAgent(name="test_agent", static_instruction=static_part)
568565
assert agent.static_instruction == static_part
569566
assert isinstance(agent.static_instruction, types.Part)
570567

571568

572-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
573-
def test_static_instruction_supports_file(llm_backend):
569+
def test_static_instruction_supports_file():
574570
"""Test that static_instruction field supports types.File."""
575571
static_file = types.File(uri="gs://bucket/file.txt", mime_type="text/plain")
576572
agent = LlmAgent(name="test_agent", static_instruction=static_file)
577573
assert agent.static_instruction == static_file
578574
assert isinstance(agent.static_instruction, types.File)
579575

580576

581-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
582-
def test_static_instruction_supports_list_of_parts(llm_backend):
577+
def test_static_instruction_supports_list_of_parts():
583578
"""Test that static_instruction field supports list[PartUnion]."""
584579
static_parts_list = [
585580
types.Part(text="First part"),
@@ -591,8 +586,7 @@ def test_static_instruction_supports_list_of_parts(llm_backend):
591586
assert len(agent.static_instruction) == 2
592587

593588

594-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
595-
def test_static_instruction_supports_list_of_strings(llm_backend):
589+
def test_static_instruction_supports_list_of_strings():
596590
"""Test that static_instruction field supports list of strings."""
597591
static_strings_list = ["First instruction", "Second instruction"]
598592
agent = LlmAgent(name="test_agent", static_instruction=static_strings_list)
@@ -601,8 +595,7 @@ def test_static_instruction_supports_list_of_strings(llm_backend):
601595
assert all(isinstance(s, str) for s in agent.static_instruction)
602596

603597

604-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
605-
def test_static_instruction_supports_multiple_parts(llm_backend):
598+
def test_static_instruction_supports_multiple_parts():
606599
"""Test that static_instruction supports multiple parts including files."""
607600
static_content = types.Content(
608601
role="user",
@@ -621,8 +614,7 @@ def test_static_instruction_supports_multiple_parts(llm_backend):
621614
assert len(agent.static_instruction.parts) == 3
622615

623616

624-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
625-
def test_static_instruction_outputs_placeholders_literally(llm_backend):
617+
def test_static_instruction_outputs_placeholders_literally():
626618
"""Test that static instructions output placeholders literally without processing."""
627619
static_content = types.Content(
628620
role="user",
@@ -635,9 +627,8 @@ def test_static_instruction_outputs_placeholders_literally(llm_backend):
635627
assert "{count}" in agent.static_instruction.parts[0].text
636628

637629

638-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
639630
@pytest.mark.asyncio
640-
async def test_static_instruction_added_to_contents(llm_backend):
631+
async def test_static_instruction_added_to_contents():
641632
"""Test that static instructions are added to llm_request.config.system_instruction."""
642633
static_content = types.Content(
643634
role="user", parts=[types.Part(text="Static instruction content")]
@@ -657,9 +648,8 @@ async def test_static_instruction_added_to_contents(llm_backend):
657648
assert llm_request.config.system_instruction == "Static instruction content"
658649

659650

660-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
661651
@pytest.mark.asyncio
662-
async def test_static_instruction_string_added_to_system(llm_backend):
652+
async def test_static_instruction_string_added_to_system():
663653
"""Test that string static instructions are added to system_instruction."""
664654
agent = LlmAgent(
665655
name="test_agent", static_instruction="Static instruction as string"
@@ -678,9 +668,8 @@ async def test_static_instruction_string_added_to_system(llm_backend):
678668
assert llm_request.config.system_instruction == "Static instruction as string"
679669

680670

681-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
682671
@pytest.mark.asyncio
683-
async def test_static_instruction_part_converted_to_system(llm_backend):
672+
async def test_static_instruction_part_converted_to_system():
684673
"""Test that Part static instructions are converted and added to system_instruction."""
685674
static_part = types.Part(text="Static instruction from Part")
686675
agent = LlmAgent(name="test_agent", static_instruction=static_part)
@@ -696,11 +685,8 @@ async def test_static_instruction_part_converted_to_system(llm_backend):
696685
assert llm_request.config.system_instruction == "Static instruction from Part"
697686

698687

699-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
700688
@pytest.mark.asyncio
701-
async def test_static_instruction_list_of_parts_converted_to_system(
702-
llm_backend,
703-
):
689+
async def test_static_instruction_list_of_parts_converted_to_system():
704690
"""Test that list of Parts is converted and added to system_instruction."""
705691
static_parts_list = [
706692
types.Part(text="First part"),
@@ -719,11 +705,8 @@ async def test_static_instruction_list_of_parts_converted_to_system(
719705
assert llm_request.config.system_instruction == "First part\n\nSecond part"
720706

721707

722-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
723708
@pytest.mark.asyncio
724-
async def test_static_instruction_list_of_strings_converted_to_system(
725-
llm_backend,
726-
):
709+
async def test_static_instruction_list_of_strings_converted_to_system():
727710
"""Test that list of strings is converted and added to system_instruction."""
728711
static_strings_list = ["First instruction", "Second instruction"]
729712
agent = LlmAgent(name="test_agent", static_instruction=static_strings_list)
@@ -742,9 +725,8 @@ async def test_static_instruction_list_of_strings_converted_to_system(
742725
)
743726

744727

745-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
746728
@pytest.mark.asyncio
747-
async def test_dynamic_instruction_without_static_goes_to_system(llm_backend):
729+
async def test_dynamic_instruction_without_static_goes_to_system():
748730
"""Test that dynamic instructions go to system when no static instruction exists."""
749731
agent = LlmAgent(name="test_agent", instruction="Dynamic instruction content")
750732

@@ -761,9 +743,8 @@ async def test_dynamic_instruction_without_static_goes_to_system(llm_backend):
761743
assert len(llm_request.contents) == 0
762744

763745

764-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
765746
@pytest.mark.asyncio
766-
async def test_dynamic_instruction_with_static_not_in_system(llm_backend):
747+
async def test_dynamic_instruction_with_static_not_in_system():
767748
"""Test that dynamic instructions don't go to system when static instruction exists."""
768749
static_content = types.Content(
769750
role="user", parts=[types.Part(text="Static instruction content")]
@@ -793,11 +774,8 @@ async def test_dynamic_instruction_with_static_not_in_system(llm_backend):
793774
assert llm_request.contents[0].parts[0].text == "Dynamic instruction content"
794775

795776

796-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
797777
@pytest.mark.asyncio
798-
async def test_dynamic_instruction_with_string_static_not_in_system(
799-
llm_backend,
800-
):
778+
async def test_dynamic_instruction_with_string_static_not_in_system():
801779
"""Test that dynamic instructions go to user content when string static_instruction exists."""
802780
agent = LlmAgent(
803781
name="test_agent",
@@ -823,9 +801,8 @@ async def test_dynamic_instruction_with_string_static_not_in_system(
823801
assert llm_request.contents[0].parts[0].text == "Dynamic instruction content"
824802

825803

826-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
827804
@pytest.mark.asyncio
828-
async def test_dynamic_instructions_added_to_user_content(llm_backend):
805+
async def test_dynamic_instructions_added_to_user_content():
829806
"""Test that dynamic instructions are added to user content when static exists."""
830807
static_content = types.Content(
831808
role="user", parts=[types.Part(text="Static instruction")]
@@ -863,11 +840,8 @@ async def test_dynamic_instructions_added_to_user_content(llm_backend):
863840
assert llm_request.contents[1].parts[0].text == "Hello world"
864841

865842

866-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
867843
@pytest.mark.asyncio
868-
async def test_dynamic_instructions_create_user_content_when_none_exists(
869-
llm_backend,
870-
):
844+
async def test_dynamic_instructions_create_user_content_when_none_exists():
871845
"""Test that dynamic instructions create user content when none exists."""
872846
static_content = types.Content(
873847
role="user", parts=[types.Part(text="Static instruction")]
@@ -898,9 +872,8 @@ async def test_dynamic_instructions_create_user_content_when_none_exists(
898872
assert llm_request.contents[0].parts[0].text == "Dynamic instruction"
899873

900874

901-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
902875
@pytest.mark.asyncio
903-
async def test_no_dynamic_instructions_when_no_static(llm_backend):
876+
async def test_no_dynamic_instructions_when_no_static():
904877
"""Test that no dynamic instructions are added to content when no static instructions exist."""
905878
agent = LlmAgent(name="test_agent", instruction="Dynamic instruction only")
906879

@@ -958,9 +931,8 @@ async def test_instructions_insert_after_function_response():
958931
assert llm_request.contents[2].parts[0].text == "Dynamic instruction"
959932

960933

961-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
962934
@pytest.mark.asyncio
963-
async def test_static_instruction_with_files_and_text(llm_backend):
935+
async def test_static_instruction_with_files_and_text():
964936
"""Test that static instruction can contain files and text together."""
965937
static_content = types.Content(
966938
role="user",
@@ -1002,11 +974,8 @@ async def test_static_instruction_with_files_and_text(llm_backend):
1002974
assert llm_request.contents[0].parts[1].inline_data.data == b"fake_image_data"
1003975

1004976

1005-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
1006977
@pytest.mark.asyncio
1007-
async def test_static_instruction_non_text_parts_moved_to_user_content(
1008-
llm_backend,
1009-
):
978+
async def test_static_instruction_non_text_parts_moved_to_user_content():
1010979
"""Test that non-text parts from static instruction are moved to user content."""
1011980
static_content = types.Content(
1012981
role="user",
@@ -1075,9 +1044,8 @@ async def test_static_instruction_non_text_parts_moved_to_user_content(
10751044
assert file_content.parts[1].file_data.display_name == "test_file.txt"
10761045

10771046

1078-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
10791047
@pytest.mark.asyncio
1080-
async def test_static_instruction_reference_id_generation(llm_backend):
1048+
async def test_static_instruction_reference_id_generation():
10811049
"""Test that reference IDs are generated correctly for non-text parts."""
10821050
static_content = types.Content(
10831051
role="user",
@@ -1125,9 +1093,8 @@ async def test_static_instruction_reference_id_generation(llm_backend):
11251093
assert len(content.parts) == 2
11261094

11271095

1128-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
11291096
@pytest.mark.asyncio
1130-
async def test_static_instruction_only_text_parts(llm_backend):
1097+
async def test_static_instruction_only_text_parts():
11311098
"""Test that static instruction with only text parts works normally."""
11321099
static_content = types.Content(
11331100
role="user",
@@ -1151,9 +1118,8 @@ async def test_static_instruction_only_text_parts(llm_backend):
11511118
assert len(llm_request.contents) == 0
11521119

11531120

1154-
@pytest.mark.parametrize("llm_backend", ["GOOGLE_AI", "VERTEX"])
11551121
@pytest.mark.asyncio
1156-
async def test_static_instruction_only_non_text_parts(llm_backend):
1122+
async def test_static_instruction_only_non_text_parts():
11571123
"""Test that static instruction with only non-text parts works correctly."""
11581124
static_content = types.Content(
11591125
role="user",

tests/unittests/models/test_llm_request.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,7 @@ def test_append_instructions_warning_unsupported_system_instruction_type(
754754
)
755755

756756

757-
@pytest.mark.parametrize('llm_backend', ['GOOGLE_AI', 'VERTEX'])
758-
def test_append_instructions_with_mixed_content(llm_backend):
757+
def test_append_instructions_with_mixed_content():
759758
"""Test append_instructions with mixed text and non-text content."""
760759
request = LlmRequest()
761760

@@ -813,8 +812,7 @@ def test_append_instructions_with_mixed_content(llm_backend):
813812
assert user_contents[1].parts[1].file_data.display_name == 'document.txt'
814813

815814

816-
@pytest.mark.parametrize('llm_backend', ['GOOGLE_AI', 'VERTEX'])
817-
def test_append_instructions_with_only_text_parts(llm_backend):
815+
def test_append_instructions_with_only_text_parts():
818816
"""Test append_instructions with only text parts."""
819817
request = LlmRequest()
820818

0 commit comments

Comments
 (0)