conftest.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import contextlib
  2. import gc
  3. import os
  4. import pytest
  5. import random
  6. from openpilot.common.prefix import OpenpilotPrefix
  7. from openpilot.system.manager import manager
  8. from openpilot.system.hardware import TICI, HARDWARE
  9. def pytest_sessionstart(session):
  10. # TODO: fix tests and enable test order randomization
  11. if session.config.pluginmanager.hasplugin('randomly'):
  12. session.config.option.randomly_reorganize = False
  13. @pytest.hookimpl(hookwrapper=True, trylast=True)
  14. def pytest_runtest_call(item):
  15. # ensure we run as a hook after capturemanager's
  16. if item.get_closest_marker("nocapture") is not None:
  17. capmanager = item.config.pluginmanager.getplugin("capturemanager")
  18. with capmanager.global_and_fixture_disabled():
  19. yield
  20. else:
  21. yield
  22. @contextlib.contextmanager
  23. def clean_env():
  24. starting_env = dict(os.environ)
  25. yield
  26. os.environ.clear()
  27. os.environ.update(starting_env)
  28. @pytest.fixture(scope="function", autouse=True)
  29. def openpilot_function_fixture(request):
  30. random.seed(0)
  31. with clean_env():
  32. # setup a clean environment for each test
  33. with OpenpilotPrefix(shared_download_cache=request.node.get_closest_marker("shared_download_cache") is not None) as prefix:
  34. prefix = os.environ["OPENPILOT_PREFIX"]
  35. yield
  36. # ensure the test doesn't change the prefix
  37. assert "OPENPILOT_PREFIX" in os.environ and prefix == os.environ["OPENPILOT_PREFIX"]
  38. # cleanup any started processes
  39. manager.manager_cleanup()
  40. # some processes disable gc for performance, re-enable here
  41. if not gc.isenabled():
  42. gc.enable()
  43. gc.collect()
  44. # If you use setUpClass, the environment variables won't be cleared properly,
  45. # so we need to hook both the function and class pytest fixtures
  46. @pytest.fixture(scope="class", autouse=True)
  47. def openpilot_class_fixture():
  48. with clean_env():
  49. yield
  50. @pytest.fixture(scope="function")
  51. def tici_setup_fixture(openpilot_function_fixture):
  52. """Ensure a consistent state for tests on-device. Needs the openpilot function fixture to run first."""
  53. HARDWARE.initialize_hardware()
  54. HARDWARE.set_power_save(False)
  55. os.system("pkill -9 -f athena")
  56. @pytest.hookimpl(tryfirst=True)
  57. def pytest_collection_modifyitems(config, items):
  58. skipper = pytest.mark.skip(reason="Skipping tici test on PC")
  59. for item in items:
  60. if "tici" in item.keywords:
  61. if not TICI:
  62. item.add_marker(skipper)
  63. else:
  64. item.fixturenames.append('tici_setup_fixture')
  65. if "xdist_group_class_property" in item.keywords:
  66. class_property_name = item.get_closest_marker('xdist_group_class_property').args[0]
  67. class_property_value = getattr(item.cls, class_property_name)
  68. item.add_marker(pytest.mark.xdist_group(class_property_value))
  69. @pytest.hookimpl(trylast=True)
  70. def pytest_configure(config):
  71. config_line = "xdist_group_class_property: group tests by a property of the class that contains them"
  72. config.addinivalue_line("markers", config_line)
  73. config_line = "nocapture: don't capture test output"
  74. config.addinivalue_line("markers", config_line)
  75. config_line = "shared_download_cache: share download cache between tests"
  76. config.addinivalue_line("markers", config_line)