Skip to content

테스트 기준선 장부 — 비결정성 분류·소스 모양 검사 전환 목록·검사 자산 인벤토리 (이슈 #1280 G02)

v0.18.0 리팩터링 동안 "테스트가 빨간불인 이유가 회귀인가, 환경인가" 를 가르기 위한 장부다. 기준 main 57fd2bb4(2026-09-07). 정책·도구 사용법은 test-audit.md "줄바꿈(LF) 정책과 결정성 도구", 총괄은 v0.18.0 아키텍처 리팩터링 총괄 §9.

1. 시간·식별자·타이머 비결정성 분류 (단위 338+25+6 파일 · e2e 8 · 오류 재현 38 케이스)

분류자리판정처리
실제 시계가 기대값에 닿음tests/react/workoutDraftArchive.test.mjs (CI run 34042079441 실패 3건)픽스처 날짜를 달력이 추월해소 — PR #1278 이 Date 전용 mock 으로. dateIndependence.test.mjs 가 ±400일에서 같은 결과를 증명
부모·자식 프로세스 시계 결합tests/react/landingPreflightGate.test.mjs (랜딩 잠금 CLI)자식 CLI 가 실제 벽시계로 만료 판정. "지금 − 24h" 로 만든 만료 픽스처는 부모 시계 이동 시 어긋남해소 — 만료 픽스처를 절대 과거(2000-01-01)로. "방금 만든 기록" 은 실제 시계 그대로(본성상 결합, 증명 대상 아님)
실제 서버 시계 (고정 불가)error-cases/CASE-013(토큰 만료 Date.now()/1000 − 30), CASE-019(어제 날짜 seed)실제 인증·DB 를 쓰는 e2e — 브라우저만 과거로 고정하면 서버와 어긋남허용, 사유 기록: 상대 시각 유지. 월초·연초 경계는 seed 날짜를 화면에서 명시 선택(test-audit "브라우저 E2E")
벽시계 폴링error-cases/CASE-029(10초 deadline 루프), error-cases/support/fixture.mjs(idle heartbeat)결과가 아니라 대기 상한허용(로그·대기용). 상한은 CI 부하에 따라 흔들릴 수 있음 — waitForTimeout 32곳/10파일은 UI 담당이 상태 대기(expect.poll)로 바꿀 후보
1회용 식별자e2e 8파일의 Date.now()/randomUUID()(계정 이메일·operationId 생성)기대값과 무관허용. 예측 가능한 값이 필요하면 tests/support/ids.mjs
손으로 만든 가짜 타이머tests/react/followingStore.test.mjs fakeTimers()결정적(주입)유지. 새로 쓸 때는 tests/support/scheduler.mjs
브라우저 시각 고정Playwright page.clock·timezoneId 사용 0건화면 테스트가 실행 날짜에 노출도구 제공 tests/support/browserClock.mjs(Date 만 고정, Asia/Seoul). 적용은 e2e/** 담당(UI 층)

제품 코드의 주입 지점 (이 트랙은 src/** 를 만지지 않는다 — 담당 이슈에 인계)

파일비결정 호출지금 주입 가능?인계
src/react/services/workoutDraftCache.tsnow 인자(있음) · 자동저장 globalThis.setTimeout(887)시각 예 / 타이머 아니오S08 (Draft lifecycle·Clock)
src/react/services/workoutLocalCacheDb.ts withIdbTimeout(35)setTimeout아니오 (timeoutMs 만)S08 / S02
src/react/services/pendingWorkoutSaves.tsnow = () => Date.now()(661)— (그대로 씀)
src/react/services/appErrorReporter.tsnow?(82) 예 · crypto.randomUUID(276) · setTimeout(332)시각만 예A07 (lifecycle) 또는 보고 담당
src/react/services/directWorkoutWrite.ts(43) · barbelicRepository.ts(403) · exerciseIdentity.ts(10)crypto.randomUUID아니오S02 (outbox 식별자 공장), D03
src/react/services/barbelicMappers.ts(603·611·691)new Date().getFullYear() 기본 인자호출자가 넘기면 예A08/UI 매퍼 — asOf 를 항상 넘기게
src/react/controllers/keyedRequestQueue.ts(61)options.sleep

2. 소스 모양 검사 — 유지 목록과 행동 검사 전환 목록

소스 파일을 읽어 문자열·정규식·슬라이스로 단언하는 테스트 72 파일(new URL("../../src/…") + readFile). 감사 기준 (test-audit "테스트 작성 원칙")대로 변수명 하나에 깨지고 실제 버그는 못 잡는 것은 전환 대상, import·권한·보안 경계 를 지키는 것은 유지한다. 전환은 해당 코드를 옮기는 담당 이슈가 그 PR 에서 한다(옮기면 어차피 앵커가 깨진다) — 새 행동 검사가 같은 보증을 하면 pending-changes.json 에 신고하고 소스 모양 단언을 지운다.

2-1. 유지 (보안·권한·import 경계 — 정적 검사가 곧 계약)

파일지키는 경계
tests/react/screenRpcContracts.test.mjs화면 RPC 계약 표면·권한(anon 금지 등)
tests/react/appErrorReporter.test.mjs오류 보고 경로가 정책 게이트 밖으로 문구를 내지 않음
tests/react/appErrorBoundary.test.mjs · userErrorPolicy.test.mjspublicErrorMessage 봉인(문구 = 기록)
tests/react/plannedSessionRevisionContract.test.mjs · recordingProfileRoundTrip.test.mjs · perceivedRpeRoundtrip.test.mjs서버 계약 필드가 앱 직렬화에서 빠지지 않음
tests/react/clientErrorLoggingSqlContract.test.mjs · statsRefreshJobs.test.mjs · statsCentralizationPhase4_3/4_4.test.mjs · clientStrengthFallback.test.mjsservice_role·RLS·통계 단일 작성자 경계
tests/react/completedWorkoutWriteBoundary.test.mjs · workoutWriteSurvival.test.mjs완료 기록 쓰기 단일 파이프라인(직접 RPC 부활 금지)
tests/react/appContainer.test.mjs(법률 문서·브랜드·location.assign 부재) · adminHealthReport.test.mjs · localAuthAdminE2eSafety.test.mjs · eslintGate.test.mjs · limitsRegistry.test.mjs · offlineServiceWorker.test.mjs · deploymentPipeline.test.mjs관리자·배포·한도·오프라인 규칙의 정적 계약
tests/auth/*.test.mjs 6파일PKCE·번들 ID·콜백 경로·provider 설정
tests/react/mobileCssBoundaries.test.mjs · homeFragmentBoundaries.test.mjsCSS·모듈 import 경계

2-2. 전환 (구현 세부를 박제 — 코드를 옮기는 이슈가 행동 검사로 대체)

파일박제한 것대체할 행동 검사담당
test/onDemandDataLoading.test.mjs(16 파일 읽음) · tests/react/homeBootLoadingOrder.test.mjs · homeFragmentCoordination.test.mjs · tabDataWarming.test.mjs로딩 순서·함수 이름·호출 위치부팅/탭 진입 시 실제 요청 순서·중복 없음(가짜 전송 기록)A08 (resource cache)
tests/react/logTableMonthCache.test.mjs · calendarReadModelMapper.test.mjs · mobileExperienceMapperModules.test.mjs캐시 키·매퍼 모듈 모양같은 입력→같은 읽기 모델, 무효화 뒤 재조회A08
tests/react/viteServices.test.mjs · staleChunkRecovery.test.mjs · test/performanceBudgets.test.mjsVite 설정 문자열·청크 이름빌드 산출물 검사(dist 매니페스트)로U(빌드)·G05
tests/react/authDegradedBootstrap.test.mjs · authConnectivityCoordination.test.mjs · connectivityController/Runtime/Wire.test.mjs · authSessionFailurePolicy.test.mjs · onboardingCommands.test.mjs인증·연결 상태 전이의 코드 위치AuthSessionRuntime/ConnectivityRuntime 상태 기계 행동(가짜 시계·전송)A07
tests/react/activeWorkoutCommands.test.mjs · activeWorkoutEntryPolicy.test.mjs · completedWorkoutCommands.test.mjs · completedWorkoutEditCutover.test.mjs · completedSessionRecoveryScenarios.test.mjs · workoutFinishBackResumeDraft.test.mjs명령 배선·JSX 앵커headless editor 명령의 입력→상태S01/S03
tests/react/appShellSnapshotIntegrationContract.test.mjs · appShellSnapshotProjection.test.mjs · appShellSnapshotRemoteStatus.test.mjsapp shell 스냅샷 코드 위치app shell 상태 투영 행동A01
tests/react/adminUiWriteContract.test.mjs · adminAtomicCatalogOperations.test.mjs · exerciseCatalogStore.test.mjs · exerciseCatalogClassification.test.mjs · exerciseFamilyBackfill.test.mjs · exerciseBodyweightMetadata.test.mjs · ownedCustomExerciseArchive.test.mjs관리자·카탈로그 코드 모양카탈로그 동기화 페이지 적용·관리자 쓰기 결과D03·U(관리자)
tests/react/measuredPrFrontendContract.test.mjs · prHomeRankHydration.test.mjs · desktopVolumeExactStats.test.mjs · daySummarySetPurposeBoundary.test.mjs · test/statisticalLoadRounding.test.mjs통계 표시 코드 모양oracle 코퍼스(tests/fixtures/stats-oracle) 대조D01
tests/react/readImportContractHardCut.test.mjs · wodupStartImportFunction.test.mjs · test/wodupPlaceholderResolution.test.mjs · leanModelHardCut.test.mjs · test/runtimeSchemaValidation.test.mjs · test/appScreenRpcContract.test.mjs(계약 표면 부분은 유지)인입·RPC 어댑터 코드 모양인입 함수 입력→출력, RPC 어댑터 왕복D03·D13
tests/react/ownDataReplica.test.mjs · ownDataReplicationJob.test.mjs복제 작업 코드 위치기기 사본 복원 행동S05
tests/react/screenRpcHotPath.test.mjs · mobileGamificationDesignWiring.test.mjs · onboardingBodyValidation.test.mjs핫패스·디자인 배선·검증 정본 위치화면 행동/검증 함수 입력→출력UI 담당

3. 검사 자산 인벤토리 — G05 장부 입력 (native / API / provider / CSS / 브라우저)

검사위치방식재사용
nativeiOS/Android 네이티브 인증 브리지 계약(PKCE·번들·콜백 중복 방어)tests/auth/iosNativeAuthContract.test.mjs · androidNativeAuthContract.test.mjs가짜 브리지에 대한 행동 검사유지, native 담당 장부에 등재
native스플래시 소유권·스토어 제출 메타tests/react/nativeSplashOwnership.test.mjs · iosStoreSubmissionContract.test.mjs행동 + 소스 모양 혼합유지
APIRPC 계약 표면·버전·위생tests/react/screenRpcContracts.test.mjs · rpcContractsAndConventions.test.mjs · rpcSurfaceHygieneContract.test.mjs · test/rpcContractVersioning.test.mjs · test/appScreenRpcContract.test.mjs계약 카탈로그 대조유지 — D03 typed 경계의 게이트
API앱 계정 권한(anon 함수 0·TRUNCATE 류 0)tests/react/appRolePrivilegesContract.test.mjs · serviceRoleReadbackContract.test.mjs · schemaRls.test.mjsschema.sql 상태 검사유지
provider소셜 provider 서버 활성 프로브scripts/check-social-provider-config.mjs실제 네트워크(302 판정)릴리스 게이트에서만
CSS죽은 클래스 래칫·동적 접두사scripts/check-dead-css.mjs · tests/react/deadCssGate.test.mjs정적 스캔유지 — U(CSS) 정리 트랙의 전/후 지표
CSS디자인 마커·프리미티브tests/react/designContract.test.mjs · designDeliveryPrimitives.test.mjs소스 모양유지(디자인 계약)
브라우저뷰포트 기하·하단 여백·도크e2e/viewport-matrix.spec.mjs · bottom-clearance.spec.mjs · dock-geometry.spec.mjs실제 브라우저 + 로컬 스택유지, waitForTimeout → 상태 대기로 전환 후보
브라우저CRUD·빈 계정·유산소 저니e2e/crudRoundtrip.e2e.mjs · emptyAccountJourney.e2e.mjs · cardioMinOneField.e2e.mjs실제 브라우저유지
브라우저오류 재현 38 케이스error-cases/CASE-*/regression.spec.mjs실제 브라우저·인증유지. 오프라인/abort/quota 는 단위(faultInjectionTools)에만 있고 브라우저 저니에는 없음 — S02/S04 가 필요 시 추가
DBpgTAP 108 파일(두 연결 1: stats_refresh_statement_timeout.test.sql dblink)supabase/tests/database/실 DB유지(D13). 두 연결 경합은 tests/db/ 도구로

4. 이 트랙이 남긴 도구와 검증 명령

도구파일검증 명령
고정 시계·순번 UUID·수동 스케줄러·격리 저장소tests/support/clock.mjs ids.mjs scheduler.mjs storage.mjsnode --import tsx --test tests/react/testSupportDeterminism.test.mjs
날짜 독립성 증명(±400일)tests/support/clockShift.mjs · tests/react/dateIndependence.test.mjsnode --import tsx --test tests/react/dateIndependence.test.mjs
줄바꿈 정책.gitattributes · scripts/check-utf8.mjs · scripts/normalize-line-endings.mjsnode scripts/check-utf8.mjs · node --import tsx --test tests/react/lineEndingPolicy.test.mjs
저장 실패 주입tests/support/faultInjection.mjsnode --import tsx --test tests/react/faultInjectionTools.test.mjs
두 DB 연결 barriertests/db/support/pgSessions.mjs · tests/db/concurrencyBarrier.test.mjsBARBELIC_DB_SANDBOX=<ci:local 샌드박스> node --import tsx --test tests/db/concurrencyBarrier.test.mjs (대상 없으면 skip = 미실행)
통계 oracle 코퍼스tests/support/statsOracle.mjs · tests/fixtures/stats-oracle/node --import tsx --test tests/react/statsOracleTools.test.mjs
owner 전환 픽스처tests/support/ownerSwitch.mjsnode --import tsx --test tests/react/ownerSwitchFixture.test.mjs
브라우저 시각 픽스처tests/support/browserClock.mjsnode --import tsx --test tests/react/browserClockFixture.test.mjs (Playwright 적용은 e2e/** 담당)

미실행·미연결로 남긴 것: tests/db/ 는 CI 레인에 연결되지 않았다(.github/** 는 HQ 통합 슬롯). CI 의 verify 잡에서는 대상이 없어 skip 으로 집계된다 — 성공으로 합산하지 않는다. 로컬 실행 기록은 작업 기록 §5 에 있다.