Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[flake8]
max-line-length = 110
extend-ignore = E203
exclude = .venv, .git, __pycache__, build, dist
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: CI

on: [push, pull_request]
on:
pull_request:
branches:
- dev
- main

jobs:
build:
Expand All @@ -13,10 +17,9 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install -r requirements.txt
- name: Lint with flake8
run: |
pip install flake8
flake8 src tests
- name: Run tests
run: |
Expand Down
2 changes: 1 addition & 1 deletion .prettierrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"useTabs": false,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 120,
"printWidth": 110,
"semi": true,
"endOfLine": "lf",
"overrides": [
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"python.analysis.typeCheckingMode": "basic",
"python.analysis.autoImportCompletions": true,
"python.defaultInterpreterPath": ".venv/bin/python",
"python.terminal.activateEnvInCurrentTerminal": true
"python.terminal.activateEnvInCurrentTerminal": true,
"cSpell.words": ["MQTT"]
}
248 changes: 248 additions & 0 deletions README_TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
# Robot Library Python — Testing Guide

## Overview

The robot library includes comprehensive unit and integration tests to validate functionality without requiring a physical robot or external MQTT broker.

- **Unit Tests** (`test_all.py`): Fast, isolated tests using mocks
- **Integration Tests** (`test_integration.py`): Real MQTT client behavior with in-process broker or live broker

## Quick Start

### Run All Tests

From the repository root:

```bash
cd src
python -m unittest discover -s robot -p "test_*.py" -v
```

Or run specific test suites:

```bash
# Unit tests only
python -m unittest robot.test_all -v

# Integration tests only
python -m unittest robot.test_integration -v

# Both
python -m unittest robot.test_all robot.test_integration -v
```

### Expected Output

```
test_coordinate_publish_and_setters (robot.test_all.RobotPackageSmokeTests...) ... ok
test_motion_controller_stub_coord_and_moves (robot.test_all.RobotPackageSmokeTests...) ... ok
test_neopixel_and_indicator_publish (robot.test_all.RobotPackageSmokeTests...) ... ok
test_proximity_reading_type (robot.test_all.RobotPackageSmokeTests...) ... ok
test_rgb_color_type_basic (robot.test_all.RobotPackageSmokeTests...) ... ok
test_sensors_handle_subscription (robot.test_all.RobotPackageSmokeTests...) ... ok
test_client_initialization (robot.test_integration.IntegrationTestRobotMqttClient...) ... ok
test_mqtt_msg_queueing (robot.test_integration.IntegrationTestRobotMqttClient...) ... ok
test_multiple_subscribers (robot.test_integration.IntegrationTestRobotMqttClient...) ... ok
test_publish_and_receive (robot.test_integration.IntegrationTestRobotMqttClient...) ... ok
test_client_queue_operations (robot.test_integration.RobotMqttClientMockTests...) ... ok
test_in_queue_append (robot.test_integration.RobotMqttClientMockTests...) ... ok

Ran 12 tests in 0.024s

OK
```

## Test Structure

### Unit Tests (`src/robot/test_all.py`)

Fast smoke tests using lightweight mocks, no external dependencies.

**Coverage:**
- `RGBColorType`: Color initialization, hex code parsing, string parsing, comparison
- `ProximityReadingType`: Distance/color parsing, list operations
- `Coordinate`: Getters, setters, publish operations
- `MotionController`: Movement calculations, zero-speed handling
- `NeoPixel`: Initialization, color changes, publish
- `Sensors` (Distance, Color, Proximity): Subscription handling, state updates

**Run:**
```bash
python -m unittest robot.test_all -v
```

**Execution Time:** < 0.01s

### Integration Tests (`src/robot/test_integration.py`)

Tests for `RobotMqttClient` behavior with real or simulated MQTT broker.

**Coverage:**
- Client initialization and connection
- Publish/subscribe with in-process broker
- Multi-client message routing
- Message queue operations
- Connection lifecycle

**Run:**
```bash
python -m unittest robot.test_integration -v
```

**Execution Time:** < 0.05s

## MQTT Broker Setup (Optional)

### For Development/Integration Testing

The integration tests work with or without a real MQTT broker:

- **Without broker**: Uses in-process `InMemoryMQTTBroker` stub (tests skip gracefully)
- **With broker**: Tests connect to real `localhost:1883`

#### Install Mosquitto (Windows via Chocolatey)

```powershell
choco install mosquitto
```

#### Start Mosquitto

```bash
mosquitto -p 1883
```

Or use Windows Service:
```powershell
net start mosquitto
```

#### Verify Connection

```bash
python -c "from paho import mqtt; print('MQTT available')"
```

## Development Workflow

### Before Committing

1. **Run all tests:**
```bash
cd src
python -m unittest robot.test_all robot.test_integration -v
```

2. **Check for syntax errors (optional):**
```bash
python -m py_compile robot/**/*.py
```

3. **Run specific test file:**
```bash
python -m unittest robot.test_all.RobotPackageSmokeTests.test_rgb_color_type_basic -v
```

### Adding New Tests

