Skip to content

Latest commit

 

History

History
147 lines (104 loc) · 6.05 KB

File metadata and controls

147 lines (104 loc) · 6.05 KB

테스트 가이드

kma 테스트는 실제 날씨값에 의존하지 않고 KMA 특유의 실수를 잡도록 설계합니다.

기본 테스트

python -m pytest

기본 테스트는 다음 조건을 지켜야 합니다.

  • 네트워크 호출 없음
  • 결정적 결과
  • DATA_GO_KR_SERVICE_KEY 없이 실행 가능
  • 요청 파라미터, 응답 파싱, 변환, 예외 동작 중심
  • serviceKey, authKey, key 원문이 모델 metadata, 예외, repr, fixture에 남지 않음

현재 테스트 범위

  • tests/test_client.py: 단기예보 typed client 요청 파라미터, fake session 응답 파싱, result code 매핑, 잘못된 응답 처리.
  • tests/test_datagokr.py: data.go.kr 범용 service/operation 호출, 기상청 전용 dataset 카탈로그 86개와 gateway operation 160개, pagination helper, sanitized cache key, 중기예보 typed row wrapper와 최신 tmFc 선택, 주요 서비스 helper, 해수욕장 날씨 helper.
  • tests/test_pydantic_models.py: public 응답 모델의 Pydantic 직렬화, frozen 동작, 좌표 검증.
  • tests/test_apihub.py: APIHub 범용 요청, typ02/openApi helper, 탐색 HTML parser, TXT table parser, 이미지 header parser.
  • tests/test_apihub_endpoints.py: 생성된 APIHub 470개 함수형 래퍼, sample parameter 적용, 이름 없는 query string 보존.
  • tests/test_apihub_generator.py: APIHub 보조 metadata 페이지가 실패해도 생성기가 본문 endpoint 수집을 유지하는지 검증.
  • tests/test_live_services.py: .env.local 인증키와 KMA_RUN_LIVE=1이 있을 때만 실행되는 APIHub/data.go.kr 실서버 smoke test.
  • tests/test_codes.py: SKY/PTY 라벨, PCP/SNO 보존, parse_amount().
  • tests/test_enums.py: public enum wire value, enum-aware code helper, 모델의 enum/category helper.
  • tests/test_grid.py: 알려진 격자 변환점과 좌표 범위.
  • tests/test_locations.py: LatLon, GridPoint, mapping 기반 location= 표준화와 모호한 입력 거부.
  • tests/test_public_api.py: package-level __all__과 권장 public API 정렬.
  • tests/test_time_utils.py: KST 변환, endpoint별 base time 선택, 발표주기 기반 cache 만료 시각.
  • tests/test_timeline.py: ForecastItem row를 ForecastTimepoint 시간축 객체로 피벗하는 helper.
  • tests/test_cli.py: CLI 인자 처리와 JSON/text 출력 형태.

실제 API 테스트

실제 API 호출 테스트는 반드시 명시적 marker를 사용합니다.

import os
import pytest

pytestmark = pytest.mark.integration

@pytest.mark.skipif(os.getenv("KMA_RUN_LIVE") != "1", reason="set KMA_RUN_LIVE=1")
@pytest.mark.skipif(not os.getenv("DATA_GO_KR_SERVICE_KEY"), reason="DATA_GO_KR_SERVICE_KEY is not set")
def test_live_now_shape():
    ...

실제 API 테스트는 KMA_RUN_LIVE=1과 해당 인증키가 모두 있을 때만 실행합니다. 정확한 날씨값이 아니라 구조와 타입을 검증합니다.

좋은 검증:

  • 잘 알려진 격자에서 응답이 비어 있지 않음
  • datetime 필드가 KST aware임
  • nx, ny가 요청값과 일치함
  • category가 문자열임
  • 응답 URL이나 metadata에 인증키 원문이 없음

피해야 할 검증:

  • 정확한 기온
  • 정확한 하늘상태나 강수형태
  • API 계약이 보장하지 않는 정확한 row 개수

수동 smoke test

data.go.kr Decoding 키가 있을 때:

DATA_GO_KR_SERVICE_KEY=<decoded key> kma now --nx 60 --ny 127
DATA_GO_KR_SERVICE_KEY=<decoded key> kma forecast --lat 37.5665 --lon 126.9780

PowerShell:

$env:DATA_GO_KR_SERVICE_KEY="<decoded key>"
kma now --nx 60 --ny 127

APIHub 키가 있을 때:

$env:KMA_APIHUB_AUTH_KEY="<APIHub authKey>"
kma apihub /api/typ01/url/wrn_reg.php --param tmfc=0

로컬에서만 쓰는 인증키는 .env.local에 둘 수 있습니다. 이 파일은 .gitignore에 포함되어 커밋되지 않습니다.

KMA_APIHUB_AUTH_KEY=<APIHub authKey>
DATA_GO_KR_SERVICE_KEY=<data.go.kr decoded service key>
DATA_GO_KR_SERVICE_KEY=<data.go.kr decoded service key>

클라이언트의 from_env()는 process env를 우선하고, 없으면 .env, .env.local을 읽습니다. 같은 key가 여러 로컬 파일에 있으면 가까운 디렉터리 값이 우선하고, 같은 디렉터리에서는 .env.local이 .env보다 우선합니다. data.go.kr 계열은 DATA_GO_KR_SERVICE_KEY 또는 DATA_GO_KR_SERVICE_KEY, APIHub 계열은 KMA_APIHUB_AUTH_KEY 또는 KMA_APIHUB_KEY를 사용합니다. 복사/붙여넣기 공백은 생성자에서 제거합니다.

실제 서버 integration 테스트는 의도치 않은 네트워크 호출을 막기 위해 marker와 KMA_RUN_LIVE=1을 함께 요구합니다.

$env:KMA_RUN_LIVE="1"
python -m pytest -m integration
Remove-Item Env:\KMA_RUN_LIVE

KMA_RUN_LIVE가 없으면 integration 테스트도 실제 서버를 호출하지 않고 skip됩니다. 기본 테스트에서 integration 테스트 자체를 제외하려면:

python -m pytest -m "not integration"

함수형 래퍼를 직접 smoke test할 때:

import asyncio
from kma import ApiHubGeneratedClient


async def main() -> None:
    async with ApiHubGeneratedClient.from_env() as hub:
        response = (await hub.kma_sfctm2(tm="202605010900", stn="108", help="1"))
        print(response.text[:200])


asyncio.run(main())

이 테스트도 인증키가 필요하므로 기본 테스트에 넣지 않습니다.

회귀 테스트 규칙

버그를 고칠 때:

  1. 그 버그를 잡을 실패 테스트를 먼저 추가합니다.
  2. 코드를 수정합니다.
  3. 반복되기 쉬운 KMA/APIHub 함정이면 docs/repeated-mistakes.md를 갱신합니다.

APIHub endpoint 목록을 갱신할 때:

  1. python -X utf8 tools/update_apihub_endpoints.py를 실행합니다.
  2. src/kma/apihub_endpoints.py와 docs/apihub-endpoints.md가 함께 바뀌었는지 확인합니다.
  3. python -m pytest tests/test_apihub.py tests/test_apihub_endpoints.py를 실행합니다.
  4. endpoint 개수가 바뀌면 docs/api-coverage.md와 docs/apihub.md의 숫자를 맞춥니다.