본문 바로가기

개발하자

Fast 테스트 방법이미지를 소비하는 API 끝점?

반응형

Fast 테스트 방법이미지를 소비하는 API 끝점?

나는 Fast를 테스트하기 위해 pytest를 사용하고 있다.이진 형식으로 이미지를 입력하는 API 끝점

@app.post("/analyse")
async def analyse(file: bytes = File(...)):

    image = Image.open(io.BytesIO(file)).convert("RGB")
    stats = process_image(image)
    return stats

서버를 시작한 후 다음과 같이 호출을 실행하여 엔드포인트를 수동으로 테스트할 수 있습니다.

import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

url = "http://127.0.0.1:8000/analyse"

filename = "./example.jpg"
m = MultipartEncoder(
        fields={'file': ('filename', open(filename, 'rb'), 'image/jpeg')}
    )
r = requests.post(url, data=m, headers={'Content-Type': m.content_type}, timeout = 8000)
assert r.status_code == 200

그러나 다음 형식의 함수로 테스트를 설정합니다.

from fastapi.testclient import TestClient
from requests_toolbelt.multipart.encoder import MultipartEncoder
from app.server import app

client = TestClient(app)

def test_image_analysis():

    filename = "example.jpg"

    m = MultipartEncoder(
        fields={'file': ('filename', open(filename, 'rb'), 'image/jpeg')}
        )

    response = client.post("/analyse",
                           data=m,
                           headers={"Content-Type": "multipart/form-data"}
                           )

    assert response.status_code == 200

로 테스트를 실행할 때, 그것은 나를 다시 돌려준다.

>       assert response.status_code == 200
E       assert 400 == 200
E        +  where 400 = <Response [400]>.status_code

tests\test_server.py:22: AssertionError
-------------------------------------------------------- Captured log call --------------------------------------------------------- 
ERROR    fastapi:routing.py:133 Error getting request body: can't concat NoneType to bytes
===================================================== short test summary info ====================================================== 
FAILED tests/test_server.py::test_image_analysis - assert 400 == 200

내가 뭘 잘못하고 있지? 이미지 파일을 사용하여 테스트 기능을 작성하는 올바른 방법은 무엇입니까?




모든 면에서 랩과 동일하지 않기 때문에 다른 동작을 볼 수 있습니다. 더 깊이 파고들려면 소스 코드를 참조하십시오: (FYI, starlette 라이브러리에서 사용 중)

https://github.com/encode/starlette/blob/master/starlette/testclient.py

해결하기 위해, 당신은 파일 바이트를 받아들이고 그것을 다음과 같은 것으로 포맷으로 인코딩할 수 있기 때문에 제거할 수 있다.

# change it
r = requests.post(url, data=m, headers={'Content-Type': m.content_type}, timeout = 8000)

# to 
r = requests.post(url, files={"file": ("filename", open(filename, "rb"), "image/jpeg")})

그리고 Fast를 수정합니다.API 테스트 코드:

# change
response = client.post("/analyse",
                       data=m,
                       headers={"Content-Type": "multipart/form-data"}
                       )
# to
response = client.post(
    "/analyse", files={"file": ("filename", open(filename, "rb"), "image/jpeg")}
)



아래 코드가 작동합니다.

** API 구조: **

파일:

from fastapi import APIRouter, File, UploadFile, Query
router = APIRouter()
@router.post(path="{{API_PATH}}", tags=["Prediction"])
def prediction(id: str, uploadFile: UploadFile):
    ...
    {{CODE}}
    return response

테스트 코드

파일:

import pytest
import os
from fastapi.testclient import TestClient
import.api_routers

client = TestClient(api_routers.router)

def test_prediction(constants):  
    # Use constants if fixture created
    file_path = "{{IMAGE PATH}}"
    if os.path.isfile(file_path):
        _files = {'uploadFile': open(file_path, 'rb')}
        response = client.post('{{API_PATH}}',
                           params={
                               "id": {{ID}}
                           },
                           files=_files
                           )
        assert response.status_code == 200
    else:
        pytest.fail("Scratch file does not exists.")

반응형