CarsRUS / tests /test_cloud.py
galbendavids's picture
CarsRUS: Link & Co 01 normalization (and/ืœื™ื ืง&ืงื•), tests
b262f99
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Cloud tests for CarsRUS Space on Hugging Face.
Runs against: https://huggingface.co/spaces/galbendavids/CarsRUS
Requires: pip install gradio_client
Run: PYTHONPATH=. python tests/test_cloud.py
or: bash tests/run_cloud_tests.sh
"""
import os
import sys
_tests_dir = os.path.dirname(os.path.abspath(__file__))
_project_root = os.path.dirname(_tests_dir)
if _project_root not in sys.path:
sys.path.insert(0, _project_root)
# Space URL (public Space โ€“ no token needed for read)
SPACE_URL = os.environ.get("CARSRUS_SPACE_URL", "galbendavids/CarsRUS")
def get_client():
"""Create Gradio client for the Space. Uses HF token from env if set."""
try:
from gradio_client import Client
except ImportError:
print("โŒ gradio_client not installed. Run: pip install gradio_client")
sys.exit(1)
hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
return Client(SPACE_URL, hf_token=hf_token or None)
def collect_chat_response(client, message: str):
"""Call the chat endpoint and return the full response (streaming collected)."""
# Space API: predict(message, api_name="/chat") -> response (str)
result = client.predict(message, api_name="/chat")
return result
def test_space_reachable():
"""Space is up and client can connect."""
print("\n[Cloud] test_space_reachable...")
client = get_client()
# Just ensure we can get API info (view_api or similar)
try:
api_info = client.view_api()
print(f" Endpoints: {list(api_info.get('named_endpoints', api_info) if isinstance(api_info, dict) else 'ok')}")
except Exception as e:
print(f" view_api: {e}")
print("โœ… test_space_reachable passed")
return client
def test_chat_supported_car(client):
"""Ask about a supported car (e.g. Audi RS3) โ€“ expect substantive answer, no config error."""
print("\n[Cloud] test_chat_supported_car...")
message = "Tell me about the Audi RS3"
try:
result = collect_chat_response(client, message)
except Exception as e:
print(f" Call failed: {e}")
try:
api = client.view_api()
print(f" API: {api}")
except Exception:
pass
raise
text = result if isinstance(result, str) else str(result)
# Should not be config/init error
assert "Configuration Error" not in text and "Initialization Error" not in text, (
f"Expected normal answer, got: {text[:200]}"
)
# Should mention something about the car or content
assert len(text.strip()) > 50, f"Response too short: {text[:200]}"
print(f" Response length: {len(text)} chars")
print("โœ… test_chat_supported_car passed")
def test_chat_unsupported_car(client):
"""Ask about an unsupported car โ€“ expect refusal or supported list."""
print("\n[Cloud] test_chat_unsupported_car...")
message = "What do you think about BMW X5?"
try:
result = collect_chat_response(client, message)
except Exception as e:
print(f" Call failed: {e}")
raise
text = result if isinstance(result, str) else str(result)
assert "Configuration Error" not in text and "Initialization Error" not in text
# Refusal or supported list
has_refusal = (
"not in my knowledge" in text.lower()
or "ืœื ื ืžืฆื" in text
or "supported" in text.lower()
or "ื ืชืžื›ื™ื" in text
or "Citroen" in text
or "Audi RS3" in text
)
assert has_refusal or len(text) > 20, f"Expected refusal/supported list, got: {text[:300]}"
print("โœ… test_chat_unsupported_car passed")
def test_chat_comparison(client):
"""Ask to compare two supported cars โ€“ expect comparison content."""
print("\n[Cloud] test_chat_comparison...")
message = "Compare Audi RS3 vs Hyundai Elantra N"
try:
result = collect_chat_response(client, message)
except Exception as e:
print(f" Call failed: {e}")
raise
text = result if isinstance(result, str) else str(result)
assert "Configuration Error" not in text and "Initialization Error" not in text
assert len(text.strip()) > 30, f"Response too short: {text[:200]}"
print("โœ… test_chat_comparison passed")
def test_chat_hebrew(client):
"""Hebrew query โ€“ app should respond (Hebrew or English)."""
print("\n[Cloud] test_chat_hebrew...")
message = "ืกืคืจ ืœื™ ืขืœ ืื•ื“ื™ RS3"
try:
result = collect_chat_response(client, message)
except Exception as e:
print(f" Call failed: {e}")
raise
text = result if isinstance(result, str) else str(result)
assert "Configuration Error" not in text and "Initialization Error" not in text
assert len(text.strip()) > 20, f"Response too short: {text[:200]}"
print("โœ… test_chat_hebrew passed")
def test_chat_link_co_01(client):
"""Link & Co 01 is in the knowledge base โ€“ must NOT say 'not in my knowledge'."""
print("\n[Cloud] test_chat_link_co_01...")
for message in ["ืกืคืจ ืขืœ ืœื™ื ืง ืื ื“ ืงื• 01", "Tell me about Link and Co 01"]:
try:
result = collect_chat_response(client, message)
except Exception as e:
print(f" Call failed for {message!r}: {e}")
raise
text = result if isinstance(result, str) else str(result)
assert "Configuration Error" not in text and "Initialization Error" not in text
assert "not in my knowledge" not in text and "ืœื ื ืžืฆื ื‘ื‘ืกื™ืก ื”ื™ื“ืข" not in text, (
f"Link & Co 01 is in scraped_data (link-and-co-01-2026); got refusal: {text[:300]}"
)
assert len(text.strip()) > 50, f"Response too short for {message!r}: {text[:200]}"
print("โœ… test_chat_link_co_01 passed")
def run_all():
"""Run all cloud tests. Exit 0 if all pass."""
print("=" * 60)
print("CarsRUS โ€“ Cloud tests")
print(f"Space: {SPACE_URL}")
print("=" * 60)
try:
client = test_space_reachable()
test_chat_supported_car(client)
test_chat_unsupported_car(client)
test_chat_comparison(client)
test_chat_hebrew(client)
test_chat_link_co_01(client)
except Exception as e:
print(f"\nโŒ Cloud test failed: {e}")
import traceback
traceback.print_exc()
return 1
print("\nโœ… All cloud tests passed.")
return 0
if __name__ == "__main__":
sys.exit(run_all())