9.5 KiB
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
# 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 utilitiestest_fragmentation.py- Packet fragmentation and reassemblytest_gatt_server.py- GATT server functionalitytest_ble_peer_interface.py- Per-peer connection managementtest_error_recovery.py- Error handling and recoverytest_prioritization.py- Connection prioritization logictest_multi_device_simulation.py- Multi-node mesh simulationtest_integration.py- Configuration and integration tests
Running Specific Tests
# 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:
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):
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:
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:
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:
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:
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
# 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
-
Install on each device:
pip install -r requirements.txt cp src/RNS/Interfaces/BLE*.py ~/.reticulum/interfaces/ -
Configure interface on each device (same
service_uuid):[[BLE Interface]] type = BLEInterface enabled = yes device_name = Device-1 # Unique per device service_uuid = 00000001-5824-4f48-9e1a-3b3e8f0c1234 -
Start Reticulum on each device:
rnsd --verbose
Integration Test Scenarios
Test 1: Peer Discovery
Objective: Verify devices discover each other
- Start
rnsdon both devices - Monitor logs for discovery messages
- 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
- Wait for discovery
- Monitor logs for connection
- Check
rnstatusfor 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
- Establish connection
- Send announces from one device
- Monitor reception on other device
# 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)
- Place devices in line: A <-> B <-> C
- Ensure A and C can only connect via B
- Send packets from A to C
- Verify routing through B
Test 5: Connection Recovery
Objective: Verify reconnection after disconnection
- Establish connection
- Move devices out of range or restart one device
- Return to range
- Verify: Automatic reconnection within 60 seconds
Performance Testing
Throughput Test
Measure packet transmission rate:
# 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:
- Send echo request from Device A
- Device B responds immediately
- Measure time from send to receive
Expected latency:
- Local (same room): 50-200ms
- Medium range (10-15m): 100-500ms
Connection Scaling
Test maximum connections:
- Configure
max_connections = 7 - Connect 7 devices simultaneously
- Verify all connections stable
Expected: All 7 connections maintained for >5 minutes
Troubleshooting Tests
Test Not Running
Problem: Pytest can't find tests
Solution:
# 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:
# 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:
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:
# 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
- Create test file in
tests/directory - Import required fixtures from
conftest.py - Write test functions (prefix with
test_) - Use descriptive names and docstrings
Example:
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:
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:
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
-
Run tests before committing
pytest -
Check coverage for new code
pytest --cov=src/RNS/Interfaces --cov-report=term-missing -
Test both success and failure cases
- Happy path
- Error conditions
- Edge cases
-
Use meaningful assertions
# Good assert len(fragments) == 3, "Expected 3 fragments for 500-byte packet" # Less helpful assert len(fragments) == 3 -
Keep tests independent
- Each test should work in isolation
- Don't rely on test execution order
- Clean up resources in teardown
Additional Resources
Questions?
If you have questions about testing, please open an issue with the testing label.