# 09 - Automated Testing (`tests/conftest.py` & `tests/test_tenant.py`)

Is document me hum `tests/` directory me maujood automated testing setup ko samjhenge.

---

## 1. Why Automated Testing Matters? (The "WHY")

Har baar code me change karke browser ya cURL se manual test karna slow aur error-prone hota hai.

### Automated Testing with `pytest` & `TestClient`:
`pytest` seconds me pooray codebase ke business logic ko auto-verify kar deta hai:
1. Valid tenant register hota hai ya nahi?
2. Duplicate domain try karne par HTTP 400 error aata hai ya nahi?
3. Invalid inputs (e.g. empty name) submit karne par HTTP 422 validation error milta hai ya nahi?

---

## 2. Line-by-Line Breakdown of `tests/conftest.py`

Here is the exact code in `tests/conftest.py`:

```python
 1: import sys
 2: from pathlib import Path
 3: import pytest
 4: from fastapi.testclient import TestClient
 5: 
 6: # Ensure backend folder is in python path
 7: sys.path.insert(0, str(Path(__file__).parent.parent))
 8: 
 9: from app.config import settings
10: from app.main import app
11: 
12: # Set test database name
13: settings.database_name = "chatbot_test_db"
14: 
15: @pytest.fixture
16: def client():
17:     with TestClient(app) as c:
18:         yield c
```

### Key Highlights:
- **`sys.path.insert(...)`:** Backend root directory ko Python import path me add karta hai taaki `from app...` imports work karein.
- **`settings.database_name = "chatbot_test_db"`:** CRITICAL! Re-routes test runs to a separate isolated test database so production/development database (`chatbot_db`) remains untouched.
- **`@pytest.fixture def client():`:** Creates a reusable `TestClient(app)` instance. `TestClient` allows sending simulated HTTP requests directly to FastAPI in-memory without running an external server.

---

## 3. Line-by-Line Breakdown of `tests/test_tenant.py`

Here is the exact code in `tests/test_tenant.py`:

```python
 1: import uuid
 2: from fastapi import status
 3: 
 4: def test_register_tenant_success(client):
 5:     unique_domain = f"test-{uuid.uuid4().hex[:6]}.com"
 6:     payload = {
 7:         "domain": unique_domain,
 8:         "name": "Test Acme Store"
 9:     }
10:     
11:     response = client.post("/api/v1/tenant/register", json=payload)
12:     
13:     assert response.status_code == status.HTTP_201_CREATED
14:     data = response.json()
15:     assert "siteId" in data
16:     assert data["siteId"].startswith("site_")
17:     assert data["domain"] == unique_domain
18:     assert data["name"] == "Test Acme Store"
19:     assert "createdAt" in data
```
- **`test_register_tenant_success`:** Tests successful tenant creation. Generates unique domain (`test-a1b2c3.com`), sends `POST`, verifies `201 Created` HTTP status code, and asserts response contains `siteId` starting with `site_`.

```python
22: def test_register_tenant_duplicate_domain_fails(client):
23:     unique_domain = f"dup-{uuid.uuid4().hex[:6]}.com"
24:     payload = {
25:         "domain": unique_domain,
26:         "name": "Duplicate Test Store"
27:     }
28:     
29:     # First registration
30:     resp1 = client.post("/api/v1/tenant/register", json=payload)
31:     assert resp1.status_code == status.HTTP_201_CREATED
32:     
33:     # Second registration with same domain should fail
34:     resp2 = client.post("/api/v1/tenant/register", json=payload)
35:     assert resp2.status_code == status.HTTP_400_BAD_REQUEST
36:     assert "already registered" in resp2.json()["detail"]
```
- **`test_register_tenant_duplicate_domain_fails`:** Verifies duplicate domain restriction. Registers once (succeeds `201`), then registers again with exact same domain (fails `400 Bad Request`).

```python
38: def test_register_tenant_validation_error(client):
39:     payload = {
40:         "domain": "valid-domain.com",
41:         "name": ""
42:     }
43:     response = client.post("/api/v1/tenant/register", json=payload)
44:     assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
```
- **`test_register_tenant_validation_error`:** Tests Pydantic input validation. Sends empty `name: ""`, verifies API rejects it with `422 Unprocessable Entity`.

---

## 4. How to Run Tests Command
```bash
cd backend
pytest
```
Output:
`3 passed in 0.45s` ✅
