Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

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나 권한 및 실제 데이터셋 쓰기 검증은 포함하지 않습니다.