"""그림 겹침 검사기. 겹친 것을 실제로 잡고 안 겹친 것은 안 잡는지 본다.""" import os import subprocess import sys import tempfile import unittest ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) SCRIPT = os.path.join(ROOT, "scripts", "check-figure-overlap.py") HEAD = '' TAIL = "" def svg(*rects): return HEAD + "".join(rects) + TAIL def rect(cls, x, y, w, h): return f'' def run(body): with tempfile.NamedTemporaryFile("w", suffix=".svg", delete=False, encoding="utf-8") as fh: fh.write(body) path = fh.name try: p = subprocess.run([sys.executable, SCRIPT, "--file", path], capture_output=True, text=True, cwd=ROOT) return p.returncode, p.stdout + p.stderr finally: os.unlink(path) class Overlap(unittest.TestCase): def test_안_겹치면_통과한다(self): code, out = run(svg(rect("group-box", 0, 0, 100, 100), rect("group-box", 150, 0, 100, 100))) self.assertEqual(code, 0, out) self.assertIn("PASS", out) def test_맞닿기만_한_것은_겹친_것이_아니다(self): code, out = run(svg(rect("group-box", 0, 0, 100, 100), rect("group-box", 100, 0, 100, 100))) self.assertEqual(code, 0, out) def test_구역_둘이_겹치면_잡는다(self): code, out = run(svg(rect("group-box", 0, 0, 100, 100), rect("group-box", 50, 50, 100, 100))) self.assertEqual(code, 1) self.assertIn("구역 둘이 겹쳐 그려졌다", out) def test_이음_라벨이_상자에_먹히면_잡는다(self): code, out = run(svg(rect("node-shape kind-service", 100, 100, 120, 60), rect("edge-label-bg", 80, 110, 60, 20))) self.assertEqual(code, 1) self.assertIn("이음 라벨이 상자에 먹혔다", out) def test_구역_이름이_서로를_덮으면_잡는다(self): code, out = run(svg(rect("group-label-bg", 10, 10, 120, 22), rect("group-label-bg", 20, 12, 120, 22))) self.assertEqual(code, 1) self.assertIn("구역 이름이 서로를 덮는다", out) def test_상자_안에_든_상자는_설계다(self): """node-shape 가 group-box 안에 드는 것은 정상이라 잡지 않는다.""" code, out = run(svg(rect("group-box", 0, 0, 200, 200), rect("node-shape kind-service", 20, 20, 80, 40))) self.assertEqual(code, 0, out) def test_겹친_자리의_이름을_말해_준다(self): body = svg(rect("node-shape kind-service", 100, 100, 120, 60), rect("edge-label-bg", 80, 110, 60, 20)) \ .replace(TAIL, '토큰' + TAIL) code, out = run(body) self.assertEqual(code, 1) self.assertIn("토큰", out) class Project(unittest.TestCase): @unittest.skipUnless(os.path.isdir(os.path.join(ROOT, "docs/keycloak/final/assets")), "keycloak 그림이 없다") def test_프로젝트_단위로도_돈다(self): p = subprocess.run([sys.executable, SCRIPT, "keycloak"], capture_output=True, text=True, cwd=ROOT) self.assertIn("FIGURE OVERLAP", p.stdout) if __name__ == "__main__": unittest.main() class UnseenIsNotClean(unittest.TestCase): """「안 겹친다」와 「못 봤다」는 다른 출력이다. 이 검사기는 techviz 렌더러가 붙인 `class` 로만 상자를 알아본다. 손으로 그린 SVG 에는 그 class 가 없어 `boxes()` 가 비고, 겹칠 짝이 없으니 겹침 0 이 나온다. 고치기 전에는 그것을 `그림 182 · 겹친 그림 0` 으로 찍었는데 **실제로 본 것은 18장**이었다. 나머지 164장은 안 겹친 것이 아니라 볼 수 없었던 것이다. """ HAND_DRAWN = ('' '' '' '' '겹친 상자 둘') def test_a_hand_drawn_svg_is_counted_as_unseen(self): _, out = run(self.HAND_DRAWN) self.assertIn("못 본 그림 1", out, out) self.assertIn("본 그림 0", out, out) def test_a_hand_drawn_svg_does_not_read_as_checked(self): """상자가 실제로 겹쳐 있는데도 이 검사기는 답하지 못한다. 그 사실이 보여야 한다.""" _, out = run(self.HAND_DRAWN) self.assertIn("답하지 못한다", out, out) def test_a_techviz_svg_is_counted_as_seen(self): _, out = run(svg(rect("node-shape", 10, 10, 100, 40))) self.assertIn("본 그림 1", out, out) self.assertNotIn("못 본 그림", out, out)