* Added combinatorial shuffle. * A1111: Improved combinatorial with hiresfix. * Some refactoring. * Update of AI test instructions. Co-authored-by: Copilot <copilot@github.com>
4.4 KiB
4.4 KiB
description, applyTo
| description | applyTo |
|---|---|
| Use when writing, editing, or reviewing test files. Enforces unittest patterns used in this project: TestCase inheritance, base class setup, process() helper, and naming conventions. | tests/**/*.py |
Test Conventions
All tests use the standard unittest module. Do not use pytest-specific features (fixtures, @pytest.mark, conftest.py, etc.).
File & Class Naming
- One test file per concern, named
tests_{category}.py - One test class per file inheriting from
TestPromptPostProcessorBase:
import unittest
from tests.base_tests import TestPromptPostProcessorBase
class TestMyFeature(TestPromptPostProcessorBase):
def setUp(self):
super().setUp(enable_file_logging=False)
Test Method Naming
test_{2-3 letter category prefix}_{short_description}
Examples: test_cl_simple, test_ch_choices, test_wc_ignore
Running a Test Case via self.process()
Use the process() helper from the base class — never instantiate PromptPostProcessor directly in test methods unless there is a need to pass specific options not covered by the default setup or the "nocup" or "nostrict" options.
def test_cl_simple(self):
"""simple cleanup"""
self.process(
InputTuple(
"input prompt", # positive prompt
""), # negative prompt
OutputTuple(
"expected output", # expected positive prompt
"", # expected negative prompt
{} # expected variables (optional)
),
)
def test_cl_combinatorial(self):
"""simple cleanup"""
self.process(
InputTuple(
"input prompt", # positive prompt
""), # negative prompt
[
OutputTuple(
"expected output", # expected positive prompt
"", # expected negative prompt
{} # expected variables (optional)
),
OutputTuple(
"expected output", # expected positive prompt
"", # expected negative prompt
{} # expected variables (optional)
),
],
combinatorial=True,
)
process() Signature (key parameters)
| Parameter | Type | Notes |
|---|---|---|
input_prompts |
InputTuple |
Prompts input |
expected_output |
OutputTuple | list[OutputTuple] |
Single or multiple valid outputs |
seed |
int |
Optional, defaults to fixed seed |
ppp |
PromptPostProcessor | str | None |
Supported values "nocup", "nostrict" or a specific instance |
interrupted |
bool |
Expected interrupt flag |
combinatorial |
bool |
Whether to run a combinatorial generation. If a specific ppp instance is used then it is ignored |
Assertions
Use assertEqual or similar methods with a descriptive message string:
self.assertEqual(result, expected, "Descriptive failure message")
self.assertIn(key, container, f"Key '{key}' not found in output")
Do not use bare assert statements.
Default Options & Environment
Override self.defopts or self.def_env_info to pass non-default options — do not hardcode option dicts from scratch:
def test_cl_custom(self):
"""cleanup with custom separator"""
self.process(
InputTuple("a, , b", ""),
OutputTuple("a | b", ""),
ppp=PromptPostProcessor(
self.ppp_logger,
self.def_env_info,
replace(
self.defopts,
keep_choices_order=True,
cup_do_cleanup=False,
do_combinatorial=True,
),
self.grammar_content,
self.interrupt,
self.wildcards_obj,
self.extranetwork_maps_obj,
),
)
Entry Point
Every test file must start with:
if __name__ == "__main__":
raise SystemExit("This script must not be run directly")