Skip to content

Commit 547c6d5

Browse files
romanlutzCopilot
andcommitted
TEST: cover deprecated shim methods to satisfy diff-cover threshold
The unit-test-diff-cover check failed because six newly-added print_deprecation_message(...) lines were not exercised by existing tests: - pyrit/output/scenario_result/base.py:38 (print_summary_async) - pyrit/output/scorer/base.py:68 (print_objective_scorer), :79 (print_harm_scorer) - pyrit/prompt_converter/persuasion_converter.py:132 (send_persuasion_prompt_async) - pyrit/prompt_converter/variation_converter.py:116 (send_variation_prompt_async) - pyrit/prompt_target/common/prompt_chat_target.py:53 (__init__) Add focused tests that invoke each shim, assert a DeprecationWarning is emitted, and verify the shim delegates to the replacement API. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4998e6d commit 547c6d5

5 files changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT license.
3+
4+
from unittest.mock import AsyncMock, MagicMock
5+
6+
import pytest
7+
8+
from pyrit.models.scenario_result import ScenarioResult
9+
from pyrit.output.scenario_result.base import ScenarioResultPrinterBase
10+
11+
12+
def test_scenario_result_printer_cannot_be_instantiated():
13+
with pytest.raises(TypeError, match="Can't instantiate abstract class"):
14+
ScenarioResultPrinterBase() # type: ignore[abstract]
15+
16+
17+
async def test_print_summary_async_emits_deprecation_warning_and_delegates():
18+
"""``print_summary_async`` is a deprecated shim that should warn and call ``write_async``."""
19+
20+
class _MinimalPrinter(ScenarioResultPrinterBase):
21+
def __init__(self) -> None:
22+
self.write_async = AsyncMock()
23+
24+
async def render_async(self, result: ScenarioResult) -> str:
25+
return ""
26+
27+
printer = _MinimalPrinter()
28+
result = MagicMock(spec=ScenarioResult)
29+
30+
with pytest.warns(DeprecationWarning, match="print_summary_async"):
31+
await printer.print_summary_async(result)
32+
33+
printer.write_async.assert_awaited_once_with(result)

tests/unit/output/scorer/test_base.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT license.
33

4+
from unittest.mock import AsyncMock
5+
46
import pytest
57