1. Add test method to existing test class or create new `TestCase`:
```python
def test_new_feature(self):
# Arrange
obj = MyClass()

# Act
result = obj.do_something()

# Assert
self.assertEqual(result, expected_value)
```

2. Run tests to verify:
```bash
python -m unittest robot.test_all -v
```

## Dependencies

### Required
- Python 3.10+
- (No external packages for unit tests)

### Optional
- `paho-mqtt`: For real MQTT broker integration (auto-stubbed if missing)
- Mosquitto: Real MQTT broker for development (optional)

## Troubleshooting

### Import Errors in IDE

If VS Code shows `Import "robot.x.y" could not be resolved`:

1. Ensure `src/` is the Python source root
2. VS Code settings (`.vscode/settings.json`):
```json
{
"python.analysis.extraPaths": ["${workspaceFolder}/src"]
}
```

### Tests Won't Run

**Error: `No module named robot`**
```bash
cd src
python -m unittest robot.test_all -v # Must run from src/
```

**Error: `ModuleNotFoundError: No module named 'paho'`**
- This is expected and graceful. Tests skip MQTT connection tests.
- To fix: `pip install paho-mqtt`

### MQTT Connection Refused

If tests show `MQTT connection error`:
1. Ensure Mosquitto is running: `mosquitto -p 1883`
2. Check if port 1883 is in use: `netstat -ano | findstr :1883`
3. Tests will skip gracefully if broker unavailable

## Test Coverage

| Module | Status | Notes |
|--------|--------|-------|
| `types/` | ✅ Full | RGBColorType, ProximityReadingType |
| `sensors/` | ✅ Full | Distance, Color, Proximity |
| `helpers/` | ✅ Partial | Coordinate, MotionController (logic tested) |
| `indicators/` | ✅ Full | NeoPixel |
| `mqtt/` | ✅ Partial | RobotMqttClient (connection + queue ops) |
| `communication/` | ⚠️ Mock only | Requires full robot context |
| `robot_base/` | ⚠️ Mock only | Requires MQTT server + robot setup |

## CI/CD Integration

For GitHub Actions or similar:

```yaml
- name: Run Tests
run: |
cd src
python -m unittest discover -s robot -p "test_*.py" -v
```

## Performance Benchmarks

| Test Suite | Count | Duration | Notes |
|-----------|-------|----------|-------|
| Unit Tests | 6 | < 0.01s | No I/O, no network |
| Integration Tests | 6 | < 0.05s | In-process broker or real MQTT |
| **Total** | **12** | **< 0.1s** | Fast feedback loop |

## Further Reading

- [unittest Documentation](https://docs.python.org/3/library/unittest.html)
- [MQTT Protocol](https://mqtt.org/)
- [Mosquitto Docs](https://mosquitto.org/documentation/)

---

**Last Updated:** January 12, 2026
2 changes: 1 addition & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ apidoc:
html:
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html"

livehtml:
livehtml: clean
sphinx-autobuild --host 0.0.0.0 --port ${PORT} -c . "$(SOURCEDIR)" "$(BUILDDIR)/html"
8 changes: 8 additions & 0 deletions docs/api/robot.communication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ robot.communication package
Submodules
----------

robot.communication.communication module
----------------------------------------

.. automodule:: robot.communication.communication
:members:
:show-inheritance:
:undoc-members:

robot.communication.directed\_comm module
-----------------------------------------

Expand Down
10 changes: 10 additions & 0 deletions docs/api/robot.exception.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
robot.exception package
=======================

Module contents
---------------

.. automodule:: robot.exception
:members:
:show-inheritance:
:undoc-members:
8 changes: 8 additions & 0 deletions docs/api/robot.helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ robot.helpers.coordinate module
:show-inheritance:
:undoc-members:

robot.helpers.motion\_controller module
---------------------------------------

.. automodule:: robot.helpers.motion_controller
:members:
:show-inheritance:
:undoc-members:

robot.helpers.robot\_mqtt module
--------------------------------

Expand Down
8 changes: 8 additions & 0 deletions docs/api/robot.indicators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ robot.indicators package
Submodules
----------

robot.indicators.abstract\_indicator module
-------------------------------------------

.. automodule:: robot.indicators.abstract_indicator
:members:
:show-inheritance:
:undoc-members:

robot.indicators.neopixel module
--------------------------------

Expand Down
10 changes: 10 additions & 0 deletions docs/api/robot.interfaces.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
robot.interfaces package
========================

Module contents
---------------

.. automodule:: robot.interfaces
:members:
:show-inheritance:
:undoc-members:
29 changes: 29 additions & 0 deletions docs/api/robot.mqtt.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
robot.mqtt package
==================

Submodules
----------

robot.mqtt.mqtt\_msg module
---------------------------

.. automodule:: robot.mqtt.mqtt_msg
:members:
:show-inheritance:
:undoc-members:

robot.mqtt.robot\_mqtt\_client module
-------------------------------------

.. automodule:: robot.mqtt.robot_mqtt_client
:members:
:show-inheritance:
:undoc-members:

Module contents
---------------

.. automodule:: robot.mqtt
:members:
:show-inheritance:
:undoc-members:
Loading
Loading