# Refactoring: HIL docs
This commit is contained in:
parent
ab6d2f1393
commit
6f0e082849
5 changed files with 130 additions and 79 deletions
|
|
@ -108,14 +108,24 @@ PYOCD_FREQUENCY=4000000
|
||||||
FCB_PATH=tools/host/dcd/w25q128_fdcb.bin
|
FCB_PATH=tools/host/dcd/w25q128_fdcb.bin
|
||||||
|
|
||||||
# HIL — аппаратный стенд
|
# HIL — аппаратный стенд
|
||||||
HIL_VCOM_PORT=/dev/cu.usbmodemXXXX # MCU-Link VCOM (macOS: cu.usbmodem*, Linux: ttyACM*)
|
|
||||||
HIL_M5_PORT=/dev/cu.usbmodemYYYY # M5StampPLC USB CDC
|
|
||||||
HIL_VCOM_BAUD=115200
|
|
||||||
HIL_M5_BAUD=115200
|
|
||||||
HIL_READY_TIMEOUT=5.0
|
|
||||||
HIL_M5_TIMEOUT=3.0
|
|
||||||
HIL_PYOCD_FREQUENCY=1000000
|
HIL_PYOCD_FREQUENCY=1000000
|
||||||
HIL_BUILD_DIR=build/target-debug
|
HIL_BUILD_DIR=build/target-debug
|
||||||
|
HIL_TARGET_POWER_SETTLE_S=1.5 # задержка после включения питания (POR + стабилизация)
|
||||||
|
|
||||||
|
# VCOM на программаторе NXP MCU-Link
|
||||||
|
HIL_VCOM_PORT=/dev/cu.usbmodemXXXX # macOS: cu.usbmodem*, Linux: ttyACM*
|
||||||
|
HIL_VCOM_BAUD=115200
|
||||||
|
HIL_READY_TIMEOUT=5.0
|
||||||
|
|
||||||
|
# M5Stack StamPLC (промежуточная платформа для HIL)
|
||||||
|
HIL_M5_PORT=/dev/cu.usbmodemYYYY # M5StampPLC USB CDC
|
||||||
|
HIL_M5_BAUD=115200
|
||||||
|
HIL_M5_TIMEOUT=3.0
|
||||||
|
|
||||||
|
# VCOM на плате таргета (USB CDC, появляется после загрузки ELF)
|
||||||
|
HIL_USB_CDC_PORT=/dev/cu.usbmodemZZZZ
|
||||||
|
HIL_USB_CDC_BAUD=115200
|
||||||
|
HIL_USB_CDC_TIMEOUT=5.0
|
||||||
```
|
```
|
||||||
|
|
||||||
**Как значения попадают в инструменты:**
|
**Как значения попадают в инструменты:**
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ _OPTO_TO_RELAY = {1: 3, 2: 4, 3: 2}
|
||||||
|
|
||||||
| Файл | Назначение |
|
| Файл | Назначение |
|
||||||
|--------------|----------------------------------------------------------------|
|
|--------------|----------------------------------------------------------------|
|
||||||
| `agent.py` | MicroPython агент на M5. Принимает JSON-команды через USB CDC, управляет реле через I2C экспандер AW9523B |
|
| `agent.py` | MicroPython агент на M5. Принимает JSON-команды через USB CDC, подает сигналы на таргет |
|
||||||
| `cli.py` | Интерактивный CLI для ручного тестирования агента |
|
| `cli.py` | Интерактивный CLI для ручного тестирования агента |
|
||||||
| `power.py` | Скрипт управления питанием таргета (RLY1) из командной строки |
|
| `power.py` | Скрипт управления питанием таргета (RLY1) из командной строки |
|
||||||
|
|
||||||
|
|
@ -109,7 +109,6 @@ just host::m5-deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
> ⚠️ После изменения `agent.py` обязательно задеплоить перед запуском тестов.
|
> ⚠️ После изменения `agent.py` обязательно задеплоить перед запуском тестов.
|
||||||
> Иначе на M5 работает старая версия.
|
|
||||||
|
|
||||||
### MCU-Link — загрузка ELF и UART CLI
|
### MCU-Link — загрузка ELF и UART CLI
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -167,55 +167,59 @@ ls build/target-debug/tests/target/<name>/test_<name>.elf
|
||||||
|
|
||||||
## Шаг 5 — `conftest.py`: добавить фикстуры
|
## Шаг 5 — `conftest.py`: добавить фикстуры
|
||||||
|
|
||||||
Открыть `tools/hil/conftest.py` и добавить в конец раздела с фикстурами загрузки.
|
Открыть `tools/hil/conftest.py` и добавить:
|
||||||
|
|
||||||
|
1. Фикстуру загрузки `loaded_<n>` в конец раздела загрузок.
|
||||||
|
2. Одну строку в `_UART_FIXTURE_MAP` — фабрика `_make_uart_fixture` автоматически
|
||||||
|
создаст фикстуру `uart_<n>` через контекстный менеджер `_uart_context`.
|
||||||
|
|
||||||
### Базовый тест (без M5)
|
### Базовый тест (без M5)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
# 1. Фикстура загрузки — добавить в раздел loaded_*
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def loaded_<name>(request: pytest.FixtureRequest) -> None:
|
def loaded_<n>(request: pytest.FixtureRequest) -> None:
|
||||||
_load_elf(
|
_load_elf(
|
||||||
request,
|
request,
|
||||||
Path(cfg.BUILD_DIR) / "tests/target/<name>/test_<name>.elf",
|
Path(cfg.BUILD_DIR) / "tests/target/<n>/test_<n>.elf",
|
||||||
)
|
)
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
# 2. UART-фикстура — добавить одну строку в словарь
|
||||||
def uart_<name>(
|
_UART_FIXTURE_MAP = {
|
||||||
request: pytest.FixtureRequest,
|
...
|
||||||
loaded_<name>, # ← гарантирует порядок: ELF раньше UART
|
"uart_<n>": "loaded_<n>", # ← добавить
|
||||||
) -> Generator[serial.Serial, None, None]:
|
}
|
||||||
ser = _open_uart_and_wait_ready(request)
|
|
||||||
yield ser
|
|
||||||
ser.close()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Тест с M5 (GPIO, реле, питание)
|
### Тест с M5 (GPIO, реле, питание)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
# 1. Фикстура загрузки — зависимость от m5 гарантирует питание
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def loaded_<name>(request: pytest.FixtureRequest, m5: M5Agent) -> None:
|
def loaded_<n>(request: pytest.FixtureRequest, m5: M5Agent) -> None:
|
||||||
"""
|
"""
|
||||||
Зависит от m5 — питание таргета уже включено к моменту загрузки ELF.
|
Зависит от m5 — питание таргета уже включено к моменту загрузки ELF.
|
||||||
"""
|
"""
|
||||||
_load_elf(
|
_load_elf(
|
||||||
request,
|
request,
|
||||||
Path(cfg.BUILD_DIR) / "tests/target/<name>/test_<name>.elf",
|
Path(cfg.BUILD_DIR) / "tests/target/<n>/test_<n>.elf",
|
||||||
)
|
)
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
# 2. UART-фикстура — та же одна строка
|
||||||
def uart_<name>(
|
_UART_FIXTURE_MAP = {
|
||||||
request: pytest.FixtureRequest,
|
...
|
||||||
loaded_<name>,
|
"uart_<n>": "loaded_<n>", # ← добавить
|
||||||
) -> Generator[serial.Serial, None, None]:
|
}
|
||||||
ser = _open_uart_and_wait_ready(request)
|
|
||||||
yield ser
|
|
||||||
ser.close()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Правило:** если тест управляет железом через M5 — `loaded_<name>` должен явно
|
**Правило:** если тест управляет железом через M5 — `loaded_<n>` должен явно
|
||||||
зависеть от `m5`. Это гарантирует что питание включено до того как pyOCD
|
зависеть от `m5`. Это гарантирует что питание включено до того как pyOCD
|
||||||
попытается подключиться к MCU.
|
попытается подключиться к MCU.
|
||||||
|
|
||||||
|
> Ручное написание `uart_<n>` фикстур больше не требуется — фабрика
|
||||||
|
> `_make_uart_fixture` создаёт фикстуру с `_uart_context` (контекстный менеджер,
|
||||||
|
> гарантирует `ser.close()` при любом исходе).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Шаг 6 — `tools/hil/test_<name>.py`
|
## Шаг 6 — `tools/hil/test_<name>.py`
|
||||||
|
|
@ -429,7 +433,7 @@ uart.close() test_something
|
||||||
[ ] tests/target/<n>/CMakeLists.txt — сборка с bsp_boot_ram
|
[ ] tests/target/<n>/CMakeLists.txt — сборка с bsp_boot_ram
|
||||||
[ ] tests/target/CMakeLists.txt — add_subdirectory(<n>)
|
[ ] tests/target/CMakeLists.txt — add_subdirectory(<n>)
|
||||||
[ ] CMakePresets.json — добавить test_<n> в targets
|
[ ] CMakePresets.json — добавить test_<n> в targets
|
||||||
[ ] tools/hil/conftest.py — loaded_<n> + uart_<n>
|
[ ] tools/hil/conftest.py — loaded_<n> + строка в _UART_FIXTURE_MAP
|
||||||
[ ] tools/hil/test_<n>.py — pytest-тесты
|
[ ] tools/hil/test_<n>.py — pytest-тесты
|
||||||
[ ] just/host.just — рецепт hil-<n> (опционально)
|
[ ] just/host.just — рецепт hil-<n> (опционально)
|
||||||
[ ] just build::build-hil — зелёная сборка
|
[ ] just build::build-hil — зелёная сборка
|
||||||
|
|
|
||||||
|
|
@ -138,14 +138,14 @@ def flush_uart_buffer(uart):
|
||||||
```
|
```
|
||||||
|
|
||||||
**Правило:** `autouse` в `conftest.py` действует на **все** тесты в директории
|
**Правило:** `autouse` в `conftest.py` действует на **все** тесты в директории
|
||||||
и поддиректориях. Используй осторожно — можно случайно затронуть тесты,
|
и поддиректориях. Используется осторожно — можно случайно затронуть тесты,
|
||||||
которым эта фикстура не нужна.
|
которым эта фикстура не нужна.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Зависимости между фикстурами
|
## 5. Зависимости между фикстурами
|
||||||
|
|
||||||
Зависимость объявляется **в сигнатуре** фикстуры. pytest строит DAG и гарантирует
|
Зависимость объявляется **в сигнатуре** фикстуры. pytest строит `DAG` и гарантирует
|
||||||
порядок создания.
|
порядок создания.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
@ -200,15 +200,18 @@ tools/hil/
|
||||||
└── conftest.py ← (если бы был) виден только в m5/
|
└── conftest.py ← (если бы был) виден только в m5/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Что живёт в `conftest.py` нашего проекта
|
### Что живёт в `conftest.py` проекта
|
||||||
|
|
||||||
| Фикстура / функция | Scope | Назначение |
|
| Фикстура / функция | Scope | Назначение |
|
||||||
|---------------------|-------|------------|
|
|---------------------|-------|------------|
|
||||||
| `_load_elf()` | вспомогательная | pyOCD: halt → FLEXRAM → load ELF → run |
|
| `_load_elf()` | вспомогательная | pyOCD: halt → FLEXRAM → load ELF → run |
|
||||||
| `_open_uart_and_wait_ready()` | вспомогательная | Открыть VCOM, дождаться `READY\r\n` |
|
| `_uart_context()` | контекстный менеджер | Открыть VCOM, дождаться `READY\r\n`, гарантировать `close()` |
|
||||||
|
| `_make_uart_fixture()` | фабрика | Генерирует `uart_*` фикстуры из `_UART_FIXTURE_MAP` |
|
||||||
|
| `_UART_FIXTURE_MAP` | словарь | Связь `uart_<n>` → `loaded_<n>` для всех тестов |
|
||||||
| `loaded_host_uart` | module | Загрузить `test_host_uart.elf` |
|
| `loaded_host_uart` | module | Загрузить `test_host_uart.elf` |
|
||||||
| `loaded_hil_opto` | module | Загрузить `test_hil_opto.elf`, зависит от `m5` |
|
| `loaded_hil_opto` | module | Загрузить `test_hil_opto.elf`, зависит от `m5` |
|
||||||
| `uart` / `uart_hil_opto` | module | Открыть UART CLI, зависит от `loaded_*` |
|
| `uart` / `uart_opto` / ... | module | Создаются автоматически через `_UART_FIXTURE_MAP` |
|
||||||
|
| `usb_cdc_port` | module | USB CDC порт таргета, использует `cfg.TARGET_VCOM_*` |
|
||||||
| `m5` | module | Подключиться к M5, включить питание |
|
| `m5` | module | Подключиться к M5, включить питание |
|
||||||
| `uart_cmd()` | обычная функция | Отправить команду, прочитать ответ |
|
| `uart_cmd()` | обычная функция | Отправить команду, прочитать ответ |
|
||||||
|
|
||||||
|
|
@ -276,17 +279,37 @@ def loaded_<name>(request, m5): # m5 — только если нужно п
|
||||||
|
|
||||||
Teardown не нужен — MCU будет перезагружен при следующей загрузке ELF.
|
Teardown не нужен — MCU будет перезагружен при следующей загрузке ELF.
|
||||||
|
|
||||||
### 9.2. UART-сессия (с teardown)
|
### 9.2. UART-сессия (через фабрику)
|
||||||
|
|
||||||
|
Для создания UART-фикстур используется фабрика
|
||||||
|
`_make_uart_fixture` и словарь `_UART_FIXTURE_MAP`. Иначе, пришлось бы
|
||||||
|
вручную писать фикстуры`uart` / `uart_opto` / ... для каждого таргета.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
_UART_FIXTURE_MAP = {
|
||||||
|
"uart": "loaded_host_uart",
|
||||||
|
"uart_opto": "loaded_hil_opto",
|
||||||
|
"uart_can": "loaded_hil_can",
|
||||||
|
"uart_button": "loaded_hil_button",
|
||||||
|
"uart_hil_usb_cdc": "loaded_hil_usb_cdc",
|
||||||
|
}
|
||||||
|
|
||||||
|
def _make_uart_fixture(loaded_name: str):
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def uart_<name>(request, loaded_<name>):
|
def _fixture(request: pytest.FixtureRequest) -> Generator[serial.Serial, None, None]:
|
||||||
ser = _open_uart_and_wait_ready(request)
|
request.getfixturevalue(loaded_name)
|
||||||
|
port = request.config.getoption("--vcom")
|
||||||
|
with _uart_context(port, cfg.VCOM_BAUD, cfg.READY_TIMEOUT) as ser:
|
||||||
yield ser
|
yield ser
|
||||||
ser.close()
|
return _fixture
|
||||||
|
|
||||||
|
for _name, _dep in _UART_FIXTURE_MAP.items():
|
||||||
|
globals()[_name] = _make_uart_fixture(_dep)
|
||||||
```
|
```
|
||||||
|
|
||||||
`yield` обязателен — порт нужно закрыть, иначе следующий файл не сможет его открыть.
|
Для нового теста достаточно одной строки в `_UART_FIXTURE_MAP`.
|
||||||
|
Контекстный менеджер `_uart_context` гарантирует `ser.close()` при любом исходе
|
||||||
|
(исключение, `pytest.fail`, `KeyboardInterrupt`).
|
||||||
|
|
||||||
### 9.3. Управление стендом (M5 — с teardown)
|
### 9.3. Управление стендом (M5 — с teardown)
|
||||||
|
|
||||||
|
|
@ -352,21 +375,33 @@ def test_opto_ch1(self):
|
||||||
|
|
||||||
### 9.6. Ожидание `READY` от прошивки
|
### 9.6. Ожидание `READY` от прошивки
|
||||||
|
|
||||||
Паттерн из проекта — прошивка шлёт `READY\r\n` в цикле, пока хост не откроет порт:
|
Паттерн из проекта — прошивка шлёт `READY\r\n` в цикле, пока хост не откроет порт.
|
||||||
|
Реализован как контекстный менеджер `_uart_context`, который гарантирует закрытие
|
||||||
|
порта при любом исходе:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def _open_uart_and_wait_ready(request, timeout_s=5.0):
|
@contextmanager
|
||||||
port = request.config.getoption("--vcom")
|
def _uart_context(port: str, baud: int, ready_timeout: float):
|
||||||
ser = serial.Serial(port=port, baudrate=115200, timeout=2.0)
|
ser = serial.Serial(port=port, baudrate=baud, timeout=2.0, write_timeout=1.0)
|
||||||
deadline = time.monotonic() + timeout_s
|
try:
|
||||||
|
deadline = time.monotonic() + ready_timeout
|
||||||
|
ready = False
|
||||||
while time.monotonic() < deadline:
|
while time.monotonic() < deadline:
|
||||||
line = ser.readline().decode(errors="replace").strip()
|
line = ser.readline().decode("ascii", errors="replace").strip()
|
||||||
if line == "READY":
|
if line == "READY":
|
||||||
return ser
|
ready = True
|
||||||
ser.close()
|
break
|
||||||
raise TimeoutError("Прошивка не отправила READY")
|
if not ready:
|
||||||
|
pytest.fail(f"Прошивка не отправила READY за {ready_timeout} с")
|
||||||
|
ser.reset_input_buffer()
|
||||||
|
yield ser
|
||||||
|
finally:
|
||||||
|
ser.close() # выполняется всегда
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Все `uart_*` фикстуры используют `_uart_context` через фабрику `_make_uart_fixture`
|
||||||
|
(см. секцию 9.2).
|
||||||
|
|
||||||
### 9.7. Параметризация фикстур
|
### 9.7. Параметризация фикстур
|
||||||
|
|
||||||
Один тест — несколько входных наборов. Полезно для проверки всех каналов:
|
Один тест — несколько входных наборов. Полезно для проверки всех каналов:
|
||||||
|
|
@ -402,12 +437,10 @@ def uart(request, loaded_host_uart):
|
||||||
ser = _open_uart_and_wait_ready(request)
|
ser = _open_uart_and_wait_ready(request)
|
||||||
return ser # ser.close() никогда не вызовется!
|
return ser # ser.close() никогда не вызовется!
|
||||||
|
|
||||||
# ✅ yield + close
|
# ✅ Актуальное решение: _uart_context (контекстный менеджер)
|
||||||
@pytest.fixture(scope="module")
|
# ser.close() гарантирован блоком finally внутри _uart_context.
|
||||||
def uart(request, loaded_host_uart):
|
# Все uart_* фикстуры создаются через _make_uart_fixture,
|
||||||
ser = _open_uart_and_wait_ready(request)
|
# который использует _uart_context — ручной close() не нужен.
|
||||||
yield ser
|
|
||||||
ser.close()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Нет зависимости от `loaded_*` — UART открывается раньше ELF
|
### Нет зависимости от `loaded_*` — UART открывается раньше ELF
|
||||||
|
|
@ -478,21 +511,22 @@ def uart(fresh_state): # ScopeMismatch!
|
||||||
```python
|
```python
|
||||||
# 1. В conftest.py — загрузка ELF
|
# 1. В conftest.py — загрузка ELF
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def loaded_<name>(request, m5): # m5 только если нужен
|
def loaded_<n>(request, m5): # m5 только если нужен
|
||||||
_load_elf(request, Path(cfg.BUILD_DIR) / "tests/target/<name>/test_<name>.elf")
|
_load_elf(request, Path(cfg.BUILD_DIR) / "tests/target/<n>/test_<n>.elf")
|
||||||
|
|
||||||
# 2. В conftest.py — UART-сессия
|
# 2. В conftest.py — одна строка в _UART_FIXTURE_MAP
|
||||||
@pytest.fixture(scope="module")
|
_UART_FIXTURE_MAP = {
|
||||||
def uart_<name>(request, loaded_<name>):
|
...
|
||||||
ser = _open_uart_and_wait_ready(request)
|
"uart_<n>": "loaded_<n>", # ← добавить
|
||||||
yield ser
|
}
|
||||||
ser.close()
|
# Фабрика _make_uart_fixture создаст фикстуру автоматически
|
||||||
|
# с _uart_context (гарантирует ser.close())
|
||||||
|
|
||||||
# 3. В test_<name>.py — autouse setup
|
# 3. В test_<n>.py — autouse setup
|
||||||
class Test<Name>:
|
class Test<n>:
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def _setup(self, uart_<name>, m5): # m5 только если нужен
|
def _setup(self, uart_<n>, m5): # m5 только если нужен
|
||||||
self.ser = uart_<name>
|
self.ser = uart_<n>
|
||||||
self.m5 = m5
|
self.m5 = m5
|
||||||
|
|
||||||
def test_ping(self):
|
def test_ping(self):
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@ just host::setup-tools
|
||||||
```bash
|
```bash
|
||||||
HIL_VCOM_PORT=/dev/cu.usbmodemXXX # MCU-Link VCOM
|
HIL_VCOM_PORT=/dev/cu.usbmodemXXX # MCU-Link VCOM
|
||||||
HIL_M5_PORT=/dev/cu.usbmodemYYY # M5StampPLC
|
HIL_M5_PORT=/dev/cu.usbmodemYYY # M5StampPLC
|
||||||
HIL_BUILD_DIR=build/target-debug # путь к собранным ELF (обычно не менять)
|
HIL_USB_CDC_PORT=/dev/cu.usbmodemZZZ # USB CDC порт на плате таргета (если тест использует USB CDC)
|
||||||
|
HIL_BUILD_DIR=build/target-debug # путь к собранным ELF (по умолчанию)
|
||||||
```
|
```
|
||||||
|
|
||||||
Как найти нужные порты:
|
Как найти нужные порты:
|
||||||
|
|
@ -55,6 +56,12 @@ just host::m5-deploy
|
||||||
just host::m5-cli # интерактивный CLI для ручной отправки команд агенту
|
just host::m5-cli # интерактивный CLI для ручной отправки команд агенту
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Также можно запустить агент с интерактивным режимом CLI на хосте с помощью команды:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just host::m5-start
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Шаг 2 — Физическое подключение стенда
|
## Шаг 2 — Физическое подключение стенда
|
||||||
|
|
@ -82,8 +89,7 @@ just host::m5-power off
|
||||||
|
|
||||||
## Шаг 3 — Сборка HIL-прошивок (в devcontainer)
|
## Шаг 3 — Сборка HIL-прошивок (в devcontainer)
|
||||||
|
|
||||||
HIL-прошивки компилируются под ARM и собираются **внутри devcontainer**,
|
HIL-прошивки компилируются под ARM и собираются **внутри devcontainer**.
|
||||||
потому что там есть `arm-none-eabi-gcc` и весь SDK.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Открыть проект в VSCode → Reopen in Container
|
# Открыть проект в VSCode → Reopen in Container
|
||||||
|
|
@ -103,9 +109,6 @@ ls build/target-debug/tests/target/
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
> Пересобирать нужно только при изменении C-кода прошивок (`tests/target/*/main.c`
|
|
||||||
> или BSP). Изменения в Python-тестах (`tools/hil/test_*.py`) сборки не требуют.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Шаг 4 — Запуск тестов (на хосте, вне контейнера)
|
## Шаг 4 — Запуск тестов (на хосте, вне контейнера)
|
||||||
|
|
@ -116,7 +119,8 @@ ls build/target-debug/tests/target/
|
||||||
just host::hil-run
|
just host::hil-run
|
||||||
```
|
```
|
||||||
|
|
||||||
pytest обходит все `test_*.py` в `tools/hil/`, **исключая** помеченные `@pytest.mark.interactive`.
|
pytest обходит все `test_*.py` в `tools/hil/`, **исключая** помеченные `@pytest.mark.interactive` и
|
||||||
|
`@pytest.mark.usb_vcom`.
|
||||||
Каждый файл — своя загрузка ELF, свой UART-сеанс, MCU перезагружается между файлами.
|
Каждый файл — своя загрузка ELF, свой UART-сеанс, MCU перезагружается между файлами.
|
||||||
|
|
||||||
### Интерактивные HIL-тесты (требуют оператора)
|
### Интерактивные HIL-тесты (требуют оператора)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue