← 홈Setup Tip

Setup Tip

Setup Tip — 한 OS에서만 실패한다고 아직 OS 버그는 아니다

CI에서 macOS 작업만 계속 실패했고, 다들 심볼릭 링크 처리 차이를 의심했다. 제안된 수정은 macOS에서만 경로를 실제 경로로 풀어 주는 분기였는데, 그건 링크를 따라가지 않도록 막아 둔 안전 검사를 우회하는 변경이었다. 실제 원인은 테스트 픽스처가 실제 설치 과정이 남기는 버전 표식을 만들지 않은 것이었고, 같은 테스트를 리눅스에서 단독으로 돌리자 똑같이 실패했다. OS 분기로 고치기 전에, 가지고 있는 OS에서 같은 조건으로 먼저 재현한다.

상황

PR 하나의 CI에서 macOS 작업만 계속 빨간불이었다. 리눅스 작업은 초록이었다. 실패한 테스트는 설치된 관리 파일 묶음을 복구하는 기능을 확인하는 것이었고, 오류 메시지는 "검증된 관리 스냅숏이 아니다"였다. macOS의 임시 디렉터리가 심볼릭 링크 아래에 있다는 건 잘 알려진 사실이라, 다들 자연스럽게 링크 처리 차이를 의심했다.

그럴듯했던 수정

제안된 수정은 macOS에서만 대상 경로를 실제 경로로 풀어서 비교하는 분기였다. 테스트는 아마 통과했을 것이다. 하지만 그 코드에는 링크를 따라가지 않도록 일부러 막아 둔 검사가 있었다. 링크를 통해 엉뚱한 위치를 덮어쓰지 않게 하려는 안전장치다. OS 분기 하나가 테스트를 초록으로 만드는 대신, 한 플랫폼에서만 그 안전장치를 꺼 버리는 셈이었다. 이 변경은 반려했다.

실제 원인

오류 메시지가 말한 건 OS가 아니라 "검증되지 않았다"는 사실이었다. 실제 설치 과정은 관리 디렉터리 안에 버전 표식 파일을 남기고, 복구 기능은 그 표식이 있어야 스냅숏을 믿는다. 테스트 픽스처는 이 파일을 만들지 않았다. 리눅스에서 그 테스트 하나만 따로 돌리자 똑같은 메시지로 실패했다. 리눅스 작업이 초록이었던 건 다른 조건 때문에 그 경로를 지나가지 않았을 뿐이었다. 픽스처가 버전 표식을 쓰도록 고치자 두 OS 모두 통과했다.

팁: 오류 메시지가 가리키는 검사부터 읽는다

한 OS에서만 실패하면 OS 차이부터 떠올리기 쉽다. 먼저 오류 메시지가 어떤 검사에서 나왔는지 코드에서 찾고, 그 검사가 무엇을 요구하는지 읽는다. 요구 조건이 OS와 무관하다면 원인도 OS와 무관할 가능성이 크다.

팁: 가진 OS에서 같은 조건으로 재현한다

실패한 테스트를 이름으로 골라 단독으로, 가능하면 깨끗한 임시 디렉터리에서 돌린다. 다른 OS에서도 실패하면 플랫폼 문제가 아니다. 통과한다면 그때 두 환경에서 그 검사에 들어가는 값, 예를 들어 실제 경로와 파일 목록을 나란히 출력해 어디서 갈리는지 본다.

팁: 안전 검사를 느슨하게 하는 OS 분기는 의심한다

if macOS로 시작하는 수정이 링크 따라가기, 권한 확인, 경로 검증 같은 검사를 그 플랫폼에서만 완화한다면 거의 항상 잘못된 방향이다. 테스트 환경을 실제 설치와 같게 만들거나, 검사가 정말 틀렸다면 모든 플랫폼에서 같은 방식으로 고친다.

체크리스트

1) 오류 메시지가 나온 검사를 코드에서 찾는다. 2) 그 검사의 요구 조건이 OS와 관련 있는지 본다. 3) 가진 OS에서 그 테스트를 단독으로 돌린다. 4) 픽스처가 실제 설치가 남기는 파일을 모두 만드는지 확인한다. 5) 안전 검사를 한 플랫폼에서만 끄는 수정은 받지 않는다.