68
from pyrit.identifiers import ComponentIdentifier
@@ -57,3 +59,44 @@ async def render_async(
5759

5860
printer = CompletePrinter()
5961
assert isinstance(printer, ScorerPrinterBase)
62+
63+
64+
def _make_complete_printer() -> ScorerPrinterBase:
65+
class CompletePrinter(ScorerPrinterBase):
66+
def __init__(self) -> None:
67+
self.write_async = AsyncMock()
68+
69+
def _get_objective_metrics(self, *, scorer_identifier: ComponentIdentifier):
70+
return None
71+
72+
def _get_harm_metrics(self, *, scorer_identifier: ComponentIdentifier, harm_category: str):
73+
return None
74+
75+
async def render_async(
76+
self, *, scorer_identifier: ComponentIdentifier, harm_category: str | None = None
77+
) -> str:
78+
return ""
79+
80+
return CompletePrinter()
81+
82+
83+
async def test_print_objective_scorer_emits_deprecation_warning_and_delegates():
84+
"""``print_objective_scorer`` is a deprecated shim that should warn and call ``write_async``."""
85+
printer = _make_complete_printer()
86+
scorer_identifier = ComponentIdentifier(class_name="TestScorer", class_module="tests")
87+
88+
with pytest.warns(DeprecationWarning, match="print_objective_scorer"):
89+
await printer.print_objective_scorer(scorer_identifier=scorer_identifier)
90+
91+
printer.write_async.assert_awaited_once_with(scorer_identifier=scorer_identifier)
92+
93+
94+
async def test_print_harm_scorer_emits_deprecation_warning_and_delegates():
95+
"""``print_harm_scorer`` is a deprecated shim that should warn and call ``write_async``."""
96+
printer = _make_complete_printer()
97+
scorer_identifier = ComponentIdentifier(class_name="TestScorer", class_module="tests")
98+
99+
with pytest.warns(DeprecationWarning, match="print_harm_scorer"):
100+
await printer.print_harm_scorer(scorer_identifier=scorer_identifier, harm_category="violence")
101+
102+
printer.write_async.assert_awaited_once_with(scorer_identifier=scorer_identifier, harm_category="violence")

tests/unit/prompt_converter/test_persuasion_converter.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,32 @@ def test_persuasion_converter_identifier_includes_technique(sqlite_instance):
149149
prompt_persuasion = PersuasionConverter(converter_target=prompt_target, persuasion_technique="logical_appeal")
150150
identifier = prompt_persuasion.get_identifier()
151151
assert identifier.params["persuasion_technique"] == "logical_appeal"
152+
153+
154+
async def test_send_persuasion_prompt_async_emits_deprecation_warning_and_delegates(sqlite_instance):
155+
"""``send_persuasion_prompt_async`` is a deprecated shim that warns and delegates to the retry helper."""
156+
prompt_target = MockPromptTarget()
157+
prompt_persuasion = PersuasionConverter(
158+
converter_target=prompt_target, persuasion_technique="authority_endorsement"
159+
)
160+
161+
request = Message(
162+
message_pieces=[
163+
MessagePiece(
164+
role="user",
165+
conversation_id="conv-1",
166+
original_value="test input",
167+
original_value_data_type="text",
168+
prompt_target_identifier=ComponentIdentifier(class_name="test", class_module="test"),
169+
)
170+
]
171+
)
172+
173+
with patch.object(
174+
prompt_persuasion, "_send_with_retries_async", new=AsyncMock(return_value="shim response")
175+
) as mock_send:
176+
with pytest.warns(DeprecationWarning, match="send_persuasion_prompt_async"):
177+
result = await prompt_persuasion.send_persuasion_prompt_async(request)
178+
179+
assert result == "shim response"
180+
mock_send.assert_awaited_once_with(request)

tests/unit/prompt_converter/test_variation_converter.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,30 @@ def test_variation_converter_input_supported(sqlite_instance):
115115
converter = VariationConverter(converter_target=prompt_target)
116116
assert converter.input_supported("audio_path") is False
117117
assert converter.input_supported("text") is True
118+
119+
120+
async def test_send_variation_prompt_async_emits_deprecation_warning_and_delegates(sqlite_instance):
121+
"""``send_variation_prompt_async`` is a deprecated shim that warns and delegates to the retry helper."""
122+
prompt_target = MockPromptTarget()
123+
prompt_variation = VariationConverter(converter_target=prompt_target)
124+
125+
request = Message(
126+
message_pieces=[
127+
MessagePiece(
128+
role="user",
129+
conversation_id="conv-1",
130+
original_value="test input",
131+
original_value_data_type="text",
132+
prompt_target_identifier=ComponentIdentifier(class_name="test", class_module="test"),
133+
)
134+
]
135+
)
136+
137+
with patch.object(
138+
prompt_variation, "_send_with_retries_async", new=AsyncMock(return_value="shim response")
139+
) as mock_send:
140+
with pytest.warns(DeprecationWarning, match="send_variation_prompt_async"):
141+
result = await prompt_variation.send_variation_prompt_async(request)
142+
143+
assert result == "shim response"
144+
mock_send.assert_awaited_once_with(request)

tests/unit/prompt_target/test_prompt_chat_target.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,28 @@ async def _send_prompt_to_target_async(self, *, normalized_conversation: list[Me
7878
assert len(deprecation_warnings) >= 1
7979

8080

81+
@pytest.mark.usefixtures("patch_central_database")
82+
def test_instantiating_prompt_chat_target_subclass_emits_deprecation_warning():
83+
"""``PromptChatTarget.__init__`` is deprecated and must emit a warning when called."""
84+
85+
class _LegacyChatSubclassForInit(PromptChatTarget):
86+
async def _send_prompt_to_target_async(self, *, normalized_conversation: list[Message]) -> list[Message]:
87+
return []
88+
89+
with warnings.catch_warnings(record=True) as caught:
90+
warnings.simplefilter("always")
91+
_LegacyChatSubclassForInit()
92+
93+
deprecation_warnings = [
94+
w
95+
for w in caught
96+
if issubclass(w.category, DeprecationWarning)
97+
and "PromptChatTarget" in str(w.message)
98+
and "0.16.0" in str(w.message)
99+
]
100+
assert len(deprecation_warnings) >= 1
101+
102+
81103
@pytest.mark.usefixtures("patch_central_database")
82104
def test_set_system_prompt_available_on_prompt_target():
83105
"""The set_system_prompt API now lives on PromptTarget directly."""

0 commit comments

Comments
 (0)