-
골든 테스트 PASS가 실제 화면 증거는 아닙니다AI Agent/flutter 2026. 7. 7. 21:00728x90반응형

골든은 초록, 실기기는 잘린 두 글자 CI 화면이 온통 초록이었습니다.
unit도, widget도, 골든 테스트까지 전부 통과.
마음 놓고 그날 오후 빌드를 실기기에 올렸습니다.
그런데 빈 상태 화면을 여니 안내 문구 끝 두 글자가 카드 밖으로 삐져나와 있었습니다.
"게시물이 아직 없어요" 정도의 짧은 문장이었는데, 오른쪽 모서리에서 잘려 있었습니다.
다른 기기로 바꿔 껴 봐도 마찬가지였습니다.이상했습니다.
그 화면은 바로 그 오버플로를 막으려고 골든 테스트를 붙여 둔 화면이었거든요.
테스트는 방금도 초록이라고 했는데, 실기기는 깨졌다고 보여주고 있었습니다.
테스트 로그를 다시 훑어도 실패한 항목은 없었습니다.
초록불과 잘린 두 글자를 번갈아 보는데, 둘 중 하나는 분명 거짓말을 하고 있었습니다.
골든 테스트의 초록불은 "이 위젯이 테스트 환경에서 이렇게 그려진다"를 닫아 줄 뿐, "실기기의 실제 폰트와 실제 화면 폭에서도 괜찮다"를 닫아 주지는 않는다는 걸, 그 잘린 두 글자로 다시 배웠습니다.초록불 아래 숨어 있던 폰트
처음엔 제 레이아웃 코드부터 의심했습니다.
카드 padding을 줄여도 보고, 텍스트에maxLines와ellipsis를 붙여도 봤습니다.
그런데 테스트 환경에서는 원래 안 넘쳤으니 고쳐도 티가 안 났고, 실기기에서는 여전히 잘렸습니다.
한참을 헤매다 baseline 이미지를 열어 실기기 캡처와 나란히 놓고 보니, 그제야 글자 모양이 미묘하게 다른 게 보였습니다.
자간도, 글자 폭도 조금씩.
거기서 폰트가 다르다는 걸 눈치챘습니다.
골든 테스트는 기본적으로 실제 앱 폰트를 로드하지 않습니다.
폰트를 따로 넣어 주지 않으면 테스트 러너는 대체 폰트로 글자를 그리는데, 이 폰트의 글자 폭과 줄 높이가 실제 기기에 올라가는 폰트와 다릅니다.
제 baseline은 그 대체 폰트로 찍혀 있었고, 코드도 그 이미지에 맞춰 정직하게 통과하고 있었습니다.즉 테스트는 "가짜 폰트 기준으로는 안 넘친다"를 통과하고 있었던 겁니다.
실제 폰트는 몇 픽셀 더 넓었고, 그 몇 픽셀이 카드 경계에서 두 글자를 밀어냈습니다.
테스트가 거짓말을 한 게 아니었습니다.
제가 그 초록불을 다른 질문의 답으로 읽고 있었을 뿐이죠.testWidgets('빈 상태 문구가 카드 안에 들어온다', (tester) async { // 이 한 줄이 없으면 baseline은 실제 폰트가 아닌 대체 폰트로 찍힙니다. await loadAppFonts(); await tester.pumpWidget(const EmptyStateCard()); await expectLater( find.byType(EmptyStateCard), matchesGoldenFile('empty_state_card.png'), ); });빨간불이 오히려 반가웠던 순간
loadAppFonts()를 넣고 baseline을 다시 찍으니 골든 테스트가 그제야 오버플로를 잡아냈습니다.
빨간불이 뜬 순간이 이상하게 반가웠습니다.
이제야 테스트가 실기기와 같은 걸 보고 있다는 뜻이었으니까요.
그 자리에서 카드 padding을 몇 픽셀 넉넉히 잡아 다시 돌리니, 실기기에서도 문구가 카드 안으로 들어왔습니다.
아까 헛되이 손봤던 그 padding이, 이번엔 실제 폰트를 기준으로 잡히니 제대로 먹힌 거죠.하지만 여기서 멈추지 않고 하나를 더 인정해야 했습니다.
폰트를 맞춰도 골든 테스트가 답하는 질문은 여전히 "이 위젯 하나가 이 크기, 이 조건에서 이렇게 그려진다"까지라는 것.
시스템 폰트 배율을 키운 기기, 가로가 유난히 좁은 기기, 언어를 바꿔 문장이 길어진 화면 — 이건 골든 하나로 닫히는 질문이 아니었습니다.
각각 다른 테스트거나, 결국 실기기에서 한 번은 눈으로 봐야 하는 것들이었습니다.
하나의 초록불이 이 전부를 대신 봐 줄 거라고 믿은 게 애초의 착각이었습니다.초록불을 믿되, 무엇을 닫아 줬는지까지
지금은 테스트가 초록이라고 뜨면 "무슨 주장이 닫힌 거지"를 한 번 더 봅니다.
골든은 렌더 결과를, widget test는 상호작용을, integration test는 흐름을 닫아 줍니다.
세 테스트가 답하는 질문이 다 다른데, 예전의 저는 초록불 하나를 "다 괜찮다"로 뭉뚱그려 읽고 있었습니다.
테스트를 못 믿겠다는 뜻은 아닙니다.
오히려 각 테스트가 무엇까지 책임지는지 알고 나니, 초록불을 볼 때 마음이 더 편해졌습니다.누가 "골든도 있는데 실기기를 왜 또 봐요?"라고 물으면, 이제는 그 잘렸던 두 글자 얘기를 합니다.
테스트가 초록이어도 실제 폰트에서는 넘칠 수 있다고.
그 한 장면만 얘기하면 대개 고개를 끄덕입니다.
저도 그 두 글자를 보기 전까진 똑같이 물었을 테니까요.그 뒤로 빈 상태 화면 PR에는 실기기 캡처를 한 장 같이 붙이는 습관이 생겼습니다.
폰트 배율을 조금 키운 채로요.
골든이 못 보는 자리를, 그 캡처 한 장이 대신 봐 줄 때가 아직도 있어서.원문 기준
원문 기준: https://docs.flutter.dev/testing/overview
원문 본 날짜: 2026-07-01.
728x90반응형'AI Agent > flutter' 카테고리의 다른 글
작은 상태에는 작은 도구가 더 낫습니다 (0) 2026.07.08 보인다는 말보다 캡처 파일이 더 강합니다 (0) 2026.07.08 같은 상태를 두 곳에서 쓰면 둘 중 하나가 거짓말합니다 (0) 2026.07.07 Flutter는 widget을 그리는 게 아니라 element/render tree를 갱신합니다 (1) 2026.07.07 post-frame, microtask, animation tick은 같은 큐가 아닙니다 (0) 2026.07.06