LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
Classes | Functions | Variables
lsst.utils.tests Namespace Reference

Classes

class  ExecutablesTestCase
 
class  MemoryTestCase
 
class  TestCase
 

Functions

def init ()
 
def sort_tests (tests)
 
def suiteClassWrapper (tests)
 
def getTempFilePath (ext, expectOutput=True)
 
def inTestCase (func)
 
def debugger (exceptions)
 
def plotImageDiff (lhs, rhs, bad=None, diff=None, plotFileName=None)
 
def assertFloatsAlmostEqual (testCase, lhs, rhs, rtol=sys.float_info.epsilon, atol=sys.float_info.epsilon, relTo=None, printFailures=True, plotOnFailure=False, plotFileName=None, invert=False, msg=None)
 
def assertFloatsNotEqual (testCase, lhs, rhs, kwds)
 
def assertFloatsEqual (testCase, lhs, rhs, kwargs)
 
def classParameters (settings)
 
def methodParameters (settings)
 

Variables

 psutil
 
 open_files
 

Function Documentation

◆ assertFloatsAlmostEqual()

def lsst.utils.tests.assertFloatsAlmostEqual (   testCase,
  lhs,
  rhs,
  rtol = sys.float_info.epsilon,
  atol = sys.float_info.epsilon,
  relTo = None,
  printFailures = True,
  plotOnFailure = False,
  plotFileName = None,
  invert = False,
  msg = None 
)
Highly-configurable floating point comparisons for scalars and arrays.

The test assertion will fail if all elements ``lhs`` and ``rhs`` are not
equal to within the tolerances specified by ``rtol`` and ``atol``.
More precisely, the comparison is:

``abs(lhs - rhs) <= relTo*rtol OR abs(lhs - rhs) <= atol``

If ``rtol`` or ``atol`` is `None`, that term in the comparison is not
performed at all.

When not specified, ``relTo`` is the elementwise maximum of the absolute
values of ``lhs`` and ``rhs``.  If set manually, it should usually be set
to either ``lhs`` or ``rhs``, or a scalar value typical of what is
expected.

Parameters
----------
testCase : `unittest.TestCase`
    Instance the test is part of.
lhs : scalar or array-like
    LHS value(s) to compare; may be a scalar or array-like of any
    dimension.
rhs : scalar or array-like
    RHS value(s) to compare; may be a scalar or array-like of any
    dimension.
rtol : `float`, optional
    Relative tolerance for comparison; defaults to double-precision
    epsilon.
atol : `float`, optional
    Absolute tolerance for comparison; defaults to double-precision
    epsilon.
relTo : `float`, optional
    Value to which comparison with rtol is relative.
printFailures : `bool`, optional
    Upon failure, print all inequal elements as part of the message.
plotOnFailure : `bool`, optional
    Upon failure, plot the originals and their residual with matplotlib.
    Only 2-d arrays are supported.
plotFileName : `str`, optional
    Filename to save the plot to.  If `None`, the plot will be displayed in
    a window.
invert : `bool`, optional
    If `True`, invert the comparison and fail only if any elements *are*
    equal. Used to implement `~lsst.utils.tests.assertFloatsNotEqual`,
    which should generally be used instead for clarity.
msg : `str`, optional
    String to append to the error message when assert fails.

Raises
------
AssertionError
    The values are not almost equal.

Definition at line 533 of file tests.py.

533  plotFileName=None, invert=False, msg=None):
534  """Highly-configurable floating point comparisons for scalars and arrays.
535 
536  The test assertion will fail if all elements ``lhs`` and ``rhs`` are not
537  equal to within the tolerances specified by ``rtol`` and ``atol``.
538  More precisely, the comparison is:
539 
540  ``abs(lhs - rhs) <= relTo*rtol OR abs(lhs - rhs) <= atol``
541 
542  If ``rtol`` or ``atol`` is `None`, that term in the comparison is not
543  performed at all.
544 
545  When not specified, ``relTo`` is the elementwise maximum of the absolute
546  values of ``lhs`` and ``rhs``. If set manually, it should usually be set
547  to either ``lhs`` or ``rhs``, or a scalar value typical of what is
548  expected.
549 
550  Parameters
551  ----------
552  testCase : `unittest.TestCase`
553  Instance the test is part of.
554  lhs : scalar or array-like
555  LHS value(s) to compare; may be a scalar or array-like of any
556  dimension.
557  rhs : scalar or array-like
558  RHS value(s) to compare; may be a scalar or array-like of any
559  dimension.
560  rtol : `float`, optional
561  Relative tolerance for comparison; defaults to double-precision
562  epsilon.
563  atol : `float`, optional
564  Absolute tolerance for comparison; defaults to double-precision
565  epsilon.
566  relTo : `float`, optional
567  Value to which comparison with rtol is relative.
568  printFailures : `bool`, optional
569  Upon failure, print all inequal elements as part of the message.
570  plotOnFailure : `bool`, optional
571  Upon failure, plot the originals and their residual with matplotlib.
572  Only 2-d arrays are supported.
573  plotFileName : `str`, optional
574  Filename to save the plot to. If `None`, the plot will be displayed in
575  a window.
576  invert : `bool`, optional
577  If `True`, invert the comparison and fail only if any elements *are*
578  equal. Used to implement `~lsst.utils.tests.assertFloatsNotEqual`,
579  which should generally be used instead for clarity.
580  msg : `str`, optional
581  String to append to the error message when assert fails.
582 
583  Raises
584  ------
585  AssertionError
586  The values are not almost equal.
587  """
588  if not numpy.isfinite(lhs).all():
589  testCase.fail("Non-finite values in lhs")
590  if not numpy.isfinite(rhs).all():
591  testCase.fail("Non-finite values in rhs")
592  diff = lhs - rhs
593  absDiff = numpy.abs(lhs - rhs)
594  if rtol is not None:
595  if relTo is None:
596  relTo = numpy.maximum(numpy.abs(lhs), numpy.abs(rhs))
597  else:
598  relTo = numpy.abs(relTo)
599  bad = absDiff > rtol*relTo
600  if atol is not None:
601  bad = numpy.logical_and(bad, absDiff > atol)
602  else:
603  if atol is None:
604  raise ValueError("rtol and atol cannot both be None")
605  bad = absDiff > atol
606  failed = numpy.any(bad)
607  if invert:
608  failed = not failed
609  bad = numpy.logical_not(bad)
610  cmpStr = "=="
611  failStr = "are the same"
612  else:
613  cmpStr = "!="
614  failStr = "differ"
615  errMsg = []
616  if failed:
617  if numpy.isscalar(bad):
618  if rtol is None:
619  errMsg = ["%s %s %s; diff=%s with atol=%s"
620  % (lhs, cmpStr, rhs, absDiff, atol)]
621  elif atol is None:
622  errMsg = ["%s %s %s; diff=%s/%s=%s with rtol=%s"
623  % (lhs, cmpStr, rhs, absDiff, relTo, absDiff/relTo, rtol)]
624  else:
625  errMsg = ["%s %s %s; diff=%s/%s=%s with rtol=%s, atol=%s"
626  % (lhs, cmpStr, rhs, absDiff, relTo, absDiff/relTo, rtol, atol)]
627  else:
628  errMsg = ["%d/%d elements %s with rtol=%s, atol=%s"
629  % (bad.sum(), bad.size, failStr, rtol, atol)]
630  if plotOnFailure:
631  if len(lhs.shape) != 2 or len(rhs.shape) != 2:
632  raise ValueError("plotOnFailure is only valid for 2-d arrays")
633  try:
634  plotImageDiff(lhs, rhs, bad, diff=diff, plotFileName=plotFileName)
635  except ImportError:
636  errMsg.append("Failure plot requested but matplotlib could not be imported.")
637  if printFailures:
638  # Make sure everything is an array if any of them are, so we can treat
639  # them the same (diff and absDiff are arrays if either rhs or lhs is),
640  # and we don't get here if neither is.
641  if numpy.isscalar(relTo):
642  relTo = numpy.ones(bad.shape, dtype=float) * relTo
643  if numpy.isscalar(lhs):
644  lhs = numpy.ones(bad.shape, dtype=float) * lhs
645  if numpy.isscalar(rhs):
646  rhs = numpy.ones(bad.shape, dtype=float) * rhs
647  if rtol is None:
648  for a, b, diff in zip(lhs[bad], rhs[bad], absDiff[bad]):
649  errMsg.append("%s %s %s (diff=%s)" % (a, cmpStr, b, diff))
650  else:
651  for a, b, diff, rel in zip(lhs[bad], rhs[bad], absDiff[bad], relTo[bad]):
652  errMsg.append("%s %s %s (diff=%s/%s=%s)" % (a, cmpStr, b, diff, rel, diff/rel))
653 
654  if msg is not None:
655  errMsg.append(msg)
656  testCase.assertFalse(failed, msg="\n".join(errMsg))
657 
658 
659 @inTestCase
def plotImageDiff(lhs, rhs, bad=None, diff=None, plotFileName=None)
Definition: tests.py:465
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.

◆ assertFloatsEqual()

def lsst.utils.tests.assertFloatsEqual (   testCase,
  lhs,
  rhs,
  kwargs 
)
Assert that lhs == rhs (both numeric types, whether scalar or array).

See `~lsst.utils.tests.assertFloatsAlmostEqual` (called with
``rtol=atol=0``) for more information.

Parameters
----------
testCase : `unittest.TestCase`
    Instance the test is part of.
lhs : scalar or array-like
    LHS value(s) to compare; may be a scalar or array-like of any
    dimension.
rhs : scalar or array-like
    RHS value(s) to compare; may be a scalar or array-like of any
    dimension.

Raises
------
AssertionError
    The values are not equal.

Definition at line 687 of file tests.py.

687 def assertFloatsEqual(testCase, lhs, rhs, **kwargs):
688  """
689  Assert that lhs == rhs (both numeric types, whether scalar or array).
690 
691  See `~lsst.utils.tests.assertFloatsAlmostEqual` (called with
692  ``rtol=atol=0``) for more information.
693 
694  Parameters
695  ----------
696  testCase : `unittest.TestCase`
697  Instance the test is part of.
698  lhs : scalar or array-like
699  LHS value(s) to compare; may be a scalar or array-like of any
700  dimension.
701  rhs : scalar or array-like
702  RHS value(s) to compare; may be a scalar or array-like of any
703  dimension.
704 
705  Raises
706  ------
707  AssertionError
708  The values are not equal.
709  """
710  return assertFloatsAlmostEqual(testCase, lhs, rhs, rtol=0, atol=0, **kwargs)
711 
712 
def assertFloatsEqual(testCase, lhs, rhs, kwargs)
Definition: tests.py:687
def assertFloatsAlmostEqual(testCase, lhs, rhs, rtol=sys.float_info.epsilon, atol=sys.float_info.epsilon, relTo=None, printFailures=True, plotOnFailure=False, plotFileName=None, invert=False, msg=None)
Definition: tests.py:533

◆ assertFloatsNotEqual()

def lsst.utils.tests.assertFloatsNotEqual (   testCase,
  lhs,
  rhs,
  kwds 
)
Fail a test if the given floating point values are equal to within the
given tolerances.

See `~lsst.utils.tests.assertFloatsAlmostEqual` (called with
``rtol=atol=0``) for more information.

Parameters
----------
testCase : `unittest.TestCase`
    Instance the test is part of.
lhs : scalar or array-like
    LHS value(s) to compare; may be a scalar or array-like of any
    dimension.
rhs : scalar or array-like
    RHS value(s) to compare; may be a scalar or array-like of any
    dimension.

Raises
------
AssertionError
    The values are almost equal.

Definition at line 660 of file tests.py.

660 def assertFloatsNotEqual(testCase, lhs, rhs, **kwds):
661  """Fail a test if the given floating point values are equal to within the
662  given tolerances.
663 
664  See `~lsst.utils.tests.assertFloatsAlmostEqual` (called with
665  ``rtol=atol=0``) for more information.
666 
667  Parameters
668  ----------
669  testCase : `unittest.TestCase`
670  Instance the test is part of.
671  lhs : scalar or array-like
672  LHS value(s) to compare; may be a scalar or array-like of any
673  dimension.
674  rhs : scalar or array-like
675  RHS value(s) to compare; may be a scalar or array-like of any
676  dimension.
677 
678  Raises
679  ------
680  AssertionError
681  The values are almost equal.
682  """
683  return assertFloatsAlmostEqual(testCase, lhs, rhs, invert=True, **kwds)
684 
685 
686 @inTestCase
def assertFloatsAlmostEqual(testCase, lhs, rhs, rtol=sys.float_info.epsilon, atol=sys.float_info.epsilon, relTo=None, printFailures=True, plotOnFailure=False, plotFileName=None, invert=False, msg=None)
Definition: tests.py:533
def assertFloatsNotEqual(testCase, lhs, rhs, kwds)
Definition: tests.py:660

◆ classParameters()

def lsst.utils.tests.classParameters (   settings)
Class decorator for generating unit tests

This decorator generates classes with class variables according to the
supplied ``settings``.

Parameters
----------
**settings : `dict` (`str`: iterable)
    The lists of test parameters to set as class variables in turn. Each
    should be an iterable of the same length.

Example
-------

    @classParameters(foo=[1, 2], bar=[3, 4])
    class MyTestCase(unittest.TestCase):
        ...

will generate two classes, as if you wrote:

    class MyTestCase_1_3(unittest.TestCase):
        foo = 1
        bar = 3
        ...

    class MyTestCase_2_4(unittest.TestCase):
        foo = 2
        bar = 4
        ...

Note that the values are embedded in the class name.

Definition at line 745 of file tests.py.

745 def classParameters(**settings):
746  """Class decorator for generating unit tests
747 
748  This decorator generates classes with class variables according to the
749  supplied ``settings``.
750 
751  Parameters
752  ----------
753  **settings : `dict` (`str`: iterable)
754  The lists of test parameters to set as class variables in turn. Each
755  should be an iterable of the same length.
756 
757  Example
758  -------
759 
760  @classParameters(foo=[1, 2], bar=[3, 4])
761  class MyTestCase(unittest.TestCase):
762  ...
763 
764  will generate two classes, as if you wrote:
765 
766  class MyTestCase_1_3(unittest.TestCase):
767  foo = 1
768  bar = 3
769  ...
770 
771  class MyTestCase_2_4(unittest.TestCase):
772  foo = 2
773  bar = 4
774  ...
775 
776  Note that the values are embedded in the class name.
777  """
778  def decorator(cls):
779  module = sys.modules[cls.__module__].__dict__
780  for params in _settingsIterator(settings):
781  name = f"{cls.__name__}_{'_'.join(str(vv) for vv in params.values())}"
782  bindings = dict(cls.__dict__)
783  bindings.update(params)
784  module[name] = type(name, (cls,), bindings)
785  return decorator
786 
787 
def classParameters(settings)
Definition: tests.py:745
table::Key< int > type
Definition: Detector.cc:163

◆ debugger()

def lsst.utils.tests.debugger (   exceptions)
Decorator to enter the debugger when there's an uncaught exception

To use, just slap a ``@debugger()`` on your function.

You may provide specific exception classes to catch as arguments to
the decorator function, e.g.,
``@debugger(RuntimeError, NotImplementedError)``.
This defaults to just `AssertionError`, for use on `unittest.TestCase`
methods.

Code provided by "Rosh Oxymoron" on StackOverflow:
http://stackoverflow.com/questions/4398967/python-unit-testing-automatically-running-the-debugger-when-a-test-fails

