cosmoguard-bd/tests/README.md

220 lines
4.7 KiB
Markdown

# PIF Compiler - Test Suite
## Overview
Comprehensive test suite for the PIF Compiler project using `pytest`.
## Structure
```
tests/
├── __init__.py # Test package marker
├── conftest.py # Shared fixtures and configuration
├── test_cosing_service.py # COSING service tests
├── test_models.py # (TODO) Pydantic model tests
├── test_echa_service.py # (TODO) ECHA service tests
└── README.md # This file
```
## Installation
```bash
# Install test dependencies
uv add --dev pytest pytest-cov pytest-mock
# Or manually install
uv pip install pytest pytest-cov pytest-mock
```
## Running Tests
### Run All Tests (Unit only)
```bash
uv run pytest
```
### Run Specific Test File
```bash
uv run pytest tests/test_cosing_service.py
```
### Run Specific Test Class
```bash
uv run pytest tests/test_cosing_service.py::TestParseCasNumbers
```
### Run Specific Test
```bash
uv run pytest tests/test_cosing_service.py::TestParseCasNumbers::test_single_cas_number
```
### Run with Verbose Output
```bash
uv run pytest -v
```
### Run with Coverage Report
```bash
uv run pytest --cov=src/pif_compiler --cov-report=html
# Open htmlcov/index.html in browser
```
## Test Categories
### Unit Tests (Default)
Fast tests with no external dependencies. Run by default.
```bash
uv run pytest -m unit
```
### Integration Tests
Tests that hit real APIs or databases. Skipped by default.
```bash
uv run pytest -m integration
```
### Slow Tests
Tests that take longer to run. Skipped by default.
```bash
uv run pytest -m slow
```
### Database Tests
Tests requiring MongoDB. Ensure Docker is running.
```bash
cd utils
docker-compose up -d
uv run pytest -m database
```
## Test Organization
### `test_cosing_service.py`
**Coverage:**
-`parse_cas_numbers()` - CAS parsing logic
- Single/multiple CAS
- Different separators (/, ;, ,, --)
- Parentheses removal
- Whitespace handling
- Invalid dash removal
-`cosing_search()` - API search
- Search by name
- Search by CAS
- Search by EC number
- Search by ID
- No results handling
- Invalid mode error
-`clean_cosing()` - JSON cleaning
- Basic field cleaning
- Empty tag removal
- CAS parsing
- URL creation
- Field renaming
- ✅ Integration tests (marked as `@pytest.mark.integration`)
- Real API calls (requires internet)
## Writing New Tests
### Example Unit Test
```python
class TestMyFunction:
"""Test my_function."""
def test_basic_case(self):
"""Test basic functionality."""
result = my_function("input")
assert result == "expected"
def test_edge_case(self):
"""Test edge case handling."""
with pytest.raises(ValueError):
my_function("invalid")
```
### Example Mock Test
```python
from unittest.mock import Mock, patch
@patch('module.external_api_call')
def test_with_mock(mock_api):
"""Test with mocked external call."""
mock_api.return_value = {"data": "mocked"}
result = my_function()
assert result == "expected"
mock_api.assert_called_once()
```
### Example Fixture Usage
```python
def test_with_fixture(sample_cosing_response):
"""Test using a fixture from conftest.py."""
result = clean_cosing(sample_cosing_response)
assert "cosingUrl" in result
```
## Best Practices
1. **Naming**: Test files/classes/functions start with `test_`
2. **Arrange-Act-Assert**: Structure tests clearly
3. **One assertion focus**: Each test should test one thing
4. **Use fixtures**: Reuse test data via `conftest.py`
5. **Mock external calls**: Don't hit real APIs in unit tests
6. **Mark appropriately**: Use `@pytest.mark.integration` for slow tests
7. **Descriptive names**: Test names should describe what they test
## Common Commands
```bash
# Run fast tests only (skip integration/slow)
uv run pytest -m "not integration and not slow"
# Run only integration tests
uv run pytest -m integration
# Run with detailed output
uv run pytest -vv
# Stop at first failure
uv run pytest -x
# Run last failed tests
uv run pytest --lf
# Run tests matching pattern
uv run pytest -k "test_parse"
# Generate coverage report
uv run pytest --cov=src/pif_compiler --cov-report=term-missing
```
## CI/CD Integration
For GitHub Actions (example):
```yaml
- name: Run tests
run: |
uv run pytest -m "not integration" --cov --cov-report=xml
```
## TODO
- [ ] Add tests for `models.py` (Pydantic validation)
- [ ] Add tests for `echa_service.py`
- [ ] Add tests for `echa_parser.py`
- [ ] Add tests for `echa_extractor.py`
- [ ] Add tests for `database_service.py`
- [ ] Add tests for `pubchem_service.py`
- [ ] Add integration tests with test database
- [ ] Set up GitHub Actions CI