The GAME SDK includes a comprehensive testing framework to ensure reliability and maintainability. This guide explains how to write and run tests for the SDK.
Tests are organized in the tests/ directory:
tests/
├── conftest.py # Shared test fixtures
├── test_config.py # Configuration tests
├── test_utils.py # Utility function tests
└── ...
-
Install development dependencies:
pip install -r requirements-dev.txt
-
Run tests:
pytest
-
Run tests with coverage:
pytest --cov=game_sdk
Common test fixtures are defined in conftest.py:
@pytest.fixture
def mock_config():
"""Fixture providing a test configuration."""
return SDKConfig(
api_base_url="https://test.virtuals.io",
api_version="test",
request_timeout=5
)
@pytest.fixture
def mock_response():
"""Fixture providing a mock HTTP response."""
def _mock_response(status_code=200, json_data=None):
mock = Mock()
mock.status_code = status_code
mock.json.return_value = json_data or {}
return mock
return _mock_response-
Group Related Tests:
class TestAgent: def test_creation(self): pass def test_execution(self): pass
-
Use Descriptive Names:
def test_get_access_token_with_invalid_key(): pass def test_create_agent_with_missing_fields(): pass
-
Mock HTTP Responses:
def test_api_call(mock_response): mock = mock_response(200, {"data": {"result": "success"}}) with patch('requests.post', return_value=mock): result = api_call() assert result == {"result": "success"}
-
Test Error Cases:
def test_api_error(mock_response): mock = mock_response(500, {"error": "Server Error"}) with patch('requests.post', return_value=mock): with pytest.raises(APIError) as exc: api_call() assert exc.value.status_code == 500
def test_config_override():
"""Test that configuration can be overridden."""
config = SDKConfig(api_base_url="https://test.example.com")
assert config.get("api_base_url") == "https://test.example.com"
# Other values should remain default
assert config.get("api_version") == "v1"def test_validation():
"""Test input validation."""
with pytest.raises(ValidationError) as exc:
create_agent("", "desc", "goal")
assert "required" in str(exc.value)-
Unit Tests:
- Test individual components in isolation
- Mock external dependencies
- Focus on edge cases
-
Integration Tests:
- Test component interactions
- Use minimal mocking
- Focus on common workflows
-
Validation Tests:
- Test input validation
- Test error handling
- Test edge cases
-
Test Independence:
def test_independent(mock_config): """Each test should be independent.""" config = mock_config config.set("timeout", 30) assert config.get("timeout") == 30
-
Clear Setup and Teardown:
class TestWithSetup: @pytest.fixture(autouse=True) def setup(self): self.config = SDKConfig() yield # Cleanup code here
-
Meaningful Assertions:
def test_with_context(): """Include context in assertions.""" result = process_data([1, 2, 3]) assert result == 6, "Sum should be 6 for input [1, 2, 3]"
-
Run All Tests:
pytest
-
Run Specific Tests:
pytest tests/test_utils.py pytest tests/test_utils.py::test_get_access_token
-
Run with Coverage:
pytest --cov=game_sdk --cov-report=html
The SDK uses GitHub Actions for CI:
-
Run Tests on Push:
name: Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 - name: Install dependencies run: pip install -r requirements-dev.txt - name: Run tests run: pytest
-
Coverage Reports:
pytest --cov=game_sdk --cov-report=xml
-
Print Debug Info:
def test_with_debug(caplog): caplog.set_level(logging.DEBUG) result = complex_operation() print(caplog.text) # View logs
-
Use PDB:
pytest --pdb
When adding new functionality:
- Create a new test file if needed
- Add tests for success cases
- Add tests for error cases
- Add tests for edge cases
- Update documentation if needed