LabHub
배우기 러닝패스 코스

Testing Tools in Practice

Test failure paths and side effects in isolation

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

네트워크와 실제 대기 없이 호출 수·백오프·파일 보존·저장 실패를 재현합니다.

왜 중요한가

정상 요청 한 번의 성공은 경계값과 장애 복구를 보장하지 않습니다. 이 실습은 각 함수의 계약을 작게 구현하거나 테스트한 뒤 실제 실행으로 연결합니다. 코드가 존재하는지나 보고서 문구만 보지 않고 결과·예외·저장 상태를 검사합니다. 앞 단계의 코드를 유지하며 다음 단계로 진행하세요.

단계

  1. /root/work/test-failures-lab/test_service.py에서 fetch가 send의 문자열을 그대로 반환하고 send를 정확히 한 번 호출하는지 테스트하세요. cache는 tmp_path 아래 pathlib.Path로 전달합니다. 첫 준비는 다음 명령으로 합니다.
mkdir -p /root/work/test-failures-lab
cp /opt/fixtures/practice_depth/test-failures-lab/* /root/work/test-failures-lab/
cd /root/work/test-failures-lab
  1. /root/work/test-failures-lab/test_service.py에서 첫 send는 TimeoutError, 두 번째는 'fresh'를 반환하도록 구성하고 fetch가 'fresh'를 반환하는지 확인하세요.
  2. /root/work/test-failures-lab/test_service.py에서 계속 TimeoutError인 send를 넣고 총 3회 호출 뒤 TimeoutError가 전파되는지 확인하세요.
  3. /root/work/test-failures-lab/test_service.py에서 ValueError를 내는 send는 정확히 1회만 호출되고 같은 종류의 예외가 전파되는지 테스트하세요.
  4. /root/work/test-failures-lab/test_service.py에서 모든 send가 TimeoutError일 때 sleep에 전달한 값이 정확히 [0.1, 0.2]인지 검사하세요. 실제로 잠들지 않습니다.
  5. /root/work/test-failures-lab/test_service.py에서 한글 문자열로 성공시킨 뒤 cache 파일을 UTF-8로 읽어 같은 내용이 저장됐는지 확인하세요.
  6. /root/work/test-failures-lab/test_service.py에서 cache에 'old'를 미리 쓴 뒤 send를 계속 실패시키세요. 예외 후 파일 내용이 여전히 'old'인지 확인합니다.
  7. /root/work/test-failures-lab/test_service.py에서 send가 성공해도 cache 쓰기가 실패하면 OSError가 전파되는지 테스트하세요. cache에 tmp_path 디렉터리 자체를 전달하면 결정적으로 쓰기가 실패합니다.

참고

성공 경로의 불필요한 호출을 잡는다

/root/work/test-failures-lab/test_service.py에서 fetch가 send의 문자열을 그대로 반환하고 send를 정확히 한 번 호출하는지 테스트하세요. cache는 tmp_path 아래 pathlib.Path로 전달합니다. 첫 준비는 다음 명령으로 합니다.

mkdir -p /root/work/test-failures-lab
cp /opt/fixtures/practice_depth/test-failures-lab/* /root/work/test-failures-lab/
cd /root/work/test-failures-lab

calls 리스트에 기록하는 함수를 주입하세요. 반환값만 보면 중복 호출을 놓칩니다.

채점은 bash /opt/lab/checks/test-failures-lab/01-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.

한 번 실패한 뒤 복구시킨다

/root/work/test-failures-lab/test_service.py에서 첫 send는 TimeoutError, 두 번째는 'fresh'를 반환하도록 구성하고 fetch가 'fresh'를 반환하는지 확인하세요.

iterator 또는 호출 횟수로 순서를 제어합니다. 테스트 자체에서 실제 네트워크에 접속하지 않습니다.

채점은 bash /opt/lab/checks/test-failures-lab/02-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.

총 시도 횟수와 마지막 예외를 검사한다

/root/work/test-failures-lab/test_service.py에서 계속 TimeoutError인 send를 넣고 총 3회 호출 뒤 TimeoutError가 전파되는지 확인하세요.

재시도 3번과 총 시도 3번은 다릅니다. 이 계약은 최초 요청을 포함해 3회입니다.

채점은 bash /opt/lab/checks/test-failures-lab/03-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.

영구 오류의 재시도를 막는다

/root/work/test-failures-lab/test_service.py에서 ValueError를 내는 send는 정확히 1회만 호출되고 같은 종류의 예외가 전파되는지 테스트하세요.

예외 종류뿐 아니라 calls 길이를 검사해야 무의미한 두 번의 추가 호출을 잡습니다.

채점은 bash /opt/lab/checks/test-failures-lab/04-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.

백오프 수열과 마지막 대기를 확인한다

/root/work/test-failures-lab/test_service.py에서 모든 send가 TimeoutError일 때 sleep에 전달한 값이 정확히 [0.1, 0.2]인지 검사하세요. 실제로 잠들지 않습니다.

sleep 인자에 delays.append를 전달합니다. 마지막 실패 뒤에는 다음 시도가 없으므로 대기도 없어야 합니다.

채점은 bash /opt/lab/checks/test-failures-lab/05-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.

반환값과 디스크 내용을 함께 확인한다

/root/work/test-failures-lab/test_service.py에서 한글 문자열로 성공시킨 뒤 cache 파일을 UTF-8로 읽어 같은 내용이 저장됐는지 확인하세요.

성공 결과만 반환하고 파일 쓰기를 빠뜨린 구현은 반환값 테스트만으로 잡을 수 없습니다.

채점은 bash /opt/lab/checks/test-failures-lab/06-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.

네트워크 실패가 기존 캐시를 지우지 못하게 한다

/root/work/test-failures-lab/test_service.py에서 cache에 'old'를 미리 쓴 뒤 send를 계속 실패시키세요. 예외 후 파일 내용이 여전히 'old'인지 확인합니다.

준비 → 실행과 예외 검사 → 파일 상태 확인 순서로 구성합니다. 파일이 존재하는지만 보지 마세요.

채점은 bash /opt/lab/checks/test-failures-lab/07-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.

저장 실패를 가짜 성공으로 바꾸지 않는다

/root/work/test-failures-lab/test_service.py에서 send가 성공해도 cache 쓰기가 실패하면 OSError가 전파되는지 테스트하세요. cache에 tmp_path 디렉터리 자체를 전달하면 결정적으로 쓰기가 실패합니다.

권한 변경에 의존하지 않는 오류를 만드세요. 성공 문자열 반환만 확인하는 테스트와 다른 책임입니다.

채점은 bash /opt/lab/checks/test-failures-lab/08-contract.sh로 직접 재현할 수 있습니다. 파일 저장 후 다시 실행하세요.