ble-reticulum/TESTING.md
2025-10-26 19:14:14 -04:00

470 lines
9.5 KiB
Markdown

# Testing Guide
This document describes how to test the Reticulum BLE Interface.
## Test Suite Overview
The test suite includes:
- **Unit tests**: Test individual components in isolation
- **Integration tests**: Test component interactions and simulated multi-device scenarios
- **Coverage**: 98+ tests covering core functionality
## Quick Start
```bash
# Create and activate virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate # On Linux/macOS
# Install test dependencies
pip install -r requirements-dev.txt
# Run all tests
pytest
# Run with verbose output
pytest -v
# Run with coverage report
pytest --cov=src/RNS/Interfaces --cov-report=html
```
## Test Organization
### Test Files
- `conftest.py` - Pytest fixtures and shared test utilities
- `test_fragmentation.py` - Packet fragmentation and reassembly
- `test_gatt_server.py` - GATT server functionality
- `test_ble_peer_interface.py` - Per-peer connection management
- `test_error_recovery.py` - Error handling and recovery
- `test_prioritization.py` - Connection prioritization logic
- `test_multi_device_simulation.py` - Multi-node mesh simulation
- `test_integration.py` - Configuration and integration tests
### Running Specific Tests
```bash
# Run single test file
pytest tests/test_fragmentation.py
# Run single test function
pytest tests/test_fragmentation.py::test_fragment_single_packet
# Run tests matching pattern
pytest -k "fragment"
# Run with specific markers
pytest -m "not slow"
```
## Test Categories
### 1. Fragmentation Tests
Tests for packet fragmentation and reassembly:
```bash
pytest tests/test_fragmentation.py -v
```
Key tests:
- Single packet fragmentation
- Large packet handling (multiple fragments)
- Packet reassembly
- Fragment ordering
- Error cases (corrupted fragments, timeout)
### 2. GATT Server Tests
Tests for peripheral mode (GATT server):
```bash
pytest tests/test_gatt_server.py -v
```
Key tests:
- GATT server initialization
- Service registration
- Characteristic read/write
- Notification handling
- Multiple client connections
### 3. Connection Management Tests
Tests for peer discovery and connection:
```bash
pytest tests/test_ble_peer_interface.py -v
```
Key tests:
- Peer discovery
- Connection establishment
- Disconnection handling
- Connection state management
- Data transmission
### 4. Error Recovery Tests
Tests for error handling:
```bash
pytest tests/test_error_recovery.py -v
```
Key tests:
- Connection timeout handling
- Retry logic
- Exponential backoff
- Blacklist management
- Recovery from errors
### 5. Prioritization Tests
Tests for connection prioritization:
```bash
pytest tests/test_prioritization.py -v
```
Key tests:
- RSSI-based scoring
- Connection history tracking
- Peer selection algorithm
- Blacklist expiration
### 6. Multi-Device Simulation
Tests for multi-node mesh networking:
```bash
pytest tests/test_multi_device_simulation.py -v
```
Key tests:
- Multiple simultaneous connections
- Packet routing through mesh
- Network topology changes
- Connection rotation
## Coverage
### Generate Coverage Report
```bash
# HTML report (recommended)
pytest --cov=src/RNS/Interfaces --cov-report=html
# Open htmlcov/index.html in browser
# Terminal report
pytest --cov=src/RNS/Interfaces --cov-report=term-missing
# XML report (for CI)
pytest --cov=src/RNS/Interfaces --cov-report=xml
```
### Coverage Goals
- Overall coverage: >90%
- Core modules (BLEInterface, BLEFragmentation): >95%
- Error handling paths: >85%
## Integration Testing
### Prerequisites
For integration testing with real BLE hardware:
- 2+ BLE-enabled devices (e.g., Raspberry Pi Zero W)
- BlueZ 5.x installed
- Devices on same network (for coordination)
### Setup
1. Install on each device:
```bash
pip install -r requirements.txt
cp src/RNS/Interfaces/BLE*.py ~/.reticulum/interfaces/
```
2. Configure interface on each device (same `service_uuid`):
```toml
[[BLE Interface]]
type = BLEInterface
enabled = yes
device_name = Device-1 # Unique per device
service_uuid = 00000001-5824-4f48-9e1a-3b3e8f0c1234
```
3. Start Reticulum on each device:
```bash
rnsd --verbose
```
### Integration Test Scenarios
#### Test 1: Peer Discovery
**Objective**: Verify devices discover each other
1. Start `rnsd` on both devices
2. Monitor logs for discovery messages
3. Verify: Each device discovers the other within 10 seconds
Expected output:
```
[2025-10-26 10:00:15] [INFO] Discovered peer: Device-2 (RSSI: -65 dBm)
```
#### Test 2: Connection Establishment
**Objective**: Verify devices connect successfully
1. Wait for discovery
2. Monitor logs for connection
3. Check `rnstatus` for active connections
Expected output:
```
BLE Interface [Enabled]
Peers: 1 connected, 0 discovered
Active connections: Device-2 (RSSI: -65 dBm)
```
#### Test 3: Packet Exchange
**Objective**: Verify data transmission
1. Establish connection
2. Send announces from one device
3. Monitor reception on other device
```bash
# On Device 1
rnid -a
# On Device 2 - should receive announce
tail -f ~/.reticulum/logfile
```
#### Test 4: Multi-Hop Routing
**Objective**: Verify mesh routing (requires 3+ devices)
1. Place devices in line: A <-> B <-> C
2. Ensure A and C can only connect via B
3. Send packets from A to C
4. Verify routing through B
#### Test 5: Connection Recovery
**Objective**: Verify reconnection after disconnection
1. Establish connection
2. Move devices out of range or restart one device
3. Return to range
4. Verify: Automatic reconnection within 60 seconds
## Performance Testing
### Throughput Test
Measure packet transmission rate:
```python
# Run from examples/
python ble_minimal_test.py test
```
Expected results:
- BLE 4.2 (185 byte MTU): ~15-20 KB/s
- BLE 5.0 (512 byte MTU): ~30-40 KB/s
### Latency Test
Measure round-trip time:
1. Send echo request from Device A
2. Device B responds immediately
3. Measure time from send to receive
Expected latency:
- Local (same room): 50-200ms
- Medium range (10-15m): 100-500ms
### Connection Scaling
Test maximum connections:
1. Configure `max_connections = 7`
2. Connect 7 devices simultaneously
3. Verify all connections stable
Expected: All 7 connections maintained for >5 minutes
## Troubleshooting Tests
### Test Not Running
**Problem**: Pytest can't find tests
**Solution**:
```bash
# Ensure you're in project root
cd /path/to/ble-reticulum
# Run from root directory
pytest
# Or specify path explicitly
pytest tests/
```
### Import Errors
**Problem**: `ModuleNotFoundError: No module named 'RNS'`
**Solution**:
```bash
# Install in development mode
pip install -e .
# Or set PYTHONPATH
export PYTHONPATH="${PYTHONPATH}:$(pwd)/src"
pytest
```
### Async Warnings
**Problem**: Warnings about unclosed asyncio resources
**Solution**: These are usually harmless in tests, but can be suppressed:
```bash
pytest -W ignore::DeprecationWarning
```
### BLE Hardware Tests Skipped
**Problem**: Integration tests marked as skipped
**Reason**: Unit tests don't require real BLE hardware (they use mocks)
**Info**: This is expected behavior. Integration tests with real hardware should be run manually.
## Continuous Integration
### GitHub Actions
The repository includes CI configuration in `.github/workflows/test.yml`:
- Runs on: Python 3.8, 3.9, 3.10, 3.11
- Tests: All unit tests
- Coverage: Generates coverage report
- Linting: Code style checks (if configured)
### Running Locally
Simulate CI environment:
```bash
# Test on specific Python version
python3.9 -m pytest
# Test with clean environment
python -m venv test-env
source test-env/bin/activate
pip install -r requirements-dev.txt
pytest
deactivate
```
## Test Development
### Writing New Tests
1. Create test file in `tests/` directory
2. Import required fixtures from `conftest.py`
3. Write test functions (prefix with `test_`)
4. Use descriptive names and docstrings
Example:
```python
import pytest
from RNS.Interfaces.BLEFragmentation import BLEFragmenter
def test_fragmenter_handles_empty_packet():
"""Test that fragmenter raises error for empty packets"""
fragmenter = BLEFragmenter(mtu=185)
with pytest.raises(ValueError, match="empty"):
fragmenter.fragment_packet(b"")
```
### Using Fixtures
Common fixtures available in `conftest.py`:
```python
def test_with_fragmenter(ble_fragmenter):
"""Use fragmenter fixture from conftest.py"""
fragments = ble_fragmenter.fragment_packet(b"test data")
assert len(fragments) >= 1
```
### Async Tests
For async code:
```python
import pytest
@pytest.mark.asyncio
async def test_async_operation():
"""Test asynchronous BLE operations"""
result = await some_async_function()
assert result is not None
```
## Best Practices
1. **Run tests before committing**
```bash
pytest
```
2. **Check coverage for new code**
```bash
pytest --cov=src/RNS/Interfaces --cov-report=term-missing
```
3. **Test both success and failure cases**
- Happy path
- Error conditions
- Edge cases
4. **Use meaningful assertions**
```python
# Good
assert len(fragments) == 3, "Expected 3 fragments for 500-byte packet"
# Less helpful
assert len(fragments) == 3
```
5. **Keep tests independent**
- Each test should work in isolation
- Don't rely on test execution order
- Clean up resources in teardown
## Additional Resources
- [pytest documentation](https://docs.pytest.org/)
- [pytest-asyncio documentation](https://pytest-asyncio.readthedocs.io/)
- [Coverage.py documentation](https://coverage.readthedocs.io/)
## Questions?
If you have questions about testing, please open an issue with the `testing` label.