Skip to content

DealAgent unit tests and integration test suite #484

Description

@kovtcharov

Summary

Comprehensive test suite for the DealAgent covering unit tests (mocked APIs), database tests (SQLite), and integration tests (real API calls with skip markers).

Motivation

Every GAIA agent requires tests. The DealAgent has multiple external API integrations that need reliable mocking, plus database operations that must be verified against real SQLite.

Test Structure

tests/
├── unit/
│   └── agents/
│       └── deals/
│           ├── test_deal_agent.py         # Agent initialization, system prompt
│           ├── test_search_tools.py       # Product search with mocked APIs
│           ├── test_price_history.py      # Database schema, query helpers
│           └── test_http_tools.py         # HTTPToolsMixin with mocked responses
├── integration/
│   └── agents/
│       └── deals/
│           ├── test_bestbuy_api.py        # Real Best Buy API (requires key)
│           ├── test_serpapi.py            # Real SerpApi (requires key)
│           └── test_deal_flow.py          # End-to-end: search → store → query

Unit Tests

# test_search_tools.py
class TestSearchTools:
    def test_search_products_bestbuy(self, mock_http, deal_agent):
        """search_products returns normalized results from Best Buy."""
        mock_http.get("https://api.bestbuy.com/v1/products", json={...})
        result = deal_agent.tools["search_products"]("laptop", retailer="bestbuy")
        assert result["status"] == "success"
        assert len(result["products"]) > 0
        assert all("price" in p for p in result["products"])

    def test_search_graceful_degradation(self, mock_http, deal_agent):
        """If one API fails, others still return results."""
        mock_http.get("https://api.bestbuy.com/v1/products", status=500)
        mock_http.get("https://serpapi.com/search", json={...})
        result = deal_agent.tools["search_products"]("laptop")
        assert result["status"] == "partial"
        assert len(result["products"]) > 0

# test_price_history.py
class TestPriceHistory:
    def test_record_and_query_prices(self, deal_agent_with_db):
        """Record prices and verify time-series query."""
        pid = deal_agent_with_db.upsert_product("Test Laptop", "SKU123", "bestbuy")
        deal_agent_with_db.record_price(pid, 999.99)
        deal_agent_with_db.record_price(pid, 899.99)
        stats = deal_agent_with_db.get_price_stats(pid)
        assert stats["min"] == 899.99
        assert stats["max"] == 999.99

    def test_detect_price_drops(self, deal_agent_with_db):
        """Detect products with significant price drops."""
        # ... seed data with price drop > threshold
        drops = deal_agent_with_db.detect_price_drops(threshold_pct=10.0)
        assert len(drops) == 1

Integration Tests

# test_bestbuy_api.py
@pytest.fixture
def require_bestbuy_key():
    key = os.getenv("BESTBUY_API_KEY")
    if not key:
        pytest.skip("BESTBUY_API_KEY not set")
    return key

def test_bestbuy_product_search(require_bestbuy_key, deal_agent):
    """Search Best Buy API for real products."""
    result = deal_agent.tools["search_products"]("laptop", retailer="bestbuy")
    assert result["status"] == "success"

Shared Fixtures

# tests/conftest.py additions
@pytest.fixture
def deal_agent():
    return DealAgent(db_path=":memory:", skip_lemonade=True)

@pytest.fixture
def deal_agent_with_db(tmp_path):
    db = tmp_path / "test_deals.db"
    agent = DealAgent(db_path=str(db), skip_lemonade=True)
    return agent

Acceptance Criteria

  • Unit tests for DealAgent initialization and config
  • Unit tests for all search tools with mocked HTTP responses
  • Unit tests for all price history query helpers
  • Unit tests for HTTPToolsMixin (rate limiting, retries, error handling)
  • Integration tests with skip markers for missing API keys
  • End-to-end test: search → store product → record price → query history
  • All tests pass in CI (unit tests always, integration tests when keys available)
  • Shared fixtures added to conftest.py

Phase

Phase 1 — Core Agent

Dependencies

  • All other Phase 1 issues (this validates them)

Metadata

Metadata

Assignees

No one assigned

    Labels

    dealsDealAgent: price tracking and deal discoverydomain:automationScheduler, autonomy, RAG, web search, watchers, researchp1medium prioritytestsTest changestrack:consumer-appConsumer product track — mobile-first: voice + messaging + memory + skills

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions