_testutils.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. """
  2. Generic test utilities.
  3. """
  4. from __future__ import division, print_function, absolute_import
  5. import os
  6. import re
  7. import sys
  8. __all__ = ['PytestTester', 'check_free_memory']
  9. class FPUModeChangeWarning(RuntimeWarning):
  10. """Warning about FPU mode change"""
  11. pass
  12. class PytestTester(object):
  13. """
  14. Pytest test runner entry point.
  15. """
  16. def __init__(self, module_name):
  17. self.module_name = module_name
  18. def __call__(self, label="fast", verbose=1, extra_argv=None, doctests=False,
  19. coverage=False, tests=None):
  20. import pytest
  21. module = sys.modules[self.module_name]
  22. module_path = os.path.abspath(module.__path__[0])
  23. pytest_args = ['-l']
  24. if doctests:
  25. raise ValueError("Doctests not supported")
  26. if extra_argv:
  27. pytest_args += list(extra_argv)
  28. if verbose and int(verbose) > 1:
  29. pytest_args += ["-" + "v"*(int(verbose)-1)]
  30. if coverage:
  31. pytest_args += ["--cov=" + module_path]
  32. if label == "fast":
  33. pytest_args += ["-m", "not slow"]
  34. elif label != "full":
  35. pytest_args += ["-m", label]
  36. if tests is None:
  37. tests = [self.module_name]
  38. pytest_args += ['--pyargs'] + list(tests)
  39. try:
  40. code = pytest.main(pytest_args)
  41. except SystemExit as exc:
  42. code = exc.code
  43. return (code == 0)
  44. def check_free_memory(free_mb):
  45. """
  46. Check *free_mb* of memory is available, otherwise do pytest.skip
  47. """
  48. import pytest
  49. try:
  50. mem_free = _parse_size(os.environ['SCIPY_AVAILABLE_MEM'])
  51. msg = '{0} MB memory required, but environment SCIPY_AVAILABLE_MEM={1}'.format(
  52. free_mb, os.environ['SCIPY_AVAILABLE_MEM'])
  53. except KeyError:
  54. mem_free = _get_mem_available()
  55. if mem_free is None:
  56. pytest.skip("Could not determine available memory; set SCIPY_AVAILABLE_MEM "
  57. "variable to free memory in MB to run the test.")
  58. msg = '{0} MB memory required, but {1} MB available'.format(
  59. free_mb, mem_free/1e6)
  60. if mem_free < free_mb * 1e6:
  61. pytest.skip(msg)
  62. def _parse_size(size_str):
  63. suffixes = {'': 1e6,
  64. 'b': 1.0,
  65. 'k': 1e3, 'M': 1e6, 'G': 1e9, 'T': 1e12,
  66. 'kb': 1e3, 'Mb': 1e6, 'Gb': 1e9, 'Tb': 1e12,
  67. 'kib': 1024.0, 'Mib': 1024.0**2, 'Gib': 1024.0**3, 'Tib': 1024.0**4}
  68. m = re.match(r'^\s*(\d+)\s*({0})\s*$'.format('|'.join(suffixes.keys())),
  69. size_str,
  70. re.I)
  71. if not m or m.group(2) not in suffixes:
  72. raise ValueError("Invalid size string")
  73. return float(m.group(1)) * suffixes[m.group(2)]
  74. def _get_mem_available():
  75. """
  76. Get information about memory available, not counting swap.
  77. """
  78. try:
  79. import psutil
  80. return psutil.virtual_memory().available
  81. except (ImportError, AttributeError):
  82. pass
  83. if sys.platform.startswith('linux'):
  84. info = {}
  85. with open('/proc/meminfo', 'r') as f:
  86. for line in f:
  87. p = line.split()
  88. info[p[0].strip(':').lower()] = float(p[1]) * 1e3
  89. if 'memavailable' in info:
  90. # Linux >= 3.14
  91. return info['memavailable']
  92. else:
  93. return info['memfree'] + info['cached']
  94. return None