Skip to content

Commit 483022c

Browse files
committed
Add GitHub Actions workflows for code quality and testing + basic tests
1 parent d77bbf5 commit 483022c

File tree

12 files changed

+1328
-0
lines changed

12 files changed

+1328
-0
lines changed

.github/workflows/quality.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Code Quality
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
9+
jobs:
10+
quality:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up Python 3.12
17+
uses: actions/setup-python@v4
18+
with:
19+
python-version: "3.12"
20+
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install -r requirements-test.txt
25+
26+
- name: Check code formatting
27+
run: |
28+
ruff format --check --diff
29+
30+
- name: Lint code
31+
run: |
32+
ruff check --output-format=github
33+
34+
- name: Run tests with coverage info
35+
run: |
36+
python -m pytest tests/ -v --asyncio-mode=auto --tb=short
37+
38+
- name: Check test file count
39+
run: |
40+
echo "Total test files: $(find tests/ -name 'test_*.py' | wc -l)"
41+
echo "Total tests: $(python -m pytest tests/ --collect-only -q | grep '::' | wc -l)"
42+
43+
- name: Validate test requirements coverage
44+
run: |
45+
echo "✅ Validating test coverage for requirements:"
46+
echo "1. No exceptions when selecting only one feature during configuration"
47+
python -m pytest tests/test_simple_validation.py::TestBasicValidation::test_config_flow_feature_validation -v
48+
python -m pytest tests/test_simple_validation.py::TestBasicValidation::test_single_feature_configurations -v
49+
50+
echo "2. No exception if API calls fail"
51+
python -m pytest tests/test_api_helpers.py::TestFetchAllPages::test_http_error_response -v
52+
python -m pytest tests/test_coordinator.py::TestUnifiDeviceCoordinator::test_fetch_devices_api_failure -v
53+
54+
echo "3. No exception if missing information in API responses"
55+
python -m pytest tests/test_unifi_device.py::TestUnifiDevice::test_device_with_unset_values -v
56+
python -m pytest tests/test_api_helpers.py::TestFetchAllPages::test_missing_data_attribute -v

.github/workflows/tests.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ["3.12", "3.13"]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python ${{ matrix.python-version }}
20+
uses: actions/setup-python@v4
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
24+
- name: Cache pip dependencies
25+
uses: actions/cache@v3
26+
with:
27+
path: ~/.cache/pip
28+
key: ${{ runner.os }}-pip-${{ hashFiles('requirements-test.txt') }}
29+
restore-keys: |
30+
${{ runner.os }}-pip-
31+
32+
- name: Install dependencies
33+
run: |
34+
python -m pip install --upgrade pip
35+
pip install -r requirements-test.txt
36+
37+
- name: Lint with Ruff
38+
run: |
39+
# Check code formatting
40+
ruff format --check
41+
# Check code quality
42+
ruff check
43+
44+
- name: Run tests
45+
run: |
46+
python -m pytest tests/ -v --asyncio-mode=auto
47+
48+
- name: Upload test results
49+
uses: actions/upload-artifact@v3
50+
if: always()
51+
with:
52+
name: test-results-${{ matrix.python-version }}
53+
path: |
54+
.pytest_cache/
55+
*.log

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Unifi Network (custom integration)
22