Notes
-----
Consider using ``pytest --pdb`` instead of this decorator.

Definition at line 431 of file tests.py.

431 def debugger(*exceptions):
432  """Decorator to enter the debugger when there's an uncaught exception
433 
434  To use, just slap a ``@debugger()`` on your function.
435 
436  You may provide specific exception classes to catch as arguments to
437  the decorator function, e.g.,
438  ``@debugger(RuntimeError, NotImplementedError)``.
439  This defaults to just `AssertionError`, for use on `unittest.TestCase`
440  methods.
441 
442  Code provided by "Rosh Oxymoron" on StackOverflow:
443  http://stackoverflow.com/questions/4398967/python-unit-testing-automatically-running-the-debugger-when-a-test-fails
444 
445  Notes
446  -----
447  Consider using ``pytest --pdb`` instead of this decorator.
448  """
449  if not exceptions:
450  exceptions = (Exception, )
451 
452  def decorator(f):
453  @functools.wraps(f)
454  def wrapper(*args, **kwargs):
455  try:
456  return f(*args, **kwargs)
457  except exceptions:
458  import sys
459  import pdb
460  pdb.post_mortem(sys.exc_info()[2])
461  return wrapper
462  return decorator
463 
464 
def debugger(exceptions)
Definition: tests.py:431

◆ getTempFilePath()

def lsst.utils.tests.getTempFilePath (   ext,
  expectOutput = True 
)
Return a path suitable for a temporary file and try to delete the
file on success

If the with block completes successfully then the file is deleted,
if possible; failure results in a printed warning.
If a file is remains when it should not, a RuntimeError exception is
raised. This exception is also raised if a file is not present on context
manager exit when one is expected to exist.
If the block exits with an exception the file if left on disk so it can be
examined. The file name has a random component such that nested context
managers can be used with the same file suffix.

Parameters
----------

ext : `str`
    File name extension, e.g. ``.fits``.
expectOutput : `bool`, optional
    If `True`, a file should be created within the context manager.
    If `False`, a file should not be present when the context manager
    exits.

Returns
-------
`str`
    Path for a temporary file. The path is a combination of the caller's
    file path and the name of the top-level function

Notes
-----
::

    # file tests/testFoo.py
    import unittest
    import lsst.utils.tests
    class FooTestCase(unittest.TestCase):
        def testBasics(self):
            self.runTest()

        def runTest(self):
            with lsst.utils.tests.getTempFilePath(".fits") as tmpFile:
                # if tests/.tests exists then
                # tmpFile = "tests/.tests/testFoo_testBasics.fits"
                # otherwise tmpFile = "testFoo_testBasics.fits"
                ...
                # at the end of this "with" block the path tmpFile will be
                # deleted, but only if the file exists and the "with"
                # block terminated normally (rather than with an exception)
    ...

Definition at line 318 of file tests.py.

318 def getTempFilePath(ext, expectOutput=True):
319  """Return a path suitable for a temporary file and try to delete the
320  file on success
321 
322  If the with block completes successfully then the file is deleted,
323  if possible; failure results in a printed warning.
324  If a file is remains when it should not, a RuntimeError exception is
325  raised. This exception is also raised if a file is not present on context
326  manager exit when one is expected to exist.
327  If the block exits with an exception the file if left on disk so it can be
328  examined. The file name has a random component such that nested context
329  managers can be used with the same file suffix.
330 
331  Parameters
332  ----------
333 
334  ext : `str`
335  File name extension, e.g. ``.fits``.
336  expectOutput : `bool`, optional
337  If `True`, a file should be created within the context manager.
338  If `False`, a file should not be present when the context manager
339  exits.
340 
341  Returns
342  -------
343  `str`
344  Path for a temporary file. The path is a combination of the caller's
345  file path and the name of the top-level function
346 
347  Notes
348  -----
349  ::
350 
351  # file tests/testFoo.py
352  import unittest
353  import lsst.utils.tests
354  class FooTestCase(unittest.TestCase):
355  def testBasics(self):
356  self.runTest()
357 
358  def runTest(self):
359  with lsst.utils.tests.getTempFilePath(".fits") as tmpFile:
360  # if tests/.tests exists then
361  # tmpFile = "tests/.tests/testFoo_testBasics.fits"
362  # otherwise tmpFile = "testFoo_testBasics.fits"
363  ...
364  # at the end of this "with" block the path tmpFile will be
365  # deleted, but only if the file exists and the "with"
366  # block terminated normally (rather than with an exception)
367  ...
368  """
369  stack = inspect.stack()
370  # get name of first function in the file
371  for i in range(2, len(stack)):
372  frameInfo = inspect.getframeinfo(stack[i][0])
373  if i == 2:
374  callerFilePath = frameInfo.filename
375  callerFuncName = frameInfo.function
376  elif callerFilePath == frameInfo.filename:
377  # this function called the previous function
378  callerFuncName = frameInfo.function
379  else:
380  break
381 
382  callerDir, callerFileNameWithExt = os.path.split(callerFilePath)
383  callerFileName = os.path.splitext(callerFileNameWithExt)[0]
384  outDir = os.path.join(callerDir, ".tests")
385  if not os.path.isdir(outDir):
386  outDir = ""
387  prefix = "%s_%s-" % (callerFileName, callerFuncName)
388  outPath = tempfile.mktemp(dir=outDir, suffix=ext, prefix=prefix)
389  if os.path.exists(outPath):
390  # There should not be a file there given the randomizer. Warn and remove.
391  # Use stacklevel 3 so that the warning is reported from the end of the with block
392  warnings.warn("Unexpectedly found pre-existing tempfile named %r" % (outPath,),
393  stacklevel=3)
394  try:
395  os.remove(outPath)
396  except OSError:
397  pass
398 
399  yield outPath
400 
401  fileExists = os.path.exists(outPath)
402  if expectOutput:
403  if not fileExists:
404  raise RuntimeError("Temp file expected named {} but none found".format(outPath))
405  else:
406  if fileExists:
407  raise RuntimeError("Unexpectedly discovered temp file named {}".format(outPath))
408  # Try to clean up the file regardless
409  if fileExists:
410  try:
411  os.remove(outPath)
412  except OSError as e:
413  # Use stacklevel 3 so that the warning is reported from the end of the with block
414  warnings.warn("Warning: could not remove file %r: %s" % (outPath, e), stacklevel=3)
415 
416 
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
def getTempFilePath(ext, expectOutput=True)
Definition: tests.py:318

◆ init()

def lsst.utils.tests.init ( )
Initialize the memory tester and file descriptor leak tester.

Definition at line 65 of file tests.py.

65 def init():
66  """Initialize the memory tester and file descriptor leak tester."""
67  global open_files
68  # Reset the list of open files
69  open_files = _get_open_files()
70 
71 
def init()
Definition: tests.py:65

◆ inTestCase()

def lsst.utils.tests.inTestCase (   func)
A decorator to add a free function to our custom TestCase class, while also
making it available as a free function.

Definition at line 423 of file tests.py.

423 def inTestCase(func):
424  """A decorator to add a free function to our custom TestCase class, while also
425  making it available as a free function.
426  """
427  setattr(TestCase, func.__name__, func)
428  return func
429 
430 
def inTestCase(func)
Definition: tests.py:423

◆ methodParameters()

def lsst.utils.tests.methodParameters (   settings)
Method decorator for unit tests

This decorator iterates over the supplied settings, using
``TestCase.subTest`` to communicate the values in the event of a failure.

Parameters
----------
**settings : `dict` (`str`: iterable)
    The lists of test parameters. Each should be an iterable of the same
    length.

Example
-------

    @methodParameters(foo=[1, 2], bar=[3, 4])
    def testSomething(self, foo, bar):
        ...

will run:

    testSomething(foo=1, bar=3)
    testSomething(foo=2, bar=4)

Definition at line 788 of file tests.py.

