콘텐츠로 이동

NextPDF 테스트 피라미드

Spec: ISO/IEC/IEEE 29119-4 Spec: ISO/IEC 25010 Evidence: Test-backed PHPStan: Level 10

NextPDF에는 한 종류의 테스트만 있는 것이 아닙니다. 다섯 개의 계층이 있으며, 각 계층은 엔진에 대한 서로 다른 질문에 답합니다. PDF는 단위 테스트를 통과하고도 디스크에 기록된 파일로는 구조적으로 깨져 있을 수 있기 때문입니다. 이 페이지는 다섯 가지 계층과 각 계층이 무엇을 증명해야 하는지를 명확히 정리합니다.

PDF 엔진은 실패 가능 영역이 비정상적으로 넓습니다. 같은 코드 경로가 함수 관점에서도, 바이트 스트림 관점에서도 올바르지만, 규격을 준수하는 리더가 거부하는 파일을 생성할 수 있습니다. 또한 페이지 나눔에서만 미묘하게 잘못 렌더링되는 파일을 만들 수도 있습니다. 엔진을 하나의 세분화 수준에서만 테스트하면 정확히 그 수준에 대한 신뢰만 얻을 뿐 그 밖의 것에 대해서는 아무것도 얻지 못합니다.

표준 문헌은 이 점을 분명히 합니다. 명세 기반 및 구조 기반 테스트 설계 기법은 서로 관련이 없으며, 테스트 전략은 둘 이상의 기준을 사용하되 최소한 하나의 기능적 기준과 하나의 구조적 기준을 포함하도록 권장됩니다(ISO/IEC/IEEE 29119-4, Annex A). 단일 계층은 좋은 전략의 축소판이 아닙니다. 그것은 별개의 전략이며, 불완전한 전략입니다.

NextPDF의 테스트는 바닥에서 정점까지 다섯 개의 계층으로 구성됩니다:

  1. 단위 — 하나의 클래스 또는 함수를 격리해 테스트합니다. 넓은 바닥입니다.
  2. 통합 — 모듈 경계를 가로질러 협력하는 단위들을 테스트합니다.
  3. 구조 — 생성된 PDF 객체 그래프, 상호 참조 테이블, 트레일러가 올바른 형식을 갖추고 규격을 준수하는지 확인합니다.
  4. 시각 — 렌더링된 페이지가 명시된 허용 오차 범위 내에서 승인된 참조와 일치하는지 확인합니다.
  5. 골든 — 최종 출력의 의도하지 않은 변동을 잡아내는 고정된 종단 간 픽스처입니다. 정점입니다.

각 계층은 그 아래 계층이 증명할 수 없는 것을 증명합니다. 그중 어느 것도 장식용이 아닙니다. 피라미드 형태는 수량을 나타냅니다 — 저렴한 단위 테스트는 많고 비싼 종단 간 테스트는 적습니다 — 중요도를 나타내는 것이 아닙니다.

이 계층들은 추상적인 이상이 아니라 실제로 존재합니다. 저장소의 PHPUnit 구성은 각 계층을 디렉터리와 일대일로 매핑되는 명명된 테스트 스위트로 선언합니다. 따라서 계층은 슬라이드 속의 라벨이 아니라, 러너로 지정해 실행할 수 있는 위치입니다. 시니어 엔지니어에게 익숙할 스위트로는 Unit, Integration, Golden, Snapshot, Reproducibility, Conformance, Standards, 그리고 Performance가 있으며, 각각 고유한 실행 프로파일(격리, 시간 버킷, 그리고 지속적 통합에서 기본으로 실행되는지 여부)을 가집니다.

이 분리는 의도적입니다. 빠른 하위 계층(Unit)은 테스트당 1초 예산으로 변경이 있을 때마다 실행됩니다. 더 느리고 환경에 민감한 계층들 — 시각 렌더링, 전체 규격 준수, 성능 —은 선택적으로 실행하거나 야간에 실행됩니다. 이렇게 하면 더 깊은 검사를 포기하지 않으면서도 일반 경로를 빠르고 결정론적으로 유지할 수 있습니다. 엄격한 타입 적용이 전체 스택의 토대를 이룹니다. 엔진은 오류 예산을 0으로 고정하고 Spec: PHPStan, Level 10 로 분석되므로, 광범위한 부류의 결함은 애초에 테스트에 도달하지 않습니다.

  1. Tier 1 of 5 Unit Isolated behaviour of a single class or function; the broad base.
  2. Tier 2 of 5 Integration Collaborating units across a module boundary.
  3. Tier 3 of 5 Structural The emitted PDF object/xref structure is well-formed and conformant.
  4. Tier 4 of 5 Visual Rendered output matches an approved reference within tolerance.
  5. Tier 5 of 5 Golden End-to-end byte/lossless fixtures pinned as the contract; the apex.
NextPDF 의 다섯 가지 테스트 계층, 바닥에서 정점까지. 단위는 넓고 빠른 바닥이며, 위쪽의 각 계층은 아래 계층이 증명할 수 없는 속성을 증명하여 정점의 골든 종단 간 픽스처에 이릅니다. 너비는 수량에 대한 힌트일 뿐이며 — 중요도를 매기지 않습니다.

Evidence: Test-backed 다섯 개의 스위트는 엔진 구성에 선언된 PHPUnit 테스트 스위트로 존재하며, 각각 자체 디렉터리와 실행 프로파일에 묶여 있습니다. 이 페이지의 계층 용어는 테스트 인프라가 사용하는 용어와 동일합니다.

Evidence: Standard-backed 둘 이상의 계층을 두는 이유는 Spec: ISO/IEC/IEEE 29119-4, Annex A 에 근거합니다: 커버리지 기준이 모두 서로 관련되는 것은 아니며, 전략은 기능적 기법과 구조적 기법을 결합하도록 권장됩니다. 특히 같은 부속서는 커버리지 기준 사이의 포섭 순서가 결함을 노출하는 능력인 테스트 효과성에 대해 아무런 시사점도 주지 않는다고 언급합니다 (ISO/IEC/IEEE 29119-4, §C.2.4). “더 많은 커버리지”는 “더 나은 테스트”와 같다는 주장이 아닙니다.

Evidence: Standard-backed 어떤 속성을 증명할지에 대한 선택은 Spec: ISO/IEC 25010 의 제품 품질 특성과 연결됩니다: 기능적 정확성(단위, 통합), 그리고 PDF를 다운스트림에서 실제로 사용 가능하게 만드는 파일 수준 속성 (구조, 시각, 골든)입니다. 품질 모델은 서로 다른 특성이 서로 다른 사용 맥락에서 중요하다는 점을 명시합니다.

계층들은 엔진 자체 스크립트에서 지정해 실행할 수 있습니다. 포매터 하나에 대한 변경은 하위 계층에서 검증됩니다. 문서 파사드에 대한 변경은 여러 계층에 걸쳐 검증됩니다:

<?php
declare(strict_types=1);
// Tier 1 — Unit: one unit, isolated, fast.
// composer test:unit → phpunit --testsuite Unit
// Tier 2 — Integration: collaborating units across a boundary.
// composer test:integration → phpunit --testsuite Integration
// Tier 3 — Structural: the emitted PDF object graph is well-formed.
// vendor/bin/phpunit --testsuite Conformance
// Tier 4/5 — Visual + Golden: rendered/serialized output vs a pinned
// reference (golden is byte/structure-pinned, never auto-updated).
// vendor/bin/phpunit --testsuite Golden
// A change to the document facade touches every API, so the routing
// guidance escalates it from "unit only" to the full unit + integration
// surface — the tier you run is a function of blast radius, not habit.

예제의 핵심은 명령어가 아니라 라우팅 로직입니다. 실행할 계층은 그 변경이 무엇을 깨뜨릴 수 있는지에 따라 선택됩니다. 인프라는 각 계층을 일급 대상으로 만들며, 개별적으로 실행할 수 있게 합니다.

피라미드는 종종 순위로 읽힙니다 — 단위 테스트는 중요도가 가장 낮기 때문에 바닥에 있고, 종단 간 테스트는 가장 중요하기 때문에 꼭대기에 있다는 식으로(또는 그 반대로). 둘 다 아닙니다. 세로축은 대략 비용과 수량을 나타냅니다: 빠르고 저렴한 단위 테스트가 많이 모여 넓은 바닥을 이루고, 위로 갈수록 더 적고 더 느리며 더 높은 충실도를 가진 테스트가 자리합니다. 골든 테스트가 단위 테스트보다 “더 나은” 것은 아닙니다. 골든 테스트는 다른 실패를 더 늦게, 더 높은 비용으로 잡아내며, 그 아래의 수천 가지 빠른 검사를 대신하기에는 좋지 않은 대체물입니다.

두 번째 오해는 높은 커버리지 수치가 피라미드가 견고하다는 뜻이라고 보는 것입니다. 그렇지 않습니다. 커버리지는 탐지가 아니라 실행을 측정합니다. 표준은 커버리지 순서를 결함 발견 능력과 동일시하는 것을 명시적으로 거부합니다. 바로 그 간극을 드러내기 위해 변이 테스트가 존재합니다.

이 페이지는 전략의 현재 결과가 아니라 형태와 의도를 설명합니다. 테스트 수, 커버리지 백분율, 변이 점수는 여기서 의도적으로 제외했습니다. 그것들은 지속적 통합 산출물에서 생성되는 살아 있는 품질 신호입니다. 현재 수치는 빌드와 함께 게시됩니다. 본문에 고정해 두면 조용히 낡아 버릴 것입니다. 명시된 단 하나의 수치 — PHPStan Level 10 —은 측정값이 아니라 엔진의 정적 분석 구성에서 확인할 수 있는 안정적인 구성 사실입니다.

계층 이름은 안정적인 아키텍처 용어입니다. 스위트의 정확한 집합과 그 실행 프로파일은 엔진과 함께 진화하며 테스트 구성에서 관리합니다. 이 설명과 어긋나는 경우에는 테스트 구성이 권위를 가집니다. 이 페이지는 특정 통과율을 주장하지 않으며 다른 어떤 라이브러리의 테스트 전략과도 비교하지 않습니다.

  • 골든 파일 테스트 — 정점 계층이 참조 출력을 고정하고 검증의 정직성을 유지하는 방법.
  • 변이 테스트 설명 — 커버리지 수치가 이 계층들의 테스트가 실제로 작동함을 증명하지 못하는 이유.
  • 어디서나 엄격한 타입 — PHPStan Level 10이 어떤 계층이 실행되기도 전에 한 부류의 결함을 제거하는 방법.
  • 테스트 계층 — 한 종류의 속성(예를 들어, 단위 동작 또는 구조적 유효성)을 증명하는 전략의 한 단계입니다. NextPDF는 다섯 개를 사용합니다.
  • 구조 테스트 — 반환 값만 확인하는 것이 아니라, 생성된 PDF의 객체 그래프, 상호 참조 테이블, 트레일러가 올바른 형식을 갖추고 규격을 준수하는지 확인하는 검사입니다.
  • 시각 테스트 — 렌더링된 페이지가 명시된 허용 오차 범위 내에서 승인된 참조 이미지와 일치하는지 확인하는 검사입니다.
  • 골든 테스트 — 절대 자동으로 갱신되지 않는 고정된 참조 출력과 대조하는 종단 간 검사입니다. 즉, “출력이 변하지 않았다”는 계약입니다.
  • 테스트 효과성 — 테스트 집합이 결함을 노출하는 능력으로, ISO/IEC/IEEE 29119-4 는 이를 커버리지와 구별합니다. 약어 참고: MSI(Mutation Score Indicator)는 변이 테스트 페이지에서 정의됩니다.
  • PHPStan Level 10 — 가장 엄격한 정적 분석 수준입니다. NextPDF는 오류 예산을 0으로 고정한 채 이를 실행합니다.