Skip to content

Commit e6c6712

Browse files
rlundeen2Copilot
andauthored
TEST: Unit test speed up (#1872)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 6e55d3a commit e6c6712

2 files changed

Lines changed: 21 additions & 40 deletions

File tree

.github/instructions/test.instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Readable, maintainable tests. Reuse helpers from `conftest.py` and `mocks.py` in
1010

1111
- Do NOT add `@pytest.mark.asyncio``asyncio_mode = "auto"` is configured project-wide so all async tests are discovered automatically.
1212
- Use `AsyncMock` for async methods, `MagicMock` for sync.
13+
- When running a full test pass, use `make unit-test` rather than invoking `pytest` directly on `tests/unit/`. It's significantly faster because it runs in parallel (`pytest -n 4`).
1314

1415
## Test Tiers
1516

tests/unit/scenario/test_jailbreak.py

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -232,25 +232,12 @@ async def test_explicit_include_baseline_false_omits_baseline(
232232
class TestJailbreakAttackGeneration:
233233
"""Tests for Jailbreak attack generation."""
234234

235-
async def test_attack_generation_for_all(
236-
self, mock_objective_target, mock_objective_scorer, mock_memory_seed_groups
237-
):
238-
"""Test that _get_atomic_attacks_async returns atomic attacks."""
239-
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
240-
scenario = Jailbreak(objective_scorer=mock_objective_scorer)
241-
242-
await scenario.initialize_async(objective_target=mock_objective_target)
243-
atomic_attacks = await scenario._get_atomic_attacks_async()
244-
245-
assert len(atomic_attacks) > 0
246-
assert all(run.attack_technique is not None for run in atomic_attacks)
247-
248235
async def test_attack_generation_for_simple(
249236
self, mock_objective_target, mock_objective_scorer, mock_memory_seed_groups, simple_jailbreak_strategy
250237
):
251238
"""Test that the simple attack generation works."""
252239
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
253-
scenario = Jailbreak(objective_scorer=mock_objective_scorer)
240+
scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
254241

255242
await scenario.initialize_async(
256243
objective_target=mock_objective_target, scenario_strategies=[simple_jailbreak_strategy]
@@ -264,7 +251,7 @@ async def test_attack_generation_for_complex(
264251
):
265252
"""Test that the complex attack generation works."""
266253
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
267-
scenario = Jailbreak(objective_scorer=mock_objective_scorer)
254+
scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
268255

269256
await scenario.initialize_async(
270257
objective_target=mock_objective_target,
@@ -282,7 +269,7 @@ async def test_attack_generation_for_manyshot(
282269
):
283270
"""Test that the manyshot attack generation works."""
284271
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
285-
scenario = Jailbreak(objective_scorer=mock_objective_scorer)
272+
scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
286273

287274
await scenario.initialize_async(
288275
objective_target=mock_objective_target,
@@ -298,7 +285,7 @@ async def test_attack_generation_for_promptsending(
298285
):
299286
"""Test that the prompt sending attack generation works."""
300287
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
301-
scenario = Jailbreak(objective_scorer=mock_objective_scorer)
288+
scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
302289

303290
await scenario.initialize_async(
304291
objective_target=mock_objective_target,
@@ -314,7 +301,7 @@ async def test_attack_generation_for_skeleton(
314301
):
315302
"""Test that the skelton key attack generation works."""
316303
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
317-
scenario = Jailbreak(objective_scorer=mock_objective_scorer)
304+
scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
318305

319306
await scenario.initialize_async(
320307
objective_target=mock_objective_target,
@@ -330,7 +317,7 @@ async def test_attack_generation_for_roleplay(
330317
):
331318
"""Test that the roleplaying attack generation works."""
332319
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
333-
scenario = Jailbreak(objective_scorer=mock_objective_scorer)
320+
scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
334321

335322
await scenario.initialize_async(
336323
objective_target=mock_objective_target,
@@ -344,33 +331,22 @@ async def test_attack_generation_for_roleplay(
344331
async def test_attack_runs_include_objectives(
345332
self, mock_objective_target, mock_objective_scorer, mock_memory_seed_groups
346333
):
347-
"""Test that attack runs include objectives for each seed prompt."""
334+
"""Test that attack runs include objectives for each seed prompt and that
335+
each atomic attack carries a valid attack_technique.
336+
337+
Combined coverage previously split across test_get_atomic_attacks_async_returns_attacks.
338+
"""
348339
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
349-
scenario = Jailbreak(
350-
objective_scorer=mock_objective_scorer,
351-
)
340+
scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
352341

353342
await scenario.initialize_async(objective_target=mock_objective_target)
354343
atomic_attacks = await scenario._get_atomic_attacks_async()
355344

356-
# Check that objectives are created for each seed prompt
345+
assert len(atomic_attacks) > 0
357346
for run in atomic_attacks:
347+
assert run.attack_technique is not None
358348
assert len(run.objectives) > 0
359349

360-
async def test_get_atomic_attacks_async_returns_attacks(
361-
self, mock_objective_target, mock_objective_scorer, mock_memory_seed_groups
362-
):
363-
"""Test that _get_atomic_attacks_async returns atomic attacks."""
364-
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
365-
scenario = Jailbreak(
366-
objective_scorer=mock_objective_scorer,
367-
)
368-
369-
await scenario.initialize_async(objective_target=mock_objective_target)
370-
atomic_attacks = await scenario._get_atomic_attacks_async()
371-
assert len(atomic_attacks) > 0
372-
assert all(run.attack_technique is not None for run in atomic_attacks)
373-
374350
async def test_get_all_jailbreak_templates(
375351
self, mock_objective_target, mock_objective_scorer, mock_memory_seed_groups
376352
):
@@ -396,11 +372,15 @@ async def test_custom_num_attempts(
396372
):
397373
"""Test that n successfully tries each jailbreak template n-many times."""
398374
with patch.object(Jailbreak, "_resolve_seed_groups", return_value=mock_memory_seed_groups):
399-
base_scenario = Jailbreak(objective_scorer=mock_objective_scorer)
375+
base_scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_templates=2)
400376
await base_scenario.initialize_async(objective_target=mock_objective_target, include_baseline=False)
401377
atomic_attacks_1 = await base_scenario._get_atomic_attacks_async()
402378

403-
mult_scenario = Jailbreak(objective_scorer=mock_objective_scorer, num_attempts=mock_random_num_attempts)
379+
mult_scenario = Jailbreak(
380+
objective_scorer=mock_objective_scorer,
381+
num_templates=2,
382+
num_attempts=mock_random_num_attempts,
383+
)
404384
await mult_scenario.initialize_async(objective_target=mock_objective_target, include_baseline=False)
405385
atomic_attacks_n = await mult_scenario._get_atomic_attacks_async()
406386

0 commit comments

Comments
 (0)