3+
[![Tests](https://github.com/wittypluck/ha-unifi-network/actions/workflows/tests.yml/badge.svg)](https://github.com/wittypluck/ha-unifi-network/actions/workflows/tests.yml)
4+
[![Code Quality](https://github.com/wittypluck/ha-unifi-network/actions/workflows/quality.yml/badge.svg)](https://github.com/wittypluck/ha-unifi-network/actions/workflows/quality.yml)
5+
36
Home Assistant custom integration for UniFi Network that uses UniFi's official Integration API. It discovers UniFi devices and connected clients, exposes presence detection (device trackers), and provides comprehensive monitoring sensors and control buttons.
47

58
## What this provides

pytest.ini

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[pytest]
2+
minversion = 6.0
3+
addopts = -ra -q --tb=short
4+
testpaths = tests
5+
python_files = test_*.py
6+
python_classes = Test*
7+
python_functions = test_*
8+
asyncio_mode = auto

requirements-test.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Test dependencies
2+
pytest>=7.0.0
3+
pytest-asyncio>=0.21.0
4+
5+
# Integration dependencies (for testing)
6+
attrs>=22.0.0
7+
aiohttp>=3.8.0
8+
voluptuous>=0.13.0
9+
httpx>=0.24.0
10+
python-dateutil>=2.8.0
11+
12+
# Code quality
13+
ruff>=0.1.0

tests/README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# UniFi Network Integration Tests
2+
3+
This directory contains tests for the UniFi Network Home Assistant integration that **do not depend on Home Assistant core**. The tests validate key functionality and error handling scenarios without requiring the full Home Assistant environment.
4+
5+
## Test Coverage
6+
7+
The test suite validates the following requirements as requested:
8+
9+
### ✅ No exception if API calls fail
10+
- `test_api_helpers.py::TestFetchAllPages::test_http_error_response`
11+
- `test_api_helpers.py::TestFetchAllPages::test_none_response`
12+
- `test_api_helpers.py::TestFetchAllPages::test_no_parsed_response`
13+
- `test_coordinator.py::TestUnifiDeviceCoordinator::test_fetch_devices_api_failure`
14+
- `test_coordinator.py::TestUnifiClientCoordinator::test_fetch_clients_api_failure`
15+
16+
Tests that API failures are handled gracefully:
17+
- HTTP error responses (500, 404, etc.)
18+
- Network connectivity issues
19+
- Malformed/missing response data
20+
- Individual device/client API call failures
21+
- Coordinator-level error handling
22+
23+
### ✅ No exception if missing information in API responses
24+
- `test_api_helpers.py::TestFetchAllPages::test_missing_data_attribute`
25+
- `test_unifi_device.py::TestUnifiDevice::test_device_with_unset_values`
26+
- `test_unifi_device.py::TestUnifiDevice::test_device_with_missing_attributes`
27+
- `test_unifi_device.py::TestUnifiDevice::test_device_with_no_details`
28+
- `test_coordinator.py::TestUnifiDeviceCoordinator::test_fetch_devices_with_statistics_failure`
29+
- `test_coordinator.py::TestUnifiDeviceCoordinator::test_fetch_devices_with_details_failure`
30+
31+
Tests handling of:
32+
- `Unset` values from the API client
33+
- Missing optional device/client attributes
34+
- Partial data when some API calls fail
35+
- Pagination responses without data
36+
- Device details/statistics unavailable
37+
38+
## Test Structure
39+
40+
### Core Test Files
41+
42+
- **`test_api_helpers.py`** - Tests for API helper functions (pagination, error handling)
43+
- **`test_unifi_device.py`** - Tests for UnifiDevice wrapper (handling missing data)
44+
- **`test_coordinator.py`** - Tests for data coordinators (API failure scenarios)
45+
46+
### Support Files
47+
48+
- **`conftest.py`** - Mock Home Assistant components to avoid dependencies
49+
- **`pytest.ini`** - Pytest configuration for async test support
50+
51+
## Running Tests
52+
53+
### Prerequisites
54+
55+
```bash
56+
# Create and activate virtual environment
57+
python3 -m venv .venv
58+
source .venv/bin/activate # Linux/macOS
59+
# or: .venv\Scripts\activate # Windows
60+
61+
# Install dependencies
62+
pip install ruff pytest pytest-asyncio attrs aiohttp voluptuous httpx python-dateutil
63+
```
64+
65+
### Run All Tests
66+
67+
```bash
68+
cd /path/to/ha-unifi-network
69+
python -m pytest tests/ -v --asyncio-mode=auto
70+
```
71+
72+
### Run Specific Test Categories
73+
74+
```bash
75+
# API and data handling tests
76+
python -m pytest tests/test_api_helpers.py tests/test_unifi_device.py -v --asyncio-mode=auto
77+
78+
# Coordinator error handling tests
79+
python -m pytest tests/test_coordinator.py -v --asyncio-mode=auto
80+
```
81+
82+
## Test Results Summary
83+
84+
**39 tests passing** across 4 test files
85+
86+
- `test_api_helpers.py`: 10 tests (pagination, HTTP errors, malformed responses)
87+
- `test_coordinator.py`: 15 tests (API failures, partial data, error propagation)
88+
- `test_unifi_device.py`: 9 tests (Unset values, missing attributes, device info)
89+
90+
## Key Validated Scenarios
91+
92+
1. **Single Feature Selection**: Users can select devices-only or clients-only without exceptions
93+
2. **API Resilience**: All API failure modes are handled gracefully without crashing
94+
3. **Missing Data Handling**: Integration handles incomplete API responses robustly
95+
4. **Error Propagation**: Errors are properly caught and logged, not leaked to users
96+
5. **Pagination**: Large datasets are fetched correctly even with API inconsistencies
97+
98+
The tests demonstrate that the integration is robust against real-world API issues and configuration scenarios without requiring a full Home Assistant installation.

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Tests for the UniFi Network integration."""

0 commit comments

Comments
 (0)