Testing
Comprehensive guide to testing WYN360 CLI during development and contribution.
Test Structure
tests/
├── __init__.py
├── test_agent.py # Agent and tool tests (46 tests)
├── test_cli.py # CLI and slash command tests (33 tests)
├── test_config.py # Configuration tests (25 tests)
├── test_utils.py # Utility function tests (29 tests)
├── test_browser_*.py # Browser automation tests
├── test_document_*.py # Document processing tests
└── test_credential_*.py # Security and credential tests
# Total: 133+ tests
Running Tests
Basic Test Execution
Run all tests:
WYN360_SKIP_CONFIRM=1 poetry run pytest tests/ -v
Run specific test file:
poetry run pytest tests/test_agent.py -v
Run specific test class:
poetry run pytest tests/test_utils.py::TestExecuteCommandSafe -v
Run with short traceback:
WYN360_SKIP_CONFIRM=1 poetry run pytest tests/ -v --tb=short
Coverage Analysis
Generate coverage report:
poetry run pytest tests/ --cov=wyn360_cli --cov-report=html
View coverage in browser:
open htmlcov/index.html # macOS
xdg-open htmlcov/index.html # Linux
Test Categories
Unit Tests
Agent Tests (test_agent.py)
- WYN360Agent initialization
- Tool method functionality
- Conversation history management
- Token tracking
- Model switching
CLI Tests (test_cli.py)
- Slash command parsing
- Command execution
- Input/output handling
- Error handling
Configuration Tests (test_config.py)
- Config file loading
- Environment variable handling
- Default value setting
- Hierarchical config merging
Utility Tests (test_utils.py)
- File operations
- Command execution safety
- Project analysis
- Performance metrics
Integration Tests
Browser Tests (test_browser_*.py)
- Browser automation
- Website fetching
- Vision-based navigation
- Authentication flows
Document Tests (test_document_*.py)
- Multi-format document reading
- Vision mode processing
- Chunking and embedding
- Cost tracking
Security Tests (test_credential_*.py)
- Credential encryption/decryption
- Session management
- Audit logging
- Permission handling
Test Environment Setup
Required Environment Variables
# Skip interactive confirmations during tests
export WYN360_SKIP_CONFIRM=1
# Test API keys (use test/mock keys)
export ANTHROPIC_API_KEY=test_key_anthropic
export GEMINI_API_KEY=test_key_gemini
export GH_TOKEN=test_key_github
export HF_TOKEN=test_key_huggingface
Mock Configuration
Tests use mocking to avoid real API calls:
# Example from tests
@patch('wyn360_cli.agent.WYN360Agent')
def test_agent_initialization(mock_agent):
"""Test agent initializes with correct parameters."""
mock_agent.return_value = MagicMock()
# Test implementation
Writing New Tests
Test Structure Template
import pytest
from unittest.mock import Mock, patch, MagicMock
from wyn360_cli.your_module import YourClass
class TestYourClass:
"""Test suite for YourClass functionality."""
def setup_method(self):
"""Set up test fixtures before each test method."""
self.instance = YourClass()
def test_basic_functionality(self):
"""Test basic functionality works as expected."""
# Arrange
input_data = "test_input"
expected_output = "expected_result"
# Act
result = self.instance.method(input_data)
# Assert
assert result == expected_output
@patch('wyn360_cli.your_module.external_dependency')
def test_with_mocking(self, mock_external):
"""Test functionality that depends on external services."""
# Arrange
mock_external.return_value = "mocked_response"
# Act
result = self.instance.method_with_dependency()
# Assert
assert result is not None
mock_external.assert_called_once()
Async Test Template
import pytest
import asyncio
class TestAsyncFunctionality:
"""Test async methods."""
@pytest.mark.asyncio
async def test_async_method(self):
"""Test async method functionality."""
instance = AsyncClass()
result = await instance.async_method()
assert result is not None
Testing Best Practices
1. Test Categories
Unit Tests: Test individual functions/methods in isolation
def test_utility_function():
"""Test utility function with known input/output."""
result = utility_function("input")
assert result == "expected_output"
Integration Tests: Test component interactions
@pytest.mark.asyncio
async def test_agent_tool_integration():
"""Test agent and tool work together."""
agent = WYN360Agent()
result = await agent.read_file("test_file.py")
assert "def " in result # Contains function definition
End-to-End Tests: Test complete workflows
def test_complete_workflow():
"""Test entire user workflow."""
# This would test CLI → Agent → Tools → Output
pass
2. Mock External Dependencies
Always mock external services:
@patch('requests.get')
def test_web_fetch(mock_get):
"""Test web fetching with mocked HTTP calls."""
mock_get.return_value.text = "mocked content"
result = fetch_website("https://example.com")
assert result == "mocked content"
3. Test Error Conditions
def test_error_handling():
"""Test proper error handling."""
with pytest.raises(ValueError, match="Invalid input"):
function_that_should_raise("invalid_input")
4. Use Fixtures for Common Setup
@pytest.fixture
def sample_config():
"""Provide sample configuration for tests."""
return {
"model": "test-model",
"max_tokens": 100,
"custom_instructions": "Test instructions"
}
def test_with_fixture(sample_config):
"""Test using the fixture."""
agent = WYN360Agent(config=sample_config)
assert agent.config["model"] == "test-model"
Continuous Integration
GitHub Actions
Tests run automatically on:
- Pull requests to main branch
- Pushes to main branch
- Release creation
Test Matrix
Tests run against:
- Python 3.10, 3.11, 3.12
- Linux, macOS, Windows
- Multiple dependency versions
Debugging Test Failures
Common Issues
Import Errors:
# Ensure package is installed in development mode
poetry install
# Check Python path
python -c "import sys; print('\n'.join(sys.path))"
API Key Errors:
# Ensure skip confirmation is set
export WYN360_SKIP_CONFIRM=1
# Use mock API keys
export ANTHROPIC_API_KEY=test_key
Async Test Issues:
# Ensure proper async test marking
@pytest.mark.asyncio
async def test_async_function():
result = await async_function()
assert result is not None
Debug Output
Run with debug output:
poetry run pytest tests/ -v -s --tb=long
Run single test with debugging:
poetry run pytest tests/test_agent.py::TestWYN360Agent::test_specific_method -v -s
Expected Test Output
When all tests pass:
============================= test session starts ==============================
platform linux -- Python 3.10.12, pytest-8.4.2, pluggy-1.6.0
cachedir: .pytest_cache
rootdir: /home/workbench/wyn360-cli/wyn360-cli
configfile: pyproject.toml
plugins: asyncio-1.2.0, mock-3.15.1
collected 133 items
tests/test_agent.py::TestWYN360Agent::test_agent_initialization PASSED [ 1%]
tests/test_agent.py::TestHistoryManagement::test_clear_history PASSED [ 18%]
tests/test_cli.py::TestSlashCommands::test_clear_command PASSED [ 42%]
tests/test_config.py::TestWYN360Config::test_default_values PASSED [ 60%]
tests/test_utils.py::TestExecuteCommandSafe::test_execute_command PASSED [100%]
============================== 133 passed in 2.64s
Performance Testing
Benchmark Tests
import time
def test_performance_benchmark():
"""Test performance meets expectations."""
start_time = time.time()
# Perform operation
result = expensive_operation()
end_time = time.time()
execution_time = end_time - start_time
assert execution_time < 5.0 # Should complete in under 5 seconds
assert result is not None
For more testing examples, see the existing test files in the tests/ directory.