LSSTApplications  20.0.0
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

 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 521 of file tests.py.

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

◆ 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 678 of file tests.py.

678 def assertFloatsEqual(testCase, lhs, rhs, **kwargs):
679  """
680  Assert that lhs == rhs (both numeric types, whether scalar or array).
681 
682  See `~lsst.utils.tests.assertFloatsAlmostEqual` (called with
683  ``rtol=atol=0``) for more information.
684 
685  Parameters
686  ----------
687  testCase : `unittest.TestCase`
688  Instance the test is part of.
689  lhs : scalar or array-like
690  LHS value(s) to compare; may be a scalar or array-like of any
691  dimension.
692  rhs : scalar or array-like
693  RHS value(s) to compare; may be a scalar or array-like of any
694  dimension.
695 
696  Raises
697  ------
698  AssertionError
699  The values are not equal.
700  """
701  return assertFloatsAlmostEqual(testCase, lhs, rhs, rtol=0, atol=0, **kwargs)
702 
703 

◆ 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 651 of file tests.py.

651 def assertFloatsNotEqual(testCase, lhs, rhs, **kwds):
652  """Fail a test if the given floating point values are equal to within the
653  given tolerances.
654 
655  See `~lsst.utils.tests.assertFloatsAlmostEqual` (called with
656  ``rtol=atol=0``) for more information.
657 
658  Parameters
659  ----------
660  testCase : `unittest.TestCase`
661  Instance the test is part of.
662  lhs : scalar or array-like
663  LHS value(s) to compare; may be a scalar or array-like of any
664  dimension.
665  rhs : scalar or array-like
666  RHS value(s) to compare; may be a scalar or array-like of any
667  dimension.
668 
669  Raises
670  ------
671  AssertionError
672  The values are almost equal.
673  """
674  return assertFloatsAlmostEqual(testCase, lhs, rhs, invert=True, **kwds)
675 
676 
677 @inTestCase

◆ 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.

Examples
--------
::

    @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 736 of file tests.py.

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

◆ 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 422 of file tests.py.

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

◆ 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 309 of file tests.py.

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

◆ init()

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

Definition at line 58 of file tests.py.

58 def init():
59  """Initialize the memory tester and file descriptor leak tester."""
60  global open_files
61  # Reset the list of open files
62  open_files = _get_open_files()
63 
64 

◆ 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 414 of file tests.py.

414 def inTestCase(func):
415  """A decorator to add a free function to our custom TestCase class, while also
416  making it available as a free function.
417  """
418  setattr(TestCase, func.__name__, func)
419  return func
420 
421 

◆ 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.

Examples
--------
::

    @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 780 of file tests.py.

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

◆ 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 456 of file tests.py.

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

◆ 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 65 of file tests.py.

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

◆ suiteClassWrapper()

def lsst.utils.tests.suiteClassWrapper (   tests)

Definition at line 108 of file tests.py.

108 def suiteClassWrapper(tests):
109  return unittest.TestSuite(sort_tests(tests))
110 
111 
112 # Replace the suiteClass callable in the defaultTestLoader
113 # so that we can reorder the test ordering. This will have
114 # no effect if no memory test cases are found.
115 unittest.defaultTestLoader.suiteClass = suiteClassWrapper
116 
117 

Variable Documentation

◆ open_files

lsst.utils.tests.open_files

Definition at line 43 of file tests.py.

lsst::utils.tests.methodParameters
def methodParameters(**settings)
Definition: tests.py:780
pex.config.history.format
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
lsst::utils.tests.assertFloatsAlmostEqual
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:521
lsst::geom::all
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.
Definition: CoordinateExpr.h:81
lsst::utils.tests.debugger
def debugger(*exceptions)
Definition: tests.py:422
lsst::utils.tests.plotImageDiff
def plotImageDiff(lhs, rhs, bad=None, diff=None, plotFileName=None)
Definition: tests.py:456
lsst::utils.tests.suiteClassWrapper
def suiteClassWrapper(tests)
Definition: tests.py:108
lsst::utils.tests.assertFloatsNotEqual
def assertFloatsNotEqual(testCase, lhs, rhs, **kwds)
Definition: tests.py:651
lsst::utils.tests.assertFloatsEqual
def assertFloatsEqual(testCase, lhs, rhs, **kwargs)
Definition: tests.py:678
lsst::utils.tests.inTestCase
def inTestCase(func)
Definition: tests.py:414
type
table::Key< int > type
Definition: Detector.cc:163
lsst::utils.tests.getTempFilePath
def getTempFilePath(ext, expectOutput=True)
Definition: tests.py:309
lsst::utils.tests.classParameters
def classParameters(**settings)
Definition: tests.py:736
lsst::utils.tests.init
def init()
Definition: tests.py:58
lsst::utils.tests.sort_tests
def sort_tests(tests)
Definition: tests.py:65