mirror of
https://github.com/dataforcanada/d4c-service-geo-assistant.git
synced 2026-06-13 14:31:01 +02:00
Enable pytest-asyncio tests in CI (#3)
* Set asyncio_mode="auto" in pytest.ini config Xref https://pytest-asyncio.readthedocs.io/en/latest/reference/configuration.html#asyncio-mode * Add test-python GitHub Actions CI workflow * Add `--color=yes` flag to force GitHub Actions logs to have color Xref https://github.com/pytest-dev/pytest/issues/7443 * Refactor contents of test_api.py slightly Using some ruff rules * Delete test_api.py * Make test_get_place async * Make get_place async, and call .ainvoke method on it
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
name: Test Python
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read # Required to checkout repository
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pytest:
|
||||||
|
name: Pytest
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.13"]
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
- name: Install a specific version of uv
|
||||||
|
uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
|
||||||
|
with:
|
||||||
|
version: "latest"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: uv sync
|
||||||
|
|
||||||
|
- name: Run pytest
|
||||||
|
run: uv run pytest --verbose
|
||||||
@@ -33,3 +33,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
packages = ["src/geo_assistant"]
|
packages = ["src/geo_assistant"]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
addopts = "--color=yes"
|
||||||
|
asyncio_mode = "auto"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from typing import Annotated
|
|
||||||
import duckdb
|
|
||||||
import json
|
import json
|
||||||
from langchain_core.tools import tool
|
from typing import Annotated
|
||||||
from langgraph.types import Command
|
|
||||||
|
import duckdb
|
||||||
from langchain_core.messages import ToolMessage
|
from langchain_core.messages import ToolMessage
|
||||||
|
from langchain_core.tools import tool
|
||||||
from langchain_core.tools.base import InjectedToolCallId
|
from langchain_core.tools.base import InjectedToolCallId
|
||||||
|
from langgraph.types import Command
|
||||||
|
|
||||||
|
|
||||||
def create_database_connection():
|
def create_database_connection():
|
||||||
@@ -15,6 +16,7 @@ def create_database_connection():
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Configured DuckDB connection
|
Configured DuckDB connection
|
||||||
|
|
||||||
"""
|
"""
|
||||||
connection = duckdb.connect()
|
connection = duckdb.connect()
|
||||||
connection.execute("INSTALL spatial;")
|
connection.execute("INSTALL spatial;")
|
||||||
@@ -25,7 +27,7 @@ def create_database_connection():
|
|||||||
|
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
def get_place(
|
async def get_place(
|
||||||
place_name: str, tool_call_id: Annotated[str, InjectedToolCallId] = ""
|
place_name: str, tool_call_id: Annotated[str, InjectedToolCallId] = ""
|
||||||
) -> Command:
|
) -> Command:
|
||||||
"""Get place location from Overture Maps based on user input place name."""
|
"""Get place location from Overture Maps based on user input place name."""
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
import pytest
|
|
||||||
import pytest_asyncio
|
|
||||||
from httpx import AsyncClient, ASGITransport
|
|
||||||
from uuid import uuid4
|
|
||||||
|
|
||||||
from geo_assistant.api.app import app
|
|
||||||
from geo_assistant.agent.graph import create_graph
|
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture
|
|
||||||
async def initialized_app():
|
|
||||||
"""Initialize the app's chatbot before testing"""
|
|
||||||
# Manually initialize the chatbot as the lifespan would
|
|
||||||
app.state.chatbot = await create_graph()
|
|
||||||
yield app
|
|
||||||
# Cleanup if needed
|
|
||||||
if hasattr(app.state, "chatbot"):
|
|
||||||
del app.state.chatbot
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_hello_world(initialized_app):
|
|
||||||
"""Hello world test for the API"""
|
|
||||||
async with AsyncClient(
|
|
||||||
transport=ASGITransport(app=initialized_app), base_url="http://test"
|
|
||||||
) as client:
|
|
||||||
thread_id = uuid4()
|
|
||||||
response = await client.post(
|
|
||||||
"/chat",
|
|
||||||
json={
|
|
||||||
"agent_state_input": {
|
|
||||||
"messages": [{"content": "Hello, world!", "type": "human"}],
|
|
||||||
"feature_collection": None,
|
|
||||||
},
|
|
||||||
"thread_id": str(thread_id),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert response.headers["content-type"] == "application/x-ndjson; charset=utf-8"
|
|
||||||
|
|
||||||
# Read the streaming response
|
|
||||||
content = response.text
|
|
||||||
assert content is not None
|
|
||||||
assert len(content) > 0
|
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
from langchain_core.tools.base import ToolCall
|
from langchain_core.tools.base import ToolCall
|
||||||
|
|
||||||
from geo_assistant.tools.overture import get_place
|
from geo_assistant.tools.overture import get_place
|
||||||
|
|
||||||
|
|
||||||
def test_get_place():
|
async def test_get_place():
|
||||||
command = get_place.invoke(
|
command = await get_place.ainvoke(
|
||||||
ToolCall(
|
ToolCall(
|
||||||
name="get_place",
|
name="get_place",
|
||||||
type="tool_call",
|
type="tool_call",
|
||||||
id="test_id",
|
id="test_id",
|
||||||
args={"place_name": "Neighboourhood Cafe Lisbon"},
|
args={"place_name": "Neighbourhood Cafe Lisbon"},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert "place" in command.update
|
assert "place" in command.update
|
||||||
|
|||||||
Reference in New Issue
Block a user