ha-testcontainer 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ha_testcontainer-1.0.1/LICENSE +21 -0
- ha_testcontainer-1.0.1/PKG-INFO +432 -0
- ha_testcontainer-1.0.1/README.md +379 -0
- ha_testcontainer-1.0.1/ha_testcontainer/__init__.py +23 -0
- ha_testcontainer-1.0.1/ha_testcontainer/container.py +475 -0
- ha_testcontainer-1.0.1/ha_testcontainer/visual.py +199 -0
- ha_testcontainer-1.0.1/ha_testcontainer.egg-info/PKG-INFO +432 -0
- ha_testcontainer-1.0.1/ha_testcontainer.egg-info/SOURCES.txt +13 -0
- ha_testcontainer-1.0.1/ha_testcontainer.egg-info/dependency_links.txt +1 -0
- ha_testcontainer-1.0.1/ha_testcontainer.egg-info/requires.txt +14 -0
- ha_testcontainer-1.0.1/ha_testcontainer.egg-info/top_level.txt +1 -0
- ha_testcontainer-1.0.1/pyproject.toml +65 -0
- ha_testcontainer-1.0.1/setup.cfg +4 -0
- ha_testcontainer-1.0.1/tests/test_container.py +94 -0
- ha_testcontainer-1.0.1/tests/test_container_unit.py +233 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lint Free Technology
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ha-testcontainer
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Full test container for Home Assistant with demo config, custom components, and visual testing
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 Lint Free Technology
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Project-URL: Homepage, https://github.com/Lint-Free-Technology/ha-testcontainer
|
|
28
|
+
Project-URL: Issues, https://github.com/Lint-Free-Technology/ha-testcontainer/issues
|
|
29
|
+
Keywords: home-assistant,testcontainers,testing,docker,playwright
|
|
30
|
+
Classifier: Development Status :: 3 - Alpha
|
|
31
|
+
Classifier: Intended Audience :: Developers
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
+
Classifier: Topic :: Software Development :: Testing
|
|
37
|
+
Requires-Python: >=3.11
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
License-File: LICENSE
|
|
40
|
+
Requires-Dist: testcontainers>=4.9
|
|
41
|
+
Requires-Dist: requests>=2.32
|
|
42
|
+
Requires-Dist: websocket-client>=1.6
|
|
43
|
+
Provides-Extra: visual
|
|
44
|
+
Requires-Dist: playwright>=1.50; extra == "visual"
|
|
45
|
+
Requires-Dist: pytest-playwright>=0.5; extra == "visual"
|
|
46
|
+
Requires-Dist: Pillow>=10.0; extra == "visual"
|
|
47
|
+
Provides-Extra: test
|
|
48
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
49
|
+
Requires-Dist: pytest-playwright>=0.5; extra == "test"
|
|
50
|
+
Requires-Dist: playwright>=1.50; extra == "test"
|
|
51
|
+
Requires-Dist: Pillow>=10.0; extra == "test"
|
|
52
|
+
Dynamic: license-file
|
|
53
|
+
|
|
54
|
+
# ha-testcontainer
|
|
55
|
+
|
|
56
|
+
> A full, reusable test container for Home Assistant.
|
|
57
|
+
|
|
58
|
+
`ha-testcontainer` is a Python library that wraps the official Home Assistant
|
|
59
|
+
Docker image in a [Testcontainers](https://testcontainers.com/)-based class.
|
|
60
|
+
It handles all the plumbing — startup, programmatic onboarding, long-lived
|
|
61
|
+
token creation, and custom component mounting — so your tests can focus on
|
|
62
|
+
what matters.
|
|
63
|
+
|
|
64
|
+
[UIX (UI eXtension)](https://github.com/Lint-Free-Technology/uix) is the
|
|
65
|
+
primary consumer and uses this library as a replacement for its legacy local
|
|
66
|
+
test stack.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Features
|
|
71
|
+
|
|
72
|
+
| Capability | Detail |
|
|
73
|
+
|---|---|
|
|
74
|
+
| **Version flexibility** | `stable`, `beta`, `dev`, or any pinned tag (`2024.6.0`) |
|
|
75
|
+
| **Automatic onboarding** | Creates an admin user and mints a long-lived API token with no manual interaction |
|
|
76
|
+
| **Demo entities** | Built-in HA `demo` integration gives you lights, sensors, weather objects immediately |
|
|
77
|
+
| **Custom config** | Mount any `configuration.yaml` tree via `config_path=` |
|
|
78
|
+
| **Custom components** | Mount any `custom_components/` directory via `custom_components_path=` |
|
|
79
|
+
| **Fetch any component** | `scripts/fetch_component.py owner/repo` — downloads any GitHub-hosted HA component |
|
|
80
|
+
| **Fetch any frontend plugin** | `scripts/fetch_plugin.py owner/repo` — downloads any JS dashboard plugin; registers it as a Lovelace resource |
|
|
81
|
+
| **Storage-mode dashboard** | Default Lovelace dashboard in storage mode; REST-pushable for tests |
|
|
82
|
+
| **REST API helper** | `ha.api("GET", "states")` — authenticated calls with zero boilerplate |
|
|
83
|
+
| **Integration setup** | `ha.setup_integration("my_domain")` — drives config-flow programmatically |
|
|
84
|
+
| **Playwright visual tests** | Session-scoped browser context, token injection, pixel-diff snapshot comparison |
|
|
85
|
+
| **Boilerplate example** | `examples/test_custom_component.py` — copy, fill in TODO values, done |
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Quick start
|
|
90
|
+
|
|
91
|
+
### 1 — Install
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install -e ".[test]"
|
|
95
|
+
playwright install chromium
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2 — Fetch a custom component
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Any GitHub-hosted HA custom component (Python, goes into custom_components/):
|
|
102
|
+
python scripts/fetch_component.py Lint-Free-Technology/uix
|
|
103
|
+
python scripts/fetch_component.py Lint-Free-Technology/uix 5.3.1 # pinned version
|
|
104
|
+
|
|
105
|
+
# Or via make (COMPONENT is required):
|
|
106
|
+
make setup COMPONENT=Lint-Free-Technology/uix
|
|
107
|
+
make setup COMPONENT=Lint-Free-Technology/uix VERSION=5.3.1
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 2b — Fetch a frontend plugin (optional)
|
|
111
|
+
|
|
112
|
+
Frontend plugins are JavaScript dashboard modules (Lovelace cards, etc.),
|
|
113
|
+
distinct from Python custom components. They are downloaded into
|
|
114
|
+
`ha-config/www/dashboard/` and automatically served by HA at `/local/…`.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Download and register a dashboard plugin:
|
|
118
|
+
python scripts/fetch_plugin.py custom-cards/button-card
|
|
119
|
+
python scripts/fetch_plugin.py thomasloven/lovelace-card-mod 3.4.4
|
|
120
|
+
|
|
121
|
+
# Or via make:
|
|
122
|
+
make fetch-plugin PLUGIN=custom-cards/button-card
|
|
123
|
+
make fetch-plugin PLUGIN=thomasloven/lovelace-card-mod VERSION=3.4.4
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 3 — Run tests
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
make test # unit + integration tests (no browser)
|
|
130
|
+
make test-visual # Playwright visual tests (requires Docker + Playwright)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
See **[Testing](#testing)** below for a full breakdown of each tier.
|
|
134
|
+
|
|
135
|
+
### 4 — Explore locally with docker compose
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
make up # starts HA at http://localhost:8123
|
|
139
|
+
make down
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Usage in your own project
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from ha_testcontainer import HATestContainer, HAVersion
|
|
148
|
+
|
|
149
|
+
with HATestContainer(
|
|
150
|
+
version=HAVersion.STABLE, # or "beta", "dev", "2024.6.0"
|
|
151
|
+
config_path="ha-config",
|
|
152
|
+
custom_components_path="custom_components",
|
|
153
|
+
) as ha:
|
|
154
|
+
# Set up any custom component via config-flow
|
|
155
|
+
ha.setup_integration("uix")
|
|
156
|
+
|
|
157
|
+
# REST API — authenticated, zero boilerplate
|
|
158
|
+
states = ha.api("GET", "states").json()
|
|
159
|
+
|
|
160
|
+
print(ha.get_url()) # http://localhost:<random-port>
|
|
161
|
+
print(ha.get_token()) # long-lived access token
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### pytest fixture example
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
# conftest.py
|
|
168
|
+
import pytest
|
|
169
|
+
from ha_testcontainer import HATestContainer
|
|
170
|
+
|
|
171
|
+
@pytest.fixture(scope="session")
|
|
172
|
+
def ha():
|
|
173
|
+
with HATestContainer(config_path="ha-config", custom_components_path="custom_components") as c:
|
|
174
|
+
c.setup_integration("uix")
|
|
175
|
+
yield c
|
|
176
|
+
|
|
177
|
+
# test_my_component.py
|
|
178
|
+
def test_api(ha):
|
|
179
|
+
resp = ha.api("GET", "states")
|
|
180
|
+
assert resp.status_code == 200
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Playwright visual test example
|
|
184
|
+
|
|
185
|
+
See [`examples/test_custom_component.py`](examples/test_custom_component.py) for a
|
|
186
|
+
fully annotated boilerplate that any component author can copy.
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from ha_testcontainer.visual import PAGE_LOAD_TIMEOUT, assert_snapshot
|
|
190
|
+
|
|
191
|
+
def test_my_card(ha_page, ha_url):
|
|
192
|
+
ha_page.goto(f"{ha_url}/lovelace/0", wait_until="networkidle",
|
|
193
|
+
timeout=PAGE_LOAD_TIMEOUT)
|
|
194
|
+
assert_snapshot(ha_page, "my_card_baseline")
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Run `SNAPSHOT_UPDATE=1 pytest tests/visual/` to create or update baselines.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Fetching custom components
|
|
202
|
+
|
|
203
|
+
`scripts/fetch_component.py` works with **any** GitHub repository that follows
|
|
204
|
+
the standard HA custom-component layout (a `custom_components/<name>/` directory
|
|
205
|
+
in the repository root):
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
python scripts/fetch_component.py owner/repo # latest release
|
|
209
|
+
python scripts/fetch_component.py owner/repo 5.3.1 # specific version
|
|
210
|
+
python scripts/fetch_component.py owner/repo --list # list releases
|
|
211
|
+
python scripts/fetch_component.py owner/repo --target-dir /other/path
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The script auto-discovers all `custom_components/` sub-directories in the
|
|
215
|
+
release archive, so multi-component repositories are handled correctly.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Fetching frontend plugins (dashboard cards)
|
|
220
|
+
|
|
221
|
+
`scripts/fetch_plugin.py` downloads **JavaScript dashboard modules** — Lovelace
|
|
222
|
+
cards and similar frontend-only plugins — from GitHub releases. These are
|
|
223
|
+
distinct from Python custom components: they live in `www/` rather than
|
|
224
|
+
`custom_components/`, and are loaded by the HA frontend via Lovelace resources.
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
python scripts/fetch_plugin.py owner/repo # latest release
|
|
228
|
+
python scripts/fetch_plugin.py owner/repo 1.2.3 # specific version
|
|
229
|
+
python scripts/fetch_plugin.py owner/repo --list # list releases
|
|
230
|
+
python scripts/fetch_plugin.py owner/repo --plugin-name custom-name
|
|
231
|
+
python scripts/fetch_plugin.py owner/repo --resource-type js # legacy (default: module)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The script:
|
|
235
|
+
1. Downloads JS files from the release (assets, zip assets, or source archive fallback).
|
|
236
|
+
2. Places them at `ha-config/www/dashboard/<plugin-name>/<file>.js`.
|
|
237
|
+
3. Registers each file as a Lovelace resource in `ha-config/lovelace_resources.yaml`.
|
|
238
|
+
|
|
239
|
+
HA serves `ha-config/www/` at `/local/`, so the plugin is immediately available
|
|
240
|
+
to Lovelace dashboards as `/local/dashboard/<plugin-name>/<file>.js`.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Configuration
|
|
245
|
+
|
|
246
|
+
### HA version
|
|
247
|
+
|
|
248
|
+
| Value | Image tag pulled |
|
|
249
|
+
|---|---|
|
|
250
|
+
| `HAVersion.STABLE` (default) | `ghcr.io/home-assistant/home-assistant:stable` |
|
|
251
|
+
| `HAVersion.BETA` | `ghcr.io/home-assistant/home-assistant:beta` |
|
|
252
|
+
| `HAVersion.DEV` | `ghcr.io/home-assistant/home-assistant:dev` |
|
|
253
|
+
| `"2024.6.0"` | `ghcr.io/home-assistant/home-assistant:2024.6.0` |
|
|
254
|
+
|
|
255
|
+
Override at runtime:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
HA_VERSION=beta pytest tests/
|
|
259
|
+
HA_VERSION=2024.6.0 make test
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Config & custom components
|
|
263
|
+
|
|
264
|
+
| Environment variable | Default | Purpose |
|
|
265
|
+
|---|---|---|
|
|
266
|
+
| `HA_VERSION` | `stable` | Image tag |
|
|
267
|
+
| `HA_CONFIG_PATH` | `ha-config/` | Host dir mounted as `/config` |
|
|
268
|
+
| `HA_CUSTOM_COMPONENTS_PATH` | `custom_components/` | Host dir mounted as `/config/custom_components` |
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Repository layout
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
ha-testcontainer/
|
|
276
|
+
├── ha_testcontainer/
|
|
277
|
+
│ ├── __init__.py # public API: HATestContainer, HAVersion, visual helpers
|
|
278
|
+
│ ├── container.py # HATestContainer implementation
|
|
279
|
+
│ └── visual.py # PAGE_LOAD_TIMEOUT, assert_snapshot, inject_ha_token
|
|
280
|
+
├── ha-config/
|
|
281
|
+
│ ├── configuration.yaml # demo HA config (default_config + demo integration)
|
|
282
|
+
│ ├── lovelace_resources.yaml # Lovelace resources list (managed by fetch_plugin.py)
|
|
283
|
+
│ ├── www/ # served at /local/ by HA; plugins downloaded here
|
|
284
|
+
│ └── themes/ # theme YAML files (auto-loaded)
|
|
285
|
+
├── custom_components/
|
|
286
|
+
│ └── README.md # populated by scripts/fetch_component.py (gitignored)
|
|
287
|
+
├── scripts/
|
|
288
|
+
│ ├── fetch_component.py # download any HA Python component from GitHub releases
|
|
289
|
+
│ └── fetch_plugin.py # download any JS frontend plugin; register as resource
|
|
290
|
+
├── examples/
|
|
291
|
+
│ └── test_custom_component.py # boilerplate visual test — copy & customise
|
|
292
|
+
├── tests/
|
|
293
|
+
│ ├── conftest.py # session-scoped ha / ha_url / ha_token fixtures
|
|
294
|
+
│ ├── test_container_unit.py # unit tests — no Docker needed (14 tests)
|
|
295
|
+
│ ├── test_container.py # integration tests — requires Docker (10 tests)
|
|
296
|
+
│ └── visual/
|
|
297
|
+
│ ├── conftest.py # Playwright fixtures (ha_page, ha_browser_context)
|
|
298
|
+
│ └── snapshots/ # gitignored — no baselines committed here (see below)
|
|
299
|
+
├── docker-compose.yml # local dev: docker compose up
|
|
300
|
+
├── Makefile # setup / test / update-snapshots targets
|
|
301
|
+
└── pyproject.toml
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Snapshot-based visual testing
|
|
307
|
+
|
|
308
|
+
Snapshot tests follow a two-file convention:
|
|
309
|
+
|
|
310
|
+
| File | Description |
|
|
311
|
+
|---|---|
|
|
312
|
+
| `snapshots/<name>.png` | **Committed baseline** — the ground truth, lives in the **consumer's repo** |
|
|
313
|
+
| `snapshots/<name>.actual.png` | Generated on every run — gitignored |
|
|
314
|
+
|
|
315
|
+
On the **first run** (or when `SNAPSHOT_UPDATE=1` is set), the actual
|
|
316
|
+
screenshot becomes the baseline. Subsequent runs diff the two; any pixel
|
|
317
|
+
difference causes the test to fail.
|
|
318
|
+
|
|
319
|
+
Baselines are placed **next to the calling test file** automatically — no
|
|
320
|
+
configuration needed.
|
|
321
|
+
|
|
322
|
+
> **Important — baselines are stored in the consumer's repo, not here.**
|
|
323
|
+
> ha-testcontainer is a reusable library; it does not commit any snapshot PNG
|
|
324
|
+
> files. All `*.png` files under `tests/visual/snapshots/` are gitignored in
|
|
325
|
+
> this repository. When you write visual tests for your own component, baselines
|
|
326
|
+
> are committed in *your* project's `tests/visual/snapshots/` directory.
|
|
327
|
+
> They will never appear in ha-testcontainer's history.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Testing
|
|
332
|
+
|
|
333
|
+
The test suite has three tiers:
|
|
334
|
+
|
|
335
|
+
### Tier 1 — Unit tests (no Docker required)
|
|
336
|
+
|
|
337
|
+
These run in milliseconds and cover the Python logic of `HATestContainer`
|
|
338
|
+
in isolation (URL construction, token handling, API path normalisation):
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
pip install -e ".[test]" # install once
|
|
342
|
+
pytest tests/test_container_unit.py -v
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Or via make:
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
make install
|
|
349
|
+
make test
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
`make test` runs **all** non-browser tests, including both unit and
|
|
353
|
+
integration tests, skipping the visual tier.
|
|
354
|
+
|
|
355
|
+
### Tier 2 — Integration tests (Docker required)
|
|
356
|
+
|
|
357
|
+
These start a real Home Assistant container and exercise the full lifecycle
|
|
358
|
+
(onboarding, REST API, demo entities, Lovelace push):
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
# Prerequisites: Docker daemon running, HA image available
|
|
362
|
+
pytest tests/test_container.py -v
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The container is started once per pytest session (session-scoped fixture)
|
|
366
|
+
and reused across all tests in the file. Startup takes ~60 s the first time
|
|
367
|
+
while HA initialises.
|
|
368
|
+
|
|
369
|
+
Environment variables let you control which image and config directory are
|
|
370
|
+
used:
|
|
371
|
+
|
|
372
|
+
| Variable | Default | Purpose |
|
|
373
|
+
|---|---|---|
|
|
374
|
+
| `HA_VERSION` | `stable` | Image tag (`stable`, `beta`, `dev`, `2024.6.0`, …) |
|
|
375
|
+
| `HA_CONFIG_PATH` | `ha-config/` | Host dir mounted as `/config` |
|
|
376
|
+
| `HA_CUSTOM_COMPONENTS_PATH` | `custom_components/` | Host dir mounted as `/config/custom_components` |
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
HA_VERSION=beta pytest tests/test_container.py -v
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Tier 3 — Visual (Playwright) tests (Docker + Playwright required)
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
pip install -e ".[test]"
|
|
386
|
+
playwright install chromium
|
|
387
|
+
pytest tests/visual/ -v
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Or via make:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
make install
|
|
394
|
+
make test-visual
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Visual tests open a Chromium browser, log in to the running HA instance, and
|
|
398
|
+
compare screenshots against committed baselines. Baselines are stored in the
|
|
399
|
+
**consumer's own repository** — see [Snapshot-based visual testing](#snapshot-based-visual-testing).
|
|
400
|
+
|
|
401
|
+
### Version smoke tests (slow, optional)
|
|
402
|
+
|
|
403
|
+
These pull the `stable`, `beta`, and `dev` images in sequence and verify that
|
|
404
|
+
the container starts for each:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
pytest tests/test_container.py -v -m version_smoke
|
|
408
|
+
# or:
|
|
409
|
+
make test-smoke
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
They are skipped by default to avoid pulling large images on every run.
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
UIX's `test/docker-compose.yaml` + `test/configuration.yaml` + `test/lovelace.yaml`
|
|
419
|
+
are replaced by `make up` and UIX writing its own `tests/` using `HATestContainer`.
|
|
420
|
+
|
|
421
|
+
1. Add `ha-testcontainer` as a dev dependency.
|
|
422
|
+
2. Fetch UIX: `python scripts/fetch_component.py Lint-Free-Technology/uix`.
|
|
423
|
+
3. Replace `docker compose -f test/docker-compose.yaml up` with `make up`.
|
|
424
|
+
4. Copy `examples/test_custom_component.py` into UIX's `tests/visual/`, fill in
|
|
425
|
+
UIX-specific TODO values, and add UIX-specific test cases.
|
|
426
|
+
5. Delete UIX's `test/` directory.
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## License
|
|
431
|
+
|
|
432
|
+
MIT — see [LICENSE](LICENSE).
|