mirror of
https://github.com/Heretek-AI/heretek-skills.git
synced 2026-07-01 19:54:03 -04:00
f23a235aa2
Remove old triad-*, curiosity-*, governance-*, and Swarm-era skills. Add 14 new heretek-* skills covering agent dev, API, backend, frontend, Docker, monitoring, security, state, testing, debugging, migration, NATS, contributing, and memory systems. Also remove data/*.db files, docs/, and legacy .env.example.
11 KiB
11 KiB
name, description
| name | description |
|---|---|
| heretek-testing | Testing patterns for Heretek Swarm. Use when writing tests, setting up test infrastructure, or debugging test failures. Covers pytest, vitest, mocking strategies, and test organization. |
Heretek Swarm Testing
Test Structure
Python Tests
tests/
├── test_memory.py # Memory system tests
├── test_memory_migration.py # Migration tests
├── test_auth.py # Authentication tests
├── test_agents/ # Agent-specific tests
├── test_api/ # API endpoint tests
├── test_integrations/ # Integration tests
├── conftest.py # Shared fixtures
└── fixtures/ # Test data
Frontend Tests
swarm-dashboard/src/
├── __tests__/ # Co-located tests
├── *.test.tsx # Test files
├── *.spec.ts # Spec files
└── mocks/ # Mock data
Python Testing
Setup
# Install test dependencies
uv sync --group dev
# Or fallback
pip install -e ".[dev]"
Running Tests
# All tests
pytest tests/ -v
# Single file
pytest tests/test_memory.py -v
# Single test
pytest tests/test_memory.py::test_search -v
# With coverage
pytest tests/ --cov=heretek_swarm --cov-report=html
# Parallel execution
pytest tests/ -n auto
Test Configuration
# pyproject.toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = "test_*.py"
python_classes = "Test*"
python_functions = "test_*"
markers = [
"slow: marks tests as slow",
"integration: marks integration tests",
"unit: marks unit tests",
]
Writing Tests
Unit Tests
import pytest
from heretek_swarm.memory import CogneeMemoryReader
@pytest.mark.asyncio
async def test_search_returns_results():
reader = CogneeMemoryReader()
results = await reader.search("test query", limit=5)
assert isinstance(results, list)
assert len(results) <= 5
@pytest.mark.asyncio
async def test_search_with_filters():
reader = CogneeMemoryReader()
results = await reader.search(
"query",
tags=["test"],
min_importance=0.5
)
for result in results:
assert "test" in result.tags
assert result.importance >= 0.5
Integration Tests
import pytest
from heretek_swarm.actors import ExplorerAgent
from heretek_swarm.memory import CogneeMemoryWriter
@pytest.mark.integration
@pytest.mark.asyncio
async def test_explorer_stores_observations():
agent = ExplorerAgent(config)
writer = CogneeMemoryWriter()
# Agent observes
observation = await agent.observe({"context": "test"})
# Store in memory
memory_id = await writer.add(
content=observation,
metadata={"agent": "explorer"}
)
assert memory_id is not None
Fixtures
# conftest.py
import pytest
from heretek_swarm.memory import CogneeMemoryReader, CogneeMemoryWriter
@pytest.fixture
async def memory_reader():
reader = CogneeMemoryReader()
yield reader
await reader.close()
@pytest.fixture
async def memory_writer():
writer = CogneeMemoryWriter()
yield writer
await writer.close()
@pytest.fixture
def sample_memory():
return {
"content": "test memory content",
"metadata": {
"importance": 0.8,
"tags": ["test", "sample"]
}
}
Mocking
import pytest
from unittest.mock import AsyncMock, MagicMock
from heretek_swarm.memory import CogneeMemoryReader
@pytest.mark.asyncio
async def test_search_with_mock():
# Mock the Cognee client
mock_client = AsyncMock()
mock_client.search.return_value = [
{"id": "1", "content": "mocked result"}
]
reader = CogneeMemoryReader(client=mock_client)
results = await reader.search("query")
assert len(results) == 1
assert results[0]["content"] == "mocked result"
mock_client.search.assert_called_once()
Negative Assertions
import pytest
from heretek_swarm.memory import __all__
def test_no_legacy_imports():
"""Verify legacy classes are not exported."""
legacy_classes = [
"DualTierMemory",
"PersistentMemory",
"TieringManager",
"VersionedMemory",
"CompressionManager"
]
for legacy in legacy_classes:
assert legacy not in __all__, f"Legacy class {legacy} should not be exported"
def test_no_legacy_modules():
"""Verify legacy modules are deleted."""
import os
memory_dir = "backend/heretek_swarm/memory"
legacy_files = [
"base.py",
"persistent.py",
"tiering.py",
"versioned.py",
"compression.py",
"migration_strategies.py"
]
for legacy in legacy_files:
path = os.path.join(memory_dir, legacy)
assert not os.path.exists(path), f"Legacy file {legacy} should be deleted"
Frontend Testing
Setup
cd swarm-dashboard
npm install
Running Tests
# All tests
npm test
# Watch mode
npm run test:watch
# Coverage
npm run test:coverage
# Single file
npx vitest run src/__tests__/AgentCard.test.tsx
Writing Tests
Unit Tests
import { render, screen, fireEvent } from '@testing-library/react';
import { AgentCard } from '../components/AgentCard';
describe('AgentCard', () => {
const mockAgent = {
id: '1',
name: 'Test Agent',
status: 'active'
};
it('renders agent name', () => {
render(<AgentCard agent={mockAgent} onSelect={() => {}} />);
expect(screen.getByText('Test Agent')).toBeInTheDocument();
});
it('calls onSelect when clicked', () => {
const onSelect = vi.fn();
render(<AgentCard agent={mockAgent} onSelect={onSelect} />);
fireEvent.click(screen.getByText('Test Agent'));
expect(onSelect).toHaveBeenCalledWith('1');
});
});
Integration Tests
import { render, screen, waitFor } from '@testing-library/react';
import { Dashboard } from '../components/Dashboard';
import { server } from '../mocks/server';
import { http, HttpResponse } from 'msw';
it('loads and displays agents', async () => {
server.use(
http.get('/api/agents', () => {
return HttpResponse.json([
{ id: '1', name: 'Agent 1', status: 'active' }
]);
})
);
render(<Dashboard />);
await waitFor(() => {
expect(screen.getByText('Agent 1')).toBeInTheDocument();
});
});
Mocking API
// mocks/handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('/api/agents', () => {
return HttpResponse.json([
{ id: '1', name: 'Agent 1', status: 'active' }
]);
}),
http.get('/api/agents/:id', ({ params }) => {
return HttpResponse.json({
id: params.id,
name: `Agent ${params.id}`,
status: 'active'
});
})
];
Test Utilities
// utils/test-utils.tsx
import { render, RenderOptions } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
export function renderWithProviders(
ui: React.ReactElement,
options?: Omit<RenderOptions, 'wrapper'>
) {
return render(ui, {
wrapper: ({ children }) => (
<QueryClientProvider client={queryClient}>
<BrowserRouter>
{children}
</BrowserRouter>
</QueryClientProvider>
),
...options,
});
}
Test Data Management
Factories
# tests/factories.py
import factory
from heretek_swarm.memory import MemoryAccessRecord
class MemoryFactory(factory.Factory):
class Meta:
model = MemoryAccessRecord
content = factory.Faker('sentence')
importance = factory.Faker('pyfloat', min_value=0, max_value=1)
tags = factory.LazyFunction(lambda: ['test', 'sample'])
Fixtures
# tests/fixtures/memories.json
[
{
"id": "mem_001",
"content": "Test memory 1",
"importance": 0.8,
"tags": ["test", "learning"]
},
{
"id": "mem_002",
"content": "Test memory 2",
"importance": 0.6,
"tags": ["observation"]
}
]
Test Categories
Unit Tests
- Fast execution
- Isolated components
- Mock external dependencies
- High coverage target (80%+)
Integration Tests
- Test component interactions
- Real database/service calls
- Slower execution
- Test critical paths
End-to-End Tests
- Full user workflows
- Browser automation
- Slowest execution
- Critical user journeys
CI/CD Integration
GitHub Actions
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
python-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: uv sync
- run: ruff check backend/ tests/
- run: pytest tests/ -v --cov=heretek_swarm
frontend-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: cd swarm-dashboard && npm install
- run: npm run lint
- run: npm test
- run: npm run build
Debugging Tests
Common Issues
-
Async tests not running
- Use
@pytest.mark.asyncio - Check
asyncio_mode = "auto"in config
- Use
-
Flaky tests
- Add proper waits
- Mock time-dependent code
- Use deterministic test data
-
Import errors
- Check test file location
- Verify module paths
- Use absolute imports
-
Memory leaks
- Clean up fixtures
- Close connections
- Use context managers
Debug Commands
# Verbose output
pytest tests/ -v -s
# Stop on first failure
pytest tests/ -x
# Run last failed tests
pytest tests/ --lf
# Show local variables on failure
pytest tests/ --tb=long
# Debug with pdb
pytest tests/ --pdb
Best Practices
- Test early, test often - Write tests alongside code
- One assertion per test - Keep tests focused
- Descriptive names - Test names should explain intent
- Independent tests - Tests shouldn't depend on each other
- Fast feedback - Unit tests should run in milliseconds
- Clean tests - Remove skipped/ignored tests regularly
- Test edge cases - Include boundary conditions
- Mock external services - Don't depend on external APIs
- Use fixtures - Share test setup code
- Document complex tests - Add comments for non-obvious assertions
Coverage Requirements
- New code: 80%+ coverage required
- Critical paths: 90%+ coverage
- Existing code: Maintain current coverage
- Coverage reports: Generate in CI
- Coverage gates: Fail build if below threshold