Spaces:
Running
Running
Commit
·
2bd9462
1
Parent(s):
f66a862
feat: add smoke tests and fix Gradio 6.x compatibility
Browse files- Add smoke tests for app initialization (catches config errors before deploy)
- Fix Gradio 6.x breaking changes:
- Remove `theme` param from gr.Blocks (removed in 6.x)
- Remove `type` param from gr.ChatInterface (removed in 6.x)
- Add typer to dev dependencies (required by Gradio CLI for smoke tests)
Smoke tests would have caught the previous deployment failures:
- Invalid examples format
- Gradio API changes
101 tests passing, 71% coverage
- pyproject.toml +6 -0
- src/app.py +0 -2
- tests/unit/test_app_smoke.py +50 -0
- uv.lock +10 -0
pyproject.toml
CHANGED
|
@@ -34,6 +34,7 @@ dev = [
|
|
| 34 |
"pytest-cov>=5.0",
|
| 35 |
"pytest-mock>=3.12",
|
| 36 |
"respx>=0.21", # Mock httpx requests
|
|
|
|
| 37 |
|
| 38 |
# Quality
|
| 39 |
"ruff>=0.4.0",
|
|
@@ -131,5 +132,10 @@ exclude_lines = [
|
|
| 131 |
"raise NotImplementedError",
|
| 132 |
]
|
| 133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
# Note: agent-framework-core is optional and installed locally for magentic mode
|
| 135 |
# CI skips tests that require it via pytest.importorskip
|
|
|
|
| 34 |
"pytest-cov>=5.0",
|
| 35 |
"pytest-mock>=3.12",
|
| 36 |
"respx>=0.21", # Mock httpx requests
|
| 37 |
+
"typer>=0.9.0", # Gradio CLI dependency for smoke tests
|
| 38 |
|
| 39 |
# Quality
|
| 40 |
"ruff>=0.4.0",
|
|
|
|
| 132 |
"raise NotImplementedError",
|
| 133 |
]
|
| 134 |
|
| 135 |
+
[dependency-groups]
|
| 136 |
+
dev = [
|
| 137 |
+
"typer>=0.20.0",
|
| 138 |
+
]
|
| 139 |
+
|
| 140 |
# Note: agent-framework-core is optional and installed locally for magentic mode
|
| 141 |
# CI skips tests that require it via pytest.importorskip
|
src/app.py
CHANGED
|
@@ -129,7 +129,6 @@ def create_demo() -> Any:
|
|
| 129 |
"""
|
| 130 |
with gr.Blocks(
|
| 131 |
title="DeepCritical - Drug Repurposing Research Agent",
|
| 132 |
-
theme=gr.themes.Soft(),
|
| 133 |
) as demo:
|
| 134 |
gr.Markdown("""
|
| 135 |
# 🧬 DeepCritical
|
|
@@ -147,7 +146,6 @@ def create_demo() -> Any:
|
|
| 147 |
# Main chat interface (existing)
|
| 148 |
gr.ChatInterface(
|
| 149 |
fn=research_agent,
|
| 150 |
-
type="messages", # type: ignore
|
| 151 |
title="",
|
| 152 |
examples=[
|
| 153 |
["What drugs could be repurposed for Alzheimer's disease?", "simple"],
|
|
|
|
| 129 |
"""
|
| 130 |
with gr.Blocks(
|
| 131 |
title="DeepCritical - Drug Repurposing Research Agent",
|
|
|
|
| 132 |
) as demo:
|
| 133 |
gr.Markdown("""
|
| 134 |
# 🧬 DeepCritical
|
|
|
|
| 146 |
# Main chat interface (existing)
|
| 147 |
gr.ChatInterface(
|
| 148 |
fn=research_agent,
|
|
|
|
| 149 |
title="",
|
| 150 |
examples=[
|
| 151 |
["What drugs could be repurposed for Alzheimer's disease?", "simple"],
|
tests/unit/test_app_smoke.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Smoke tests for the Gradio app.
|
| 2 |
+
|
| 3 |
+
These tests verify the app can start without crashing.
|
| 4 |
+
They catch configuration errors like invalid Gradio parameters
|
| 5 |
+
that wouldn't be caught by unit tests.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
import pytest
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
@pytest.mark.unit
|
| 12 |
+
class TestAppSmoke:
|
| 13 |
+
"""Smoke tests for app initialization."""
|
| 14 |
+
|
| 15 |
+
def test_app_creates_demo(self) -> None:
|
| 16 |
+
"""App should create Gradio demo without crashing.
|
| 17 |
+
|
| 18 |
+
This catches:
|
| 19 |
+
- Invalid Gradio component parameters
|
| 20 |
+
- Import errors
|
| 21 |
+
- Configuration issues
|
| 22 |
+
"""
|
| 23 |
+
# Skip if gradio not fully installed (CI may not have all deps)
|
| 24 |
+
pytest.importorskip("gradio")
|
| 25 |
+
pytest.importorskip("typer") # Gradio CLI dependency
|
| 26 |
+
|
| 27 |
+
from src.app import create_demo
|
| 28 |
+
|
| 29 |
+
demo = create_demo()
|
| 30 |
+
assert demo is not None
|
| 31 |
+
|
| 32 |
+
def test_mcp_tools_importable(self) -> None:
|
| 33 |
+
"""MCP tool functions should be importable.
|
| 34 |
+
|
| 35 |
+
Ensures the MCP server can expose these tools.
|
| 36 |
+
"""
|
| 37 |
+
from src.mcp_tools import (
|
| 38 |
+
analyze_hypothesis,
|
| 39 |
+
search_all_sources,
|
| 40 |
+
search_biorxiv,
|
| 41 |
+
search_clinical_trials,
|
| 42 |
+
search_pubmed,
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
# Just verify they're callable
|
| 46 |
+
assert callable(search_pubmed)
|
| 47 |
+
assert callable(search_clinical_trials)
|
| 48 |
+
assert callable(search_biorxiv)
|
| 49 |
+
assert callable(search_all_sources)
|
| 50 |
+
assert callable(analyze_hypothesis)
|
uv.lock
CHANGED
|
@@ -1087,6 +1087,7 @@ dev = [
|
|
| 1087 |
{ name = "pytest-sugar" },
|
| 1088 |
{ name = "respx" },
|
| 1089 |
{ name = "ruff" },
|
|
|
|
| 1090 |
]
|
| 1091 |
embeddings = [
|
| 1092 |
{ name = "chromadb" },
|
|
@@ -1104,6 +1105,11 @@ modal = [
|
|
| 1104 |
{ name = "modal" },
|
| 1105 |
]
|
| 1106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1107 |
[package.metadata]
|
| 1108 |
requires-dist = [
|
| 1109 |
{ name = "agent-framework-core", marker = "extra == 'magentic'" },
|
|
@@ -1136,10 +1142,14 @@ requires-dist = [
|
|
| 1136 |
{ name = "sentence-transformers", marker = "extra == 'embeddings'", specifier = ">=2.2.0" },
|
| 1137 |
{ name = "structlog", specifier = ">=24.1" },
|
| 1138 |
{ name = "tenacity", specifier = ">=8.2" },
|
|
|
|
| 1139 |
{ name = "xmltodict", specifier = ">=0.13" },
|
| 1140 |
]
|
| 1141 |
provides-extras = ["dev", "magentic", "embeddings", "modal"]
|
| 1142 |
|
|
|
|
|
|
|
|
|
|
| 1143 |
[[package]]
|
| 1144 |
name = "defusedxml"
|
| 1145 |
version = "0.7.1"
|
|
|
|
| 1087 |
{ name = "pytest-sugar" },
|
| 1088 |
{ name = "respx" },
|
| 1089 |
{ name = "ruff" },
|
| 1090 |
+
{ name = "typer" },
|
| 1091 |
]
|
| 1092 |
embeddings = [
|
| 1093 |
{ name = "chromadb" },
|
|
|
|
| 1105 |
{ name = "modal" },
|
| 1106 |
]
|
| 1107 |
|
| 1108 |
+
[package.dev-dependencies]
|
| 1109 |
+
dev = [
|
| 1110 |
+
{ name = "typer" },
|
| 1111 |
+
]
|
| 1112 |
+
|
| 1113 |
[package.metadata]
|
| 1114 |
requires-dist = [
|
| 1115 |
{ name = "agent-framework-core", marker = "extra == 'magentic'" },
|
|
|
|
| 1142 |
{ name = "sentence-transformers", marker = "extra == 'embeddings'", specifier = ">=2.2.0" },
|
| 1143 |
{ name = "structlog", specifier = ">=24.1" },
|
| 1144 |
{ name = "tenacity", specifier = ">=8.2" },
|
| 1145 |
+
{ name = "typer", marker = "extra == 'dev'", specifier = ">=0.9.0" },
|
| 1146 |
{ name = "xmltodict", specifier = ">=0.13" },
|
| 1147 |
]
|
| 1148 |
provides-extras = ["dev", "magentic", "embeddings", "modal"]
|
| 1149 |
|
| 1150 |
+
[package.metadata.requires-dev]
|
| 1151 |
+
dev = [{ name = "typer", specifier = ">=0.20.0" }]
|
| 1152 |
+
|
| 1153 |
[[package]]
|
| 1154 |
name = "defusedxml"
|
| 1155 |
version = "0.7.1"
|