788 def methodParameters(**settings):
789  """Method decorator for unit tests
790 
791  This decorator iterates over the supplied settings, using
792  ``TestCase.subTest`` to communicate the values in the event of a failure.
793 
794  Parameters
795  ----------
796  **settings : `dict` (`str`: iterable)
797  The lists of test parameters. Each should be an iterable of the same
798  length.
799 
800  Example
801  -------
802 
803  @methodParameters(foo=[1, 2], bar=[3, 4])
804  def testSomething(self, foo, bar):
805  ...
806 
807  will run:
808 
809  testSomething(foo=1, bar=3)
810  testSomething(foo=2, bar=4)
811  """
812  def decorator(func):
813  @functools.wraps(func)
814  def wrapper(self, *args, **kwargs):
815  for params in _settingsIterator(settings):
816  kwargs.update(params)
817  with self.subTest(**params):
818  func(self, *args, **kwargs)
819  return wrapper
820  return decorator
821 
def methodParameters(settings)
Definition: tests.py:788

◆ plotImageDiff()

def lsst.utils.tests.plotImageDiff (   lhs,
  rhs,
  bad = None,
  diff = None,
  plotFileName = None 
)
Plot the comparison of two 2-d NumPy arrays.

Parameters
----------
lhs : `numpy.ndarray`
    LHS values to compare; a 2-d NumPy array
rhs : `numpy.ndarray`
    RHS values to compare; a 2-d NumPy array
bad : `numpy.ndarray`
    A 2-d boolean NumPy array of values to emphasize in the plots
diff : `numpy.ndarray`
    difference array; a 2-d NumPy array, or None to show lhs-rhs
plotFileName : `str`
    Filename to save the plot to.  If None, the plot will be displayed in
    a window.

Notes
-----
This method uses `matplotlib` and imports it internally; it should be
wrapped in a try/except block within packages that do not depend on
`matplotlib` (including `~lsst.utils`).

Definition at line 465 of file tests.py.

465 def plotImageDiff(lhs, rhs, bad=None, diff=None, plotFileName=None):
466  """Plot the comparison of two 2-d NumPy arrays.
467 
468  Parameters
469  ----------
470  lhs : `numpy.ndarray`
471  LHS values to compare; a 2-d NumPy array
472  rhs : `numpy.ndarray`
473  RHS values to compare; a 2-d NumPy array
474  bad : `numpy.ndarray`
475  A 2-d boolean NumPy array of values to emphasize in the plots
476  diff : `numpy.ndarray`
477  difference array; a 2-d NumPy array, or None to show lhs-rhs
478  plotFileName : `str`
479  Filename to save the plot to. If None, the plot will be displayed in
480  a window.
481 
482  Notes
483  -----
484  This method uses `matplotlib` and imports it internally; it should be
485  wrapped in a try/except block within packages that do not depend on
486  `matplotlib` (including `~lsst.utils`).
487  """
488  from matplotlib import pyplot
489  if diff is None:
490  diff = lhs - rhs
491  pyplot.figure()
492  if bad is not None:
493  # make an rgba image that's red and transparent where not bad
494  badImage = numpy.zeros(bad.shape + (4,), dtype=numpy.uint8)
495  badImage[:, :, 0] = 255
496  badImage[:, :, 1] = 0
497  badImage[:, :, 2] = 0
498  badImage[:, :, 3] = 255*bad
499  vmin1 = numpy.minimum(numpy.min(lhs), numpy.min(rhs))
500  vmax1 = numpy.maximum(numpy.max(lhs), numpy.max(rhs))
501  vmin2 = numpy.min(diff)
502  vmax2 = numpy.max(diff)
503  for n, (image, title) in enumerate([(lhs, "lhs"), (rhs, "rhs"), (diff, "diff")]):
504  pyplot.subplot(2, 3, n + 1)
505  im1 = pyplot.imshow(image, cmap=pyplot.cm.gray, interpolation='nearest', origin='lower',
506  vmin=vmin1, vmax=vmax1)
507  if bad is not None:
508  pyplot.imshow(badImage, alpha=0.2, interpolation='nearest', origin='lower')
509  pyplot.axis("off")
510  pyplot.title(title)
511  pyplot.subplot(2, 3, n + 4)
512  im2 = pyplot.imshow(image, cmap=pyplot.cm.gray, interpolation='nearest', origin='lower',
513  vmin=vmin2, vmax=vmax2)
514  if bad is not None:
515  pyplot.imshow(badImage, alpha=0.2, interpolation='nearest', origin='lower')
516  pyplot.axis("off")
517  pyplot.title(title)
518  pyplot.subplots_adjust(left=0.05, bottom=0.05, top=0.92, right=0.75, wspace=0.05, hspace=0.05)
519  cax1 = pyplot.axes([0.8, 0.55, 0.05, 0.4])
520  pyplot.colorbar(im1, cax=cax1)
521  cax2 = pyplot.axes([0.8, 0.05, 0.05, 0.4])
522  pyplot.colorbar(im2, cax=cax2)
523  if plotFileName:
524  pyplot.savefig(plotFileName)
525  else:
526  pyplot.show()
527 
528 
529 @inTestCase
def plotImageDiff(lhs, rhs, bad=None, diff=None, plotFileName=None)
Definition: tests.py:465

