Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion src/google/adk/evaluation/eval_rubrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ class RubricContent(EvalBaseModel):
"""The content of a rubric."""

text_property: Optional[str] = Field(
default=None,
description=(
"The property being evaluated. Example: \"The agent's response is"
' grammatically correct." '
)
),
)


Expand Down
34 changes: 34 additions & 0 deletions tests/unittests/evaluation/test_eval_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from google.adk.evaluation.eval_case import InvocationEvent
from google.adk.evaluation.eval_case import InvocationEvents
from google.adk.evaluation.eval_case import SessionInput
from google.adk.evaluation.eval_rubrics import Rubric
from google.adk.evaluation.eval_rubrics import RubricContent
from google.genai import types as genai_types
import pytest

Expand Down Expand Up @@ -62,6 +64,38 @@ def test_invocation_event_content_defaults_to_none():
assert InvocationEvent.model_validate(event.model_dump()).content is None


def test_rubric_content_text_property_defaults_to_none():
"""A RubricContent without text_property round-trips (required-Optional fix)."""
content = RubricContent(text_property=None)

assert content.text_property is None
# Simulates the GET(exclude_none=True) -> PUT cycle: an omitted text_property
# must still validate (Pydantic v2 treats Optional-without-default as required).
assert RubricContent.model_validate(content.model_dump(exclude_none=True)).text_property is None


def test_eval_case_with_rubric_missing_text_property_round_trips():
"""An EvalCase carrying a rubric whose text_property is None survives a
GET(exclude_none=True) -> PUT round-trip instead of raising a 422."""
rubric = Rubric(
rubric_id='r1',
rubric_content=RubricContent(text_property=None),
)
eval_case = EvalCase(
eval_id='case_1',
conversation=[],
rubrics=[rubric],
)

# response_model_exclude_none=True drops text_property=None from the wire.
wire = eval_case.model_dump(by_alias=True, exclude_none=True)

# The PUT re-validates the wire; a required-Optional trap would 422 here.
revalidated = EvalCase.model_validate(wire)
assert revalidated.rubrics is not None
assert revalidated.rubrics[0].rubric_content.text_property is None


def test_session_input_accepts_session_id():
"""Tests that SessionInput accepts a fixed session_id and round-trips it."""
session_input = SessionInput(app_name='a', user_id='u', session_id='s1')
Expand Down