hil: make the usbtest-cell tests actually run

The file was bare module-level pytest functions with no entry point, and nothing
in this repo invokes pytest - so `python3 test_hil_usbtest_cell.py` exited 0
having run nothing, and the guard on the skip-accounting fix could never fail.
Converted to unittest with a __main__ block, matching its two siblings.

A pre-commit hook now runs every test/hil/test_*.py directly. Not via pytest:
hil_test.py matches pytest's default discovery glob, so `pytest test/hil/`
collects 26 hardware cases and errors on all of them. Verified the hook gates -
reintroducing the passed+failed total makes it exit non-zero.
This commit is contained in:
hathach
2026-08-15 10:54:51 +07:00
parent 17858fa183
commit 657621c554
2 changed files with 46 additions and 29 deletions

View File

@ -48,6 +48,16 @@ repos:
types_or: [c, header]
language: system
# The HIL harness's hardware-free unit tests. Each is run directly rather than through pytest:
# nothing else in the repo invokes pytest, and `pytest test/hil/` would collect hil_test.py's
# hardware cases (they match pytest's default glob) and error on every one.
- id: hil-unit-test
name: HIL harness unit tests
files: ^test/hil/
entry: sh -c 'for t in test/hil/test_*.py; do python3 "$t" || exit 1; done'
pass_filenames: false
language: system
# - id: build-fuzzer
# name: build-fuzzer
# files: ^(src/|test/fuzz/)

View File

@ -1,38 +1,45 @@
"""The usbtest report cell must never render a quirk-skipped run as a full pass."""
#!/usr/bin/env python3
"""The usbtest report cell must never render a quirk-skipped run as a full pass.
unittest (not bare pytest functions) so `python3 test_hil_usbtest_cell.py` actually runs the
assertions: nothing in CI invokes pytest, and `pytest test/hil/` is not a substitute either -
hil_test.py matches pytest's default discovery glob and drags 26 hardware tests into collection.
"""
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
import hil_test
def test_full_pass_renders_as_pass():
data = {'passed': 30, 'failed': 0, 'skipped': 0, 'cases': []}
assert hil_test.usbtest_cell(data) == '✅ 30/30'
class TestUsbtestCell(unittest.TestCase):
def test_full_pass_renders_as_pass(self):
data = {'passed': 30, 'failed': 0, 'skipped': 0, 'cases': []}
self.assertEqual(hil_test.usbtest_cell(data), '✅ 30/30')
def test_skipped_cases_are_counted_in_the_denominator(self):
"""25 ran and passed, 5 were quirk-skipped: the cell must not read 25/25."""
data = {'passed': 25, 'failed': 0, 'skipped': 5,
'cases': [{'num': n, 'status': 'SKIP'} for n in (9, 10, 13, 14, 21)]}
cell = hil_test.usbtest_cell(data)
self.assertIn('25/30', cell)
self.assertIn('5 skipped', cell)
self.assertNotIn('25/25', cell)
def test_skipped_cases_are_not_reported_as_failures(self):
data = {'passed': 24, 'failed': 1, 'skipped': 5,
'cases': [{'num': n, 'status': 'SKIP'} for n in (9, 10, 13, 14, 21)]
+ [{'num': 7, 'status': 'FAIL'}]}
with self.assertRaises(hil_test.TestFail) as cm:
hil_test.usbtest_cell(data)
self.assertIn('cases failed: [7]', str(cm.exception))
def test_missing_skipped_key_defaults_to_zero(self):
"""Output from a usbtest.py predating the skipped key must still render."""
self.assertEqual(hil_test.usbtest_cell({'passed': 30, 'failed': 0, 'cases': []}),
'✅ 30/30')
def test_skipped_cases_are_counted_in_the_denominator():
# 25 ran and passed, 5 were quirk-skipped: the cell must not read 25/25
data = {'passed': 25, 'failed': 0, 'skipped': 5,
'cases': [{'num': n, 'status': 'SKIP'} for n in (9, 10, 13, 14, 21)]}
cell = hil_test.usbtest_cell(data)
assert '25/30' in cell
assert '5 skipped' in cell
assert '25/25' not in cell
def test_skipped_cases_are_not_reported_as_failures():
data = {'passed': 24, 'failed': 1, 'skipped': 5,
'cases': [{'num': n, 'status': 'SKIP'} for n in (9, 10, 13, 14, 21)]
+ [{'num': 7, 'status': 'FAIL'}]}
try:
hil_test.usbtest_cell(data)
except hil_test.TestFail as e:
assert 'cases failed: [7]' in str(e)
else:
raise AssertionError('expected TestFail')
def test_missing_skipped_key_defaults_to_zero():
# older usbtest.py output without the key must still render
assert hil_test.usbtest_cell({'passed': 30, 'failed': 0, 'cases': []}) == '✅ 30/30'
if __name__ == '__main__':
unittest.main(verbosity=1)