conftest.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. """
  2. This is a specially-named file that pytest finds in order to
  3. configure testing. Most of the logic comes from
  4. https://docs.pytest.org/en/7.1.x/example/simple.html#control-skipping-of-tests-according-to-command-line-option
  5. """
  6. import pytest
  7. class CustomMarker:
  8. """
  9. Custom Markers are used to annotate tests.
  10. Tests marked with a custom marker will be skipped by default. Pass either
  11. --run-NAME_OF_MARKER or --run-NAME-OF-MARKER
  12. to override this behavior.
  13. --run-all may also be used to run all marked tests.
  14. """
  15. def __init__(self, name, desc, dest=None):
  16. self.name = name
  17. self.desc = desc
  18. self.dest = name if dest is None else dest
  19. def option_flags(self):
  20. """
  21. Return option flags for this marker.
  22. >>> marker = CustomMarker('foo_bar', 'my desc')
  23. >>> marker.option_flags()
  24. ['--run-foo_bar', '--run-foo-bar']
  25. >>> marker2 = CustomMarker('foo', 'my desc')
  26. >>> marker2.option_flags()
  27. ['--run-foo']
  28. """
  29. # NOTE: pytest is not testing the above doctest
  30. # instead, run this file directly (see doctest.testmod at bottom)
  31. result = ['--run-{}'.format(self.name)]
  32. as_hyphen = '--run-{}'.format(self.name.replace('_', '-'))
  33. if as_hyphen != result[0]:
  34. result.append(as_hyphen)
  35. return result
  36. CUSTOM_MARKERS = (
  37. CustomMarker('long',
  38. 'this test runs too long for Github Actions'),
  39. CustomMarker('uses_card',
  40. 'must have acceleration card installed to run test'),
  41. )
  42. def pytest_addoption(parser):
  43. """
  44. pytest hook - adds options to argument parser.
  45. """
  46. parser.addoption('--run-all',
  47. dest='run_all',
  48. action='store_true',
  49. help='Run all tests normally skipped by default')
  50. for marker in CUSTOM_MARKERS:
  51. parser.addoption(*marker.option_flags(),
  52. dest=marker.dest,
  53. action='store_true',
  54. help='Run tests marked with {}'.format(marker.name))
  55. def pytest_configure(config):
  56. # Adds explicit marker definitions
  57. # with these, pytest will error if `--strict` is applied and unregistered
  58. # markers are present.
  59. for marker in CUSTOM_MARKERS:
  60. config.addinivalue_line("markers",
  61. "{}: {}".format(marker.name, marker.desc))
  62. def pytest_collection_modifyitems(config, items):
  63. """
  64. pytest hook which runs after tests have been collected.
  65. """
  66. skip_marked_tests(config, items)
  67. def skip_marked_tests(config, items):
  68. """
  69. Dynamically applies pytest.mark.skip to tests with custom markers.
  70. Tests with explicit --run-FOO flags are not skipped.
  71. This keeps `pytest` from footshooting with tests that should only be run
  72. under particular conditions.
  73. """
  74. run_all = config.getoption('--run-all', default=False)
  75. run_mark = {marker.name: config.getoption(marker.dest)
  76. for marker in CUSTOM_MARKERS}
  77. for item in items:
  78. for marker_name, run_marker in run_mark.items():
  79. if marker_name in item.keywords and not (run_all or run_marker):
  80. item.add_marker(pytest.mark.skip)
  81. break