/test/individual_coverage.py

https://github.com/mitmproxy/mitmproxy
Python | 84 lines | 67 code | 15 blank | 2 comment | 24 complexity | a478dd4c10564a7c8b4e44c6d58726b6 MD5 | raw file
  1. #!/usr/bin/env python3
  2. import io
  3. import contextlib
  4. import os
  5. import sys
  6. import glob
  7. import multiprocessing
  8. import configparser
  9. import itertools
  10. import pytest
  11. def run_tests(src, test, fail):
  12. stderr = io.StringIO()
  13. stdout = io.StringIO()
  14. with contextlib.redirect_stderr(stderr):
  15. with contextlib.redirect_stdout(stdout):
  16. e = pytest.main([
  17. '-qq',
  18. '--disable-pytest-warnings',
  19. '--cov', src.replace('.py', '').replace('/', '.'),
  20. '--cov-fail-under', '100',
  21. '--cov-report', 'term-missing:skip-covered',
  22. '-o', 'faulthandler_timeout=0',
  23. test
  24. ])
  25. if e == 0:
  26. if fail:
  27. print("FAIL DUE TO UNEXPECTED SUCCESS:", src, "Please remove this file from setup.cfg tool:individual_coverage/exclude.")
  28. e = 42
  29. else:
  30. print(".")
  31. else:
  32. if fail:
  33. print("Ignoring allowed fail:", src)
  34. e = 0
  35. else:
  36. cov = [l for l in stdout.getvalue().split("\n") if (src in l) or ("was never imported" in l)]
  37. if len(cov) == 1:
  38. print("FAIL:", cov[0])
  39. else:
  40. print("FAIL:", src, test, stdout.getvalue(), stdout.getvalue())
  41. print(stderr.getvalue())
  42. print(stdout.getvalue())
  43. sys.exit(e)
  44. def start_pytest(src, test, fail):
  45. # run pytest in a new process, otherwise imports and modules might conflict
  46. proc = multiprocessing.Process(target=run_tests, args=(src, test, fail))
  47. proc.start()
  48. proc.join()
  49. return (src, test, proc.exitcode)
  50. def main():
  51. c = configparser.ConfigParser()
  52. c.read('setup.cfg')
  53. fs = c['tool:individual_coverage']['exclude'].strip().split('\n')
  54. no_individual_cov = [f.strip() for f in fs]
  55. excluded = ['mitmproxy/contrib/', 'mitmproxy/test/', 'mitmproxy/tools/', 'mitmproxy/platform/']
  56. src_files = glob.glob('mitmproxy/**/*.py', recursive=True)
  57. src_files = [f for f in src_files if os.path.basename(f) != '__init__.py']
  58. src_files = [f for f in src_files if not any(os.path.normpath(p) in f for p in excluded)]
  59. ps = []
  60. for src in sorted(src_files):
  61. test = os.path.join("test", os.path.dirname(src), "test_" + os.path.basename(src))
  62. if os.path.isfile(test):
  63. ps.append((src, test, src in no_individual_cov))
  64. result = list(itertools.starmap(start_pytest, ps))
  65. if any(e != 0 for _, _, e in result):
  66. sys.exit(1)
  67. pass
  68. if __name__ == '__main__':
  69. main()