system-prompts-and-models-o.../salesflow-saas/.claude/commands/generate-tests.md
Claude 83210b9d12
feat: Add founder strategy, Claude Code control plane, SaaS launch readiness
Founder Strategy & GTM (from prompts #1, #10):
- niche-brief.md: Saudi real estate primary, healthcare secondary
- icp-brief.md: Full ICP with Arabic objection handling
- content-map.md: 20 content ideas, SEO keywords, weekly schedule
- outreach-map.md: WhatsApp/Email cold outreach with Arabic templates
- launch-plan.md: 14-day sprint + 30-day plan with revenue targets
- interview-template.md: 15 Arabic customer discovery questions

Claude Code Control Plane (from prompt #2):
- .claude/settings.json: Permissions and preferences
- .claude/commands/: 5 custom commands (review-pr, release-prep, security-check, generate-tests, architecture-review)
- .claude/hooks/: pre-commit.sh (secrets check), pre-push.sh (tests)

SaaS Launch Readiness (from prompt #4):
- saas-readiness-audit.md: Full audit with gap analysis
- deployment-checklist.md: Deploy + rollback procedures
- launch-checklist.md: 100+ launch day checklist items
- feature_flags.py: Redis-backed feature flags with per-tenant control

https://claude.ai/code/session_01LsnvBa7HwF5hs99VZbgLGj
2026-04-11 08:09:50 +00:00

4.0 KiB

/generate-tests — Auto-generate Tests for Dealix Services

Analyze a service file and generate comprehensive pytest-asyncio tests with factory-boy fixtures.

Usage

Provide the path to a service file, e.g.: /generate-tests backend/app/services/lead_service.py

Steps

1. Analyze the Target Service

Read the specified service file and extract:

  • Class name and constructor dependencies (db session, other services)
  • All public methods with their signatures and return types
  • Database models referenced
  • External service calls (WhatsApp, email, Stripe, AI providers)
  • Async vs sync methods

2. Identify Test Cases

For each public method, generate tests for:

  • Happy path — normal operation with valid inputs
  • Empty/null input — None, empty string, empty list
  • Invalid tenant — wrong tenant_id, missing tenant_id
  • Not found — entity does not exist
  • Duplicate — creating something that already exists
  • Permission denied — user lacks required role
  • Boundary values — max length strings, zero amounts, negative numbers
  • Concurrent access — if method modifies shared state

3. Generate Factory Classes

Create factory-boy factories for each model used:

import factory
from factory.alchemy import SQLAlchemyModelFactory

class TenantFactory(SQLAlchemyModelFactory):
    class Meta:
        model = Tenant
        sqlalchemy_session_persistence = "commit"

    id = factory.LazyFunction(uuid4)
    name = factory.Faker("company", locale="ar_SA")
    domain = factory.Faker("domain_name")
    is_active = True
    created_at = factory.LazyFunction(lambda: datetime.now(timezone.utc))

Use locale="ar_SA" for Arabic data where appropriate (names, companies, addresses).

4. Generate Test File

Create the test file at backend/tests/test_services/test_<service_name>.py with:

"""
Tests for <ServiceName>.
Auto-generated — review and customize before committing.
"""

import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from uuid import uuid4

from app.services.<module> import <ServiceClass>


@pytest.fixture
def db_session():
    """Mock async database session."""
    session = AsyncMock()
    session.execute = AsyncMock()
    session.commit = AsyncMock()
    session.rollback = AsyncMock()
    session.refresh = AsyncMock()
    return session


@pytest.fixture
def service(db_session):
    return <ServiceClass>(db=db_session)


@pytest.fixture
def tenant_id():
    return uuid4()


class TestMethodName:
    @pytest.mark.asyncio
    async def test_success(self, service, tenant_id):
        # Arrange
        ...
        # Act
        result = await service.method_name(...)
        # Assert
        assert result is not None

    @pytest.mark.asyncio
    async def test_not_found(self, service, tenant_id):
        service.db.execute.return_value = MagicMock(scalar_one_or_none=MagicMock(return_value=None))
        with pytest.raises(NotFoundException):
            await service.method_name(...)

    @pytest.mark.asyncio
    async def test_wrong_tenant(self, service):
        wrong_tenant = uuid4()
        # Should not return data from another tenant
        ...

5. Mocking Strategy

  • Database: Mock AsyncSession with execute() returning mock results
  • Redis: Mock with fakeredis.aioredis or AsyncMock
  • External APIs (WhatsApp, Stripe): Use unittest.mock.patch on the service method
  • Celery tasks: Mock with @patch("app.workers.task_name.delay")
  • AI services: Mock LLM responses with fixed JSON structures
  • Time-dependent: Use freezegun for timestamp-sensitive logic

6. Validation Checklist

After generating, verify:

  • All public methods have at least one test
  • Async methods use @pytest.mark.asyncio
  • Mocks match actual method signatures
  • Tenant isolation is tested
  • No real external calls in tests
  • Test file runs without import errors: pytest <test_file> --co -q

7. Output

Print the complete test file content and the command to run it:

pytest backend/tests/test_services/test_<name>.py -v