DuckDB SQL 결과 검사
같은 항공기 조건을 실제 DuckDB SQL로 실행합니다. 테스트는 연결에 aircraft 표를 등록하여 런타임의 사전 등록 입력을 재현하고 출력 relation의 모든 값을 비교합니다.
변환 모듈
src/myproject/datasets/find_aircraft_duckdb.py:
from transforms.api import Input, Output, transform
def compute_data(ctx, output, aircraft):
relation = ctx.duckdb().conn.sql("""
SELECT * FROM aircraft
WHERE number_of_seats > 300
AND operating_status = 'Yes'
""")
output.write_table(relation)
compute = transform.using(
output=Output("/Example Project/Outputs/aircraft_duckdb"),
aircraft=Input("/Example Project/Inputs/aircraft"),
)(compute_data)
입력 이름 aircraft는 SQL에 등록할 이름과 같아야 합니다. 실제 자산 경로를 지정하고 DuckDB 및 Pandas를 테스트 환경에 준비합니다.
테스트
CSV 리소스를 src/test/resources/에 두고 src/test/test_find_aircraft_duckdb.py를 작성합니다.
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import MagicMock
import duckdb
import pandas as pd
from myproject.datasets.find_aircraft_duckdb import compute_data
RESOURCES = Path(__file__).parent / "resources"
def test_find_aircraft():
source_frame = pd.read_csv(RESOURCES / "aircraft_mock.csv")
expected = pd.read_csv(RESOURCES / "expected_filtered_aircraft.csv")
output = MagicMock(spec_set=["write_table"])
aircraft = MagicMock(spec_set=[])
ctx = MagicMock(spec_set=["duckdb"])
with duckdb.connect() as connection:
connection.register("aircraft", source_frame)
ctx.duckdb.return_value = SimpleNamespace(conn=connection)
compute_data(ctx=ctx, output=output, aircraft=aircraft)
output.write_table.assert_called_once()
actual = output.write_table.call_args.args[0].fetchdf()
assert list(actual.columns) == list(expected.columns)
assert len(actual) == len(expected)
pd.testing.assert_frame_equal(
actual.sort_values(list(actual.columns)).reset_index(drop=True),
expected.sort_values(list(expected.columns)).reset_index(drop=True),
check_dtype=False,
)
계산과 relation의 구체화는 실제 연결이 열려 있는 동안 수행합니다. 파일 경로를 SQL 문자열에 삽입하지 않고 CSV를 읽어 등록하므로 경로의 인용 부호에도 영향을 받지 않습니다.
비교는 행 순서와 Pandas의 내부 dtype 표현 차이를 제외하고 열 이름, 행 수와 값을 확인합니다. Foundry schema나 권한 및 실제 데이터셋 쓰기 검증은 포함하지 않습니다.