◆ sort_tests()

def lsst.utils.tests.sort_tests (   tests)
Sort supplied test suites such that MemoryTestCases are at the end.

`lsst.utils.tests.MemoryTestCase` tests should always run after any other
tests in the module.

Parameters
----------
tests : sequence
    Sequence of test suites.

Returns
-------
suite : `unittest.TestSuite`
    A combined `~unittest.TestSuite` with
    `~lsst.utils.tests.MemoryTestCase` at the end.

Definition at line 72 of file tests.py.

72 def sort_tests(tests):
73  """Sort supplied test suites such that MemoryTestCases are at the end.
74 
75  `lsst.utils.tests.MemoryTestCase` tests should always run after any other
76  tests in the module.
77 
78  Parameters
79  ----------
80  tests : sequence
81  Sequence of test suites.
82 
83  Returns
84  -------
85  suite : `unittest.TestSuite`
86  A combined `~unittest.TestSuite` with
87  `~lsst.utils.tests.MemoryTestCase` at the end.
88  """
89 
90  suite = unittest.TestSuite()
91  memtests = []
92  for test_suite in tests:
93  try:
94  # Just test the first test method in the suite for MemoryTestCase
95  # Use loop rather than next as it is possible for a test class
96  # to not have any test methods and the Python community prefers
97  # for loops over catching a StopIteration exception.
98  bases = None
99  for method in test_suite:
100  bases = inspect.getmro(method.__class__)
101  break
102  if bases is not None and MemoryTestCase in bases:
103  memtests.append(test_suite)
104  else:
105  suite.addTests(test_suite)
106  except TypeError:
107  if isinstance(test_suite, MemoryTestCase):
108  memtests.append(test_suite)
109  else:
110  suite.addTest(test_suite)
111  suite.addTests(memtests)
112  return suite
113 
114 
def sort_tests(tests)
Definition: tests.py:72

◆ suiteClassWrapper()

def lsst.utils.tests.suiteClassWrapper (   tests)

Definition at line 115 of file tests.py.

115 def suiteClassWrapper(tests):
116  return unittest.TestSuite(sort_tests(tests))
117 
118 
119 # Replace the suiteClass callable in the defaultTestLoader
120 # so that we can reorder the test ordering. This will have
121 # no effect if no memory test cases are found.
122 unittest.defaultTestLoader.suiteClass = suiteClassWrapper
123 
124 
def suiteClassWrapper(tests)
Definition: tests.py:115
def sort_tests(tests)
Definition: tests.py:72

Variable Documentation

◆ open_files

lsst.utils.tests.open_files

Definition at line 48 of file tests.py.

◆ psutil

lsst.utils.tests.psutil

Definition at line 45 of file tests.py.