테스트 도구,자동화

(인하우스 도구 개발) API 스펙으로부터 테스트 케이스와 코드를 생성해 주는 도구 => ChatGPT가 훨낫다. 접도록 하자.

genycho 2025. 4. 15. 10:31

뜨문뜨문 생각날 때마다 만들고 있던 도구가 있었다. 

오랜만에 개발 IDE를 열고 코드 작업을 하려고 보다가 ChatGPT가 같은 목적으로 어느정도 수준까지 해줄까 싶어서 

확인해 봤다. 

 

결론은... 음... ChatGPT가 나보다 나은 것 같다. 

이제 이런 류의 접근은... 그냥 AI 연동해서 AI한테 부탁하는 코드 정도나 작성하면 될 것 같다... 

 

하려던 바. 

1) Input API Spec
<- xxx_swagger.json
2) Analyze Spec
-> ApiInfo
3) Extract TestCases
->ApiTCInfo
4) Write TestCode
-> [Test Code] pytest+requests
-> [Test Script] PostMan Collection

 

ChatGPT한테 테스트용 샘플 Swagger json 파일을 업로드한 후 비슷한 방식으로 테스트 케이스를 생성해 달라고 해봤다. 

https://chatgpt.com/share/67fdb565-a4c4-8001-a1c5-355646f132bd

첨부한 petstore에 대한 HTTP API 스펙을 기반으로 (PUT) /pet API에 대한 테스트 케이스를 작성해 줘

 

다음은 OpenAPI 스펙에 정의된 (PUT) /pet API를 기준으로 작성한 테스트 케이스입니다. 이 API는 기존의 Pet 정보를 갱신하는 데 사용됩니다.


✅ 기본 정보

  • Endpoint: PUT /pet
  • 요약: 기존 Pet 정보 갱신
  • 요청 형식: application/json 또는 application/xml, application/x-www-form-urlencoded
  • 요청 본문 필수: ✅
  • 보안 요구사항: petstore_auth (write:pets, read:pets)

테스트 케이스

1. 정상 케이스

TC001. 유효한 Pet 객체로 기존 Pet 정보 갱신

  • 입력:
  • json
    { "id": 10, "name": "Rex", "category": { "id": 1, "name": "Dogs" }, "photoUrls": ["https://example.com/rex.jpg"], "tags": [{ "id": 1, "name": "friendly" }], "status": "available" }
  • 예상 결과: HTTP 200 OK, 업데이트된 Pet 객체 반환

2. 예외/에러 케이스

TC002. ID가 누락된 Pet 객체 전송

  • 입력:
  • json
    { "name": "NoID", "photoUrls": ["url"] }
  • 예상 결과: HTTP 400 Bad Request (Invalid ID supplied)

TC003. 존재하지 않는 ID로 업데이트 시도

  • 입력: id가 존재하지 않는 Pet 객체
  • 예상 결과: HTTP 404 Not Found (Pet not found)

TC004. 필수 필드(name, photoUrls)가 누락된 객체

  • 입력:
  • json
    { "id": 10 }
  • 예상 결과: HTTP 405 Validation Exception

TC005. status에 유효하지 않은 값 입력

  • 입력:
  • json
    { "id": 10, "name": "Rex", "photoUrls": ["https://example.com/rex.jpg"], "status": "lost" }
  • 예상 결과: HTTP 405 Validation Exception (Enum validation 실패)

3. 보안 관련 케이스

TC006. 인증 토큰 없이 요청

  • 입력: 유효한 Pet 객체, Authorization 헤더 없음
  • 예상 결과: HTTP 401 Unauthorized 또는 403 Forbidden

4. 엣지 케이스

TC007. 매우 큰 photoUrls 배열

  • 입력: photoUrls에 1000개 이상의 URL
  • 예상 결과: HTTP 200 또는 413 Payload Too Large (서버 설정에 따라)

TC008. name에 특수문자/이모지 포함

위 테스트 케이스를 Postman 스크립트로 만들어 줘

 

 

 

pytest 기반의 테스트 코드로도 작성해 줘

test_update_pet_api.py

import pytest
import requests

BASE_URL = "https://petstore3.swagger.io/api/v3"
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"  # 필요한 경우 사용

HEADERS = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {ACCESS_TOKEN}"
}


@pytest.mark.parametrize("payload, expected_status", [
    # TC001: 정상 케이스
    ({
        "id": 10,
        "name": "Rex",
        "category": {"id": 1, "name": "Dogs"},
        "photoUrls": ["https://example.com/rex.jpg"],
        "tags": [{"id": 1, "name": "friendly"}],
        "status": "available"
    }, 200),

    # TC002: ID 없음
    ({
        "name": "NoID",
        "photoUrls": ["url"]
    }, 400),

    # TC003: 존재하지 않는 ID
    ({
        "id": 999999,
        "name": "Ghost",
        "photoUrls": ["url"]
    }, 404),

    # TC004: 필수 필드 누락 (photoUrls)
    ({
        "id": 10
    }, 405),

    # TC005: status에 유효하지 않은 값
    ({
        "id": 10,
        "name": "Rex",
        "photoUrls": ["https://example.com/rex.jpg"],
        "status": "lost"
    }, 405),

    # TC007: 큰 photoUrls 배열
    ({
        "id": 10,
        "name": "BigPhotoList",
        "photoUrls": ["https://example.com/img.jpg"] * 1000
    }, 200),

    # TC008: 특수문자 포함 name
    ({
        "id": 10,
        "name": "🐶Rex★",
        "photoUrls": ["https://example.com/rex.jpg"],
        "status": "available"
    }, 200)
])
def test_put_pet(payload, expected_status):
    response = requests.put(f"{BASE_URL}/pet", json=payload, headers=HEADERS)
    print(f"\n[TEST] Status Code: {response.status_code}, Response: {response.text}")
    assert response.status_code == expected_status


# TC006: 인증 없이 요청
def test_put_pet_no_auth():
    payload = {
        "id": 10,
        "name": "Rex",
        "photoUrls": ["https://example.com/rex.jpg"],
        "status": "available"
    }
    headers = {"Content-Type": "application/json"}
    response = requests.put(f"{BASE_URL}/pet", json=payload, headers=headers)
    print(f"\n[TEST] No Auth - Status: {response.status_code}, Response: {response.text}")
    assert response.status_code in (401, 403, 200)  # 서버 설정에 따라 다를 수 있음