diff options
author | Picca Frédéric-Emmanuel <picca@debian.org> | 2018-03-04 10:20:27 +0100 |
---|---|---|
committer | Picca Frédéric-Emmanuel <picca@debian.org> | 2018-03-04 10:20:27 +0100 |
commit | 270d5ddc31c26b62379e3caa9044dd75ccc71847 (patch) | |
tree | 55c5bfc851dfce7172d335cd2405b214323e3caf /silx/test | |
parent | e19c96eff0c310c06c4f268c8b80cb33bd08996f (diff) |
New upstream version 0.7.0+dfsg
Diffstat (limited to 'silx/test')
-rw-r--r-- | silx/test/__init__.py | 4 | ||||
-rw-r--r-- | silx/test/test_resources.py | 15 | ||||
-rw-r--r-- | silx/test/test_sx.py | 121 | ||||
-rw-r--r-- | silx/test/utils.py | 243 |
4 files changed, 189 insertions, 194 deletions
diff --git a/silx/test/__init__.py b/silx/test/__init__.py index 0a85fe2..5175601 100644 --- a/silx/test/__init__.py +++ b/silx/test/__init__.py @@ -26,13 +26,13 @@ It is possible to disable tests depending on Qt by setting -:envvar:`WITH_QT_TEST` environment variable to 'False'. +`silx.test.utils.test_options.WITH_QT_TEST = False` It will skip all tests from :mod:`silx.test.gui`. """ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "22/06/2017" +__date__ = "09/11/2017" import logging diff --git a/silx/test/test_resources.py b/silx/test/test_resources.py index eaf65c1..66ac24f 100644 --- a/silx/test/test_resources.py +++ b/silx/test/test_resources.py @@ -26,7 +26,7 @@ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "06/09/2017" +__date__ = "17/01/2018" import os @@ -217,19 +217,6 @@ class TestExternalResources(unittest.TestCase): shutil.rmtree(self.utilstest.data_home) self.utilstest = None - def test_tempdir(self): - "test the temporary directory creation" - d = self.utilstest.tempdir - self.assertTrue(os.path.isdir(d)) - self.assertEqual(d, self.utilstest.tempdir, 'tmpdir is stable') - self.utilstest.clean_up() - self.assertFalse(os.path.isdir(d)) - e = self.utilstest.tempdir - self.assertTrue(os.path.isdir(e)) - self.assertEqual(e, self.utilstest.tempdir, 'tmpdir is stable') - self.assertNotEqual(d, e, "tempdir changed") - self.utilstest.clean_up() - def test_download(self): "test the download from silx.org" f = self.utilstest.getfile("lena.png") diff --git a/silx/test/test_sx.py b/silx/test/test_sx.py index 0de3b35..f0da32d 100644 --- a/silx/test/test_sx.py +++ b/silx/test/test_sx.py @@ -1,7 +1,7 @@ # coding: utf-8 # /*########################################################################## # -# Copyright (c) 2016-2017 European Synchrotron Radiation Facility +# Copyright (c) 2016-2018 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -24,16 +24,17 @@ # ###########################################################################*/ __authors__ = ["T. Vincent", "P. Knobel"] __license__ = "MIT" -__date__ = "05/12/2016" +__date__ = "27/02/2018" import logging import os import sys import unittest - import numpy +from silx.test.utils import test_options + _logger = logging.getLogger(__name__) @@ -52,15 +53,14 @@ if sys.platform.startswith('linux') and not os.environ.get('DISPLAY', ''): suite.addTest(SkipSXTest()) return suite -elif os.environ.get('WITH_QT_TEST', 'True') == 'False': +elif not test_options.WITH_QT_TEST: # Explicitly disabled tests - _logger.warning( - "silx.sx tests disabled (env. variable WITH_QT_TEST=False)") + msg = "silx.sx tests disabled %s" % test_options.WITH_QT_TEST_REASON + _logger.warning(msg) class SkipSXTest(unittest.TestCase): def runTest(self): - self.skipTest( - "silx.sx tests disabled (env. variable WITH_QT_TEST=False)") + self.skipTest(test_options.WITH_QT_TEST_REASON) def suite(): suite = unittest.TestSuite() @@ -73,6 +73,7 @@ else: from silx.gui import qt # load TestCaseQt before sx from silx.gui.test.utils import TestCaseQt + from silx.gui.plot.Colors import rgba from silx import sx class SXTest(TestCaseQt): @@ -163,6 +164,110 @@ else: title='origin=(10, 10), scale=(2, 2)') self._expose_and_close(plt) + def test_ginput(self): + """Test ginput function + + This does NOT perform interactive tests + """ + + plt = sx.plot() + self.qWaitForWindowExposed(plt) + self.qapp.processEvents() + + result = sx.ginput(1, timeout=0.1) + self.assertEqual(len(result), 0) + + plt.setAttribute(qt.Qt.WA_DeleteOnClose) + plt.close() + + @unittest.skipUnless(test_options.WITH_GL_TEST, + test_options.WITH_GL_TEST_REASON) + def test_contour3d(self): + """Test contour3d function""" + coords = numpy.linspace(-10, 10, 64) + z = coords.reshape(-1, 1, 1) + y = coords.reshape(1, -1, 1) + x = coords.reshape(1, 1, -1) + data = numpy.sin(x * y * z) / (x * y * z) + + # Just data + window = sx.contour3d(data) + + isosurfaces = window.getIsosurfaces() + self.assertEqual(len(isosurfaces), 1) + + self._expose_and_close(window) + if not window.getPlot3DWidget().isValid(): + self.skipTest("OpenGL context is not valid") + + # N contours + color + colors = ['red', 'green', 'blue'] + window = sx.contour3d(data, copy=False, contours=len(colors), + color=colors) + + isosurfaces = window.getIsosurfaces() + self.assertEqual(len(isosurfaces), len(colors)) + for iso, color in zip(isosurfaces, colors): + self.assertEqual(rgba(iso.getColor()), rgba(color)) + + self._expose_and_close(window) + + # by isolevel, single color + contours = 0.2, 0.5 + window = sx.contour3d(data, copy=False, contours=contours, + color='yellow') + + isosurfaces = window.getIsosurfaces() + self.assertEqual(len(isosurfaces), len(contours)) + for iso, level in zip(isosurfaces, contours): + self.assertEqual(iso.getLevel(), level) + self.assertEqual(rgba(iso.getColor()), + rgba('yellow')) + + self._expose_and_close(window) + + # Single isolevel, colormap + window = sx.contour3d(data, copy=False, contours=0.5, + colormap='gray', vmin=0.6, opacity=0.4) + + isosurfaces = window.getIsosurfaces() + self.assertEqual(len(isosurfaces), 1) + self.assertEqual(isosurfaces[0].getLevel(), 0.5) + self.assertEqual(rgba(isosurfaces[0].getColor()), + (0., 0., 0., 0.4)) + + self._expose_and_close(window) + + @unittest.skipUnless(test_options.WITH_GL_TEST, + test_options.WITH_GL_TEST_REASON) + def test_points3d(self): + """Test points3d function""" + x = numpy.random.random(1024) + y = numpy.random.random(1024) + z = numpy.random.random(1024) + values = numpy.random.random(1024) + + # 3D positions, no value + window = sx.points3d(x, y, z) + + self._expose_and_close(window) + if not window.getSceneWidget().isValid(): + self.skipTest("OpenGL context is not valid") + + # 3D positions, values + window = sx.points3d(x, y, z, values, mode='2dsquare', + colormap='magma', vmin=0.4, vmax=0.5) + self._expose_and_close(window) + + # 2D positions, no value + window = sx.points3d(x, y) + self._expose_and_close(window) + + # 2D positions, values + window = sx.points3d(x, y, values=values, mode=',', + colormap='magma', vmin=0.4, vmax=0.5) + self._expose_and_close(window) + def suite(): test_suite = unittest.TestSuite() test_suite.addTest( diff --git a/silx/test/utils.py b/silx/test/utils.py index 44eb899..bac415b 100644 --- a/silx/test/utils.py +++ b/silx/test/utils.py @@ -24,31 +24,23 @@ # ###########################################################################*/ """Utilities for writing tests. -- :class:`ParametricTestCase` provides a :meth:`TestCase.subTest` replacement - for Python < 3.4 -- :class:`TestLogging` with context or the :func:`test_logging` decorator - enables testing the number of logging messages of different levels. - :func:`temp_dir` provides a with context to create/delete a temporary directory. """ __authors__ = ["T. Vincent"] __license__ = "MIT" -__date__ = "03/08/2017" +__date__ = "17/01/2018" -import os +import sys import contextlib -import functools -import logging +import os import numpy import shutil -import sys import tempfile -import unittest from ..resources import ExternalResources -_logger = logging.getLogger(__name__) utilstest = ExternalResources(project="silx", url_base="http://www.silx.org/pub/silx/", @@ -56,174 +48,85 @@ utilstest = ExternalResources(project="silx", timeout=60) "This is the instance to be used. Singleton-like feature provided by module" -# Parametric Test Base Class ################################################## - -if sys.hexversion >= 0x030400F0: # Python >= 3.4 - class ParametricTestCase(unittest.TestCase): - pass -else: - class ParametricTestCase(unittest.TestCase): - """TestCase with subTest support for Python < 3.4. +class _TestOptions(object): - Add subTest method to support parametric tests. - API is the same, but behavior differs: - If a subTest fails, the following ones are not run. - """ + def __init__(self): + self.WITH_QT_TEST = True + """Qt tests are included""" - _subtest_msg = None # Class attribute to provide a default value - - @contextlib.contextmanager - def subTest(self, msg=None, **params): - """Use as unittest.TestCase.subTest method in Python >= 3.4.""" - # Format arguments as: '[msg] (key=value, ...)' - param_str = ', '.join(['%s=%s' % (k, v) for k, v in params.items()]) - self._subtest_msg = '[%s] (%s)' % (msg or '', param_str) - yield - self._subtest_msg = None - - def shortDescription(self): - short_desc = super(ParametricTestCase, self).shortDescription() - if self._subtest_msg is not None: - # Append subTest message to shortDescription - short_desc = ' '.join( - [msg for msg in (short_desc, self._subtest_msg) if msg]) - - return short_desc if short_desc else None - - -# Test logging messages ####################################################### - -class TestLogging(logging.Handler): - """Context checking the number of logging messages from a specified Logger. - - It disables propagation of logging message while running. - - This is meant to be used as a with statement, for example: - - >>> with TestLogging(logger, error=2, warning=0): - >>> pass # Run tests here expecting 2 ERROR and no WARNING from logger - ... - - :param logger: Name or instance of the logger to test. - (Default: root logger) - :type logger: str or :class:`logging.Logger` - :param int critical: Expected number of CRITICAL messages. - Default: Do not check. - :param int error: Expected number of ERROR messages. - Default: Do not check. - :param int warning: Expected number of WARNING messages. - Default: Do not check. - :param int info: Expected number of INFO messages. - Default: Do not check. - :param int debug: Expected number of DEBUG messages. - Default: Do not check. - :param int notset: Expected number of NOTSET messages. - Default: Do not check. - :raises RuntimeError: If the message counts are the expected ones. - """ + self.WITH_QT_TEST_REASON = "" + """Reason for Qt tests are disabled if any""" - def __init__(self, logger=None, critical=None, error=None, - warning=None, info=None, debug=None, notset=None): - if logger is None: - logger = logging.getLogger() - elif not isinstance(logger, logging.Logger): - logger = logging.getLogger(logger) - self.logger = logger - - self.records = [] - - self.count_by_level = { - logging.CRITICAL: critical, - logging.ERROR: error, - logging.WARNING: warning, - logging.INFO: info, - logging.DEBUG: debug, - logging.NOTSET: notset - } - - super(TestLogging, self).__init__() - - def __enter__(self): - """Context (i.e., with) support""" - self.records = [] # Reset recorded LogRecords - self.logger.addHandler(self) - self.logger.propagate = False - # ensure no log message is ignored - self.entry_level = self.logger.level * 1 - self.logger.setLevel(logging.DEBUG) - - def __exit__(self, exc_type, exc_value, traceback): - """Context (i.e., with) support""" - self.logger.removeHandler(self) - self.logger.propagate = True - self.logger.setLevel(self.entry_level) - - for level, expected_count in self.count_by_level.items(): - if expected_count is None: - continue - - # Number of records for the specified level_str - count = len([r for r in self.records if r.levelno == level]) - if count != expected_count: # That's an error - # Resend record logs through logger as they where masked - # to help debug - for record in self.records: - self.logger.handle(record) - raise RuntimeError( - 'Expected %d %s logging messages, got %d' % ( - expected_count, logging.getLevelName(level), count)) - - def emit(self, record): - """Override :meth:`logging.Handler.emit`""" - self.records.append(record) - - -def test_logging(logger=None, critical=None, error=None, - warning=None, info=None, debug=None, notset=None): - """Decorator checking number of logging messages. - - Propagation of logging messages is disabled by this decorator. - - In case the expected number of logging messages is not found, it raises - a RuntimeError. - - >>> class Test(unittest.TestCase): - ... @test_logging('module_logger_name', error=2, warning=0) - ... def test(self): - ... pass # Test expecting 2 ERROR and 0 WARNING messages - - :param logger: Name or instance of the logger to test. - (Default: root logger) - :type logger: str or :class:`logging.Logger` - :param int critical: Expected number of CRITICAL messages. - Default: Do not check. - :param int error: Expected number of ERROR messages. - Default: Do not check. - :param int warning: Expected number of WARNING messages. - Default: Do not check. - :param int info: Expected number of INFO messages. - Default: Do not check. - :param int debug: Expected number of DEBUG messages. - Default: Do not check. - :param int notset: Expected number of NOTSET messages. - Default: Do not check. - """ - def decorator(func): - test_context = TestLogging(logger, critical, error, - warning, info, debug, notset) + self.WITH_OPENCL_TEST = True + """OpenCL tests are included""" - @functools.wraps(func) - def wrapper(*args, **kwargs): - with test_context: - result = func(*args, **kwargs) - return result - return wrapper - return decorator + self.WITH_GL_TEST = True + """OpenGL tests are included""" + self.WITH_GL_TEST_REASON = "" + """Reason for OpenGL tests are disabled if any""" + self.TEST_LOW_MEM = False + """Skip tests using too much memory""" + def configure(self, parsed_options): + """Configure the TestOptions class from the command line arguments and the + environment variables + """ + if not parsed_options.gui: + self.WITH_QT_TEST = False + self.WITH_QT_TEST_REASON = "Skipped by command line" + elif os.environ.get('WITH_QT_TEST', 'True') == 'False': + self.WITH_QT_TEST = False + self.WITH_QT_TEST_REASON = "Skipped by WITH_QT_TEST env var" + elif sys.platform.startswith('linux') and not os.environ.get('DISPLAY', ''): + self.WITH_QT_TEST = False + self.WITH_QT_TEST_REASON = "DISPLAY env variable not set" + + if not parsed_options.opencl or os.environ.get('SILX_OPENCL', 'True') == 'False': + self.WITH_OPENCL_TEST = False + # That's an easy way to skip OpenCL tests + # It disable the use of OpenCL on the full silx project + os.environ['SILX_OPENCL'] = "False" + + if not parsed_options.opengl: + self.WITH_GL_TEST = False + self.WITH_GL_TEST_REASON = "Skipped by command line" + elif os.environ.get('WITH_GL_TEST', 'True') == 'False': + self.WITH_GL_TEST = False + self.WITH_GL_TEST_REASON = "Skipped by WITH_GL_TEST env var" + + if parsed_options.low_mem or os.environ.get('SILX_TEST_LOW_MEM', 'True') == 'False': + self.TEST_LOW_MEM = True + + if self.WITH_QT_TEST: + from silx.gui import qt + if sys.platform == "win32" and qt.qVersion() == "5.9.2": + self.SKIP_TEST_FOR_ISSUE_936 = True + + def add_parser_argument(self, parser): + """Add extrat arguments to the test argument parser + + :param ArgumentParser parser: An argument parser + """ + parser.add_argument("-x", "--no-gui", dest="gui", default=True, + action="store_false", + help="Disable the test of the graphical use interface") + parser.add_argument("-g", "--no-opengl", dest="opengl", default=True, + action="store_false", + help="Disable tests using OpenGL") + parser.add_argument("-o", "--no-opencl", dest="opencl", default=True, + action="store_false", + help="Disable the test of the OpenCL part") + parser.add_argument("-l", "--low-mem", dest="low_mem", default=False, + action="store_true", + help="Disable test with large memory consumption (>100Mbyte") + + +test_options = _TestOptions() +"""Singleton providing configuration information for all the tests""" # Temporary directory context ################################################# |