Files
bradsec-ComfyUI_RandomPerson/test_random_person.py
T

136 lines
5.1 KiB
Python

"""Unit tests for the Random Person Description shared core.
Pure logic, no ComfyUI required: reads the bundled data/ JSON only.
Run: python -m unittest test_random_person -v
"""
import unittest
import nodes as core
def cat_args(**overrides):
"""All categories on 'random' by default; override with key=(mode, allow, fixed)."""
args = {key: ("random", "", "(none)") for key, _, _ in core.CATEGORY_SPECS}
args.update(overrides)
return args
def run(seed=123, randomize=False, sex="female", age_mode="random",
age_min=0, age_max=0, age_fixed=0, extra="", **cat):
return core.generate_person(seed, randomize, sex, cat_args(**cat),
age_mode, age_min, age_max, age_fixed, extra)
class TestSelection(unittest.TestCase):
def test_seed_reproducible(self):
a = run(seed=42)
b = run(seed=42)
self.assertEqual(a, b)
def test_different_seed_differs(self):
# Not guaranteed in theory, but with this data the full string should differ.
self.assertNotEqual(run(seed=1)[0], run(seed=999)[0])
def test_randomize_returns_used_seed(self):
out = run(randomize=True)
used = out[-1]
self.assertIsInstance(used, int)
self.assertNotEqual(used, 0)
# Re-running with that seed and randomize off reproduces the person.
self.assertEqual(run(seed=used)[0], out[0])
def test_off_mode_omits_body(self):
out = run(body_type=("off", "", "(none)"))
self.assertEqual(out[8], "") # body_type pin empty
self.assertNotIn("build", out[0].lower())
def test_fixed_nationality(self):
out = run(nationality=("fixed", "", "Japanese"))
self.assertIn("japanese", out[3].lower())
def test_allow_list_custom_value(self):
# A token with no field overlap with any JSON entry is used as a literal.
out = run(hair_color=("allow_list", "ultraviolet", "(none)"))
self.assertIn("ultraviolet", out[6]) # hair pin carries the custom value
def test_custom_nationality_not_dropped(self):
# Regression F-NAT: a custom nationality (no "descriptor" key) must still
# reach the description opener and the nationality pin.
out = run(nationality=("allow_list", "Atlantean", "(none)"))
self.assertEqual(out[3], "Atlantean") # nationality pin
self.assertIn("Atlantean", out[0]) # description opener
def test_sex_resolved_from_random(self):
self.assertIn(run(sex="random")[1], ("male", "female"))
def test_flair_categories_default_off(self):
# Optional categories must ship with mode default "off"; identity
# categories must default "random".
req = core.RandomPersonNode.INPUT_TYPES()["required"]
for key in core.DEFAULT_OFF:
self.assertEqual(req[f"{key}_mode"][1]["default"], "off", key)
for key in ("nationality", "complexion", "eyes", "hair_color", "body_type"):
self.assertEqual(req[f"{key}_mode"][1]["default"], "random", key)
def test_female_never_grows_facial_hair(self):
for seed in range(40):
self.assertEqual(run(seed=seed, sex="female")[7], "") # facial_hair pin empty
def test_male_makeup_empty(self):
for seed in range(40):
self.assertEqual(run(seed=seed, sex="male")[11], "") # makeup pin empty
def test_skin_texture_in_complexion_pin(self):
out = run(skin_texture=("fixed", "", "freckled"),
complexion=("fixed", "", "tan"))
self.assertIn("tan", out[4])
self.assertIn("freckled", out[4])
def test_expression_pin_and_off(self):
on = run(expression=("fixed", "", "serious"))
self.assertIn("serious", on[9])
off = run(expression=("off", "", "(none)"))
self.assertEqual(off[9], "")
class TestAge(unittest.TestCase):
def test_age_off(self):
out = run(age_mode="off")
self.assertEqual(out[2], "")
self.assertNotIn("year old", out[0])
def test_age_fixed_clamped_to_min(self):
out = run(age_mode="fixed", age_fixed=15)
self.assertGreaterEqual(int(out[2]), 21)
def test_age_range_respected(self):
ages = core.load_shared("age.json")
for seed in range(30):
picked = core.resolve_age("random", 30, 40, 0, ages)
self.assertTrue(30 <= picked["age"] <= 40)
class TestBuildDescription(unittest.TestCase):
def test_empty_when_all_none(self):
self.assertEqual(core.build_description(*( [""] + [None] * 17 )), "")
def test_extra_attributes_appended(self):
out = run(extra="wearing glasses, gold earrings")
self.assertIn("wearing glasses", out[0])
self.assertIn("gold earrings", out[0])
def test_eyes_no_double_suffix(self):
# An eyes description already containing "eyes" must not get " eyes" appended.
args = [""] + [None] * 17
args[6] = {"description": "muted natural green eyes"} # eyes positional slot
s = core.build_description(*args)
self.assertNotIn("eyes eyes", s)
if __name__ == "__main__":
unittest.main()