계획서 §검증 후반부를 다시 대조해 미구현 3건을 확인하고 모두 구현했다. 앞선 커밋에서 "미구현 1건" 으로 보고한 것은 §12 불변식 표만 파일로 대조하고 §검증 섹션의 표 두 개는 확인하지 않은 결과였다. - 설치 2단계 요구사항 화면에 자산 URL 방식 항목 추가. 판정은 서버가 아니라 브라우저가 한다 — 서버에서 자기 APP_URL 로 요청하면 loopback 이 vhost·프록시 체인을 우회해 실제 방문자와 다른 답을 낸다. 2단계와 3단계가 같은 판정 함수를 쓰도록 추출했다 - 대시보드가 스스로 프로브를 던져 **저장된** 방식과 대조하고 어긋나면 안내한다. 런타임 값이 아니라 저장값을 보는 이유는, 자가 복구가 이미 전환해 놓았을 때가 바로 알려야 할 상황이기 때문이다 — 봇은 자바스크립트를 실행하지 않아 자가 복구가 닿지 않는다. 알리기만 하고 저장하지 않으므로 클라이언트가 서버 설정을 뒤집지 않는다 - 레이아웃 렌더링 테스트를 두 모드로 추가. 핵심 단언은 두 모드의 DOM 이 완전히 동일하다는 것이다 — 모드가 화면 구조로 새어나가면 확장자 없는 환경에서만 깨지고 그 환경은 개발 중 거의 재현되지 않는다 함께 고친 테스트 격리 결함 4건 (이번 기능과 무관하나 같은 세션에서 발견): - 인스톨러 공유 클래스 로드가 오토로드를 막고 있어, 앱 루트를 임시 디렉토리로 바꾸는 테스트에서 없는 파일을 읽으려다 죽었다 (8건 fatal) - 테스트용 번역 스텁이 실제 구현과의 정의 경쟁에서 이기면 주입된 번역을 무시했다. 클래스 단독 실행은 통과하고 스위트 실행만 실패하던 원인 - 모듈 활성 목록은 "디스크 로드분 ∩ DB 활성분" 인데 부팅 시 테이블이 비어 디스크 스캔이 일어나지 않아, 파일 캐시 잔재가 있을 때만 통과하던 순서 의존 테스트 - 라우트 프로바이더 가드 테스트가 Git 미추적 파일(.env) 존재에 의존해 신규 클론·CI 에서 실패했다. 임시 앱 루트로 격리 또한 일부 테스트가 실제 개발 환경 파일을 삭제·재생성하고 자신의 정리 단계에서 되돌리는데, 그 테스트가 죽으면 되돌아오지 않아 복구 불가능한 유실이 발생한다. 실제로 이번 세션에서 겪었으므로 테스트 부트스트랩에 프로세스 수준 복원 안전망을 추가했다. 검증: 백엔드 344건 / 템플릿 2799건 / 레이아웃 7건 / 브라우저 9건 green, audit 위반 0.
43 lines
1.7 KiB
PHP
43 lines
1.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* 인스톨러 단위 테스트용 lang() 글로벌 스텁
|
|
*
|
|
* public/install/includes/functions.php 의 lang() 헬퍼 대체.
|
|
* 번역이 주입되지 않은 테스트에서는 메시지 키를 그대로 반환해 검증 가능한 형태로 노출한다.
|
|
*
|
|
* ## 왜 번역 주입을 존중하는가
|
|
*
|
|
* `lang()` 은 전역 함수이고 양쪽 정의 모두 `function_exists` 로 가드된다. 즉 같은
|
|
* PHPUnit 프로세스에서 **먼저 로드된 쪽이 이기고** 그 승자가 뒤따르는 모든 테스트 클래스에
|
|
* 적용된다. 이 스텁이 이기면, `$GLOBALS['translations']` 를 채워 실제 문구를 검증하는
|
|
* 테스트(PrivilegedDbAccountGuardTest 등)가 키만 돌려받아 실패한다 — 클래스 단독 실행은
|
|
* 통과하고 스위트 실행만 실패하는 전형적인 격리 결함이다.
|
|
*
|
|
* 그래서 스텁은 번역이 주입돼 있으면 실제 구현과 동일하게 동작하고, 없을 때만 키를
|
|
* 반환한다. 두 사용처의 의도를 모두 만족시키므로 로드 순서가 결과를 바꾸지 않는다.
|
|
*/
|
|
if (! function_exists('lang')) {
|
|
/**
|
|
* 번역 키를 해석한다 (테스트 스텁).
|
|
*
|
|
* @param string $key 번역 키
|
|
* @param array $params 치환할 플레이스홀더 (`:name` 형식)
|
|
* @return string 번역 문자열 또는 키
|
|
*/
|
|
function lang(string $key, array $params = []): string
|
|
{
|
|
global $translations;
|
|
|
|
$message = (isset($translations) && is_array($translations))
|
|
? ($translations[$key] ?? $key)
|
|
: $key;
|
|
|
|
foreach ($params as $placeholder => $value) {
|
|
$message = str_replace(":{$placeholder}", (string) $value, $message);
|
|
}
|
|
|
|
return $message;
|
|
}
|
|
}
|