From 5177edc0ac1767d738f6dc80ab4350c7cc5fd477 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Thu, 1 Jun 2023 19:03:25 -0600 Subject: [PATCH 1/3] Fixup unit test The unit test appears to have fallen out of sync with the code long ago (e.g. it seems to previously expect the values from `get_sRGB` to range from 0-255). I did my best to restore it, but at this point I'm not 100% sure why the colormaps only match approximately after applying these fixes. --- .github/workflows/test.yml | 35 ++++++ .travis.yml | 20 --- Makefile | 11 ++ environment.yml | 4 + tests.py => test/test_editor_loads_native.py | 123 +++++++++++-------- 5 files changed, 121 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml rename tests.py => test/test_editor_loads_native.py (56%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..131562e --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,35 @@ +name: "Unit test" +on: + - "push" + - "pull_request" + +jobs: + + unit-test-with-pytest: + runs-on: "ubuntu-latest" + strategy: + matrix: + python-version: + - "3.11" + - "3.10" + - "3.9" + - "3.8" + pyqt-dependency: + - "PyQt5" + # - "PyQt6" + + steps: + - uses: "actions/checkout@v3" + + - name: "Set up Python ${{ matrix.python-version }}" + uses: "actions/setup-python@v4" + with: + python-version: "${{ matrix.python-version }}" + + - name: "Install dependencies in pyproject.toml" + run: | + pip install . + pip install pytest pytest-cov ${{ matrix.pyqt-dependency }} + + - name: "Run tests" + run: "make test" diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index df3b66d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: python -python: - - "2.7" - - "3.4" - - "3.5" -addon: - apt: - packages: - - python-qt4 - -before_install: - - pip install --no-index --trusted-host travis-wheels.scikit-image.org --find-links=http://travis-wheels.scikit-image.org numpy scipy matplotlib PySide - - pip install colorspacious - - pip install pytest pytest-cov - - python $(dirname $(which python))/pyside_postinstall.py -install - - sh -e /etc/init.d/xvfb start - - export DISPLAY=:99 -script: - - "py.test tests.py" -sudo: false \ No newline at end of file diff --git a/Makefile b/Makefile index 3ea713f..77aaa6c 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,14 @@ +.PHONY: test +test: + python -m pytest --version + python -m pytest test/ + + .PHONY: lint lint: + pre-commit --version pre-commit run --all-files --show-diff-on-failure --color always + + +.PHONY: ci +ci: lint test diff --git a/environment.yml b/environment.yml index 21689cc..e198e5d 100644 --- a/environment.yml +++ b/environment.yml @@ -12,6 +12,10 @@ dependencies: # Development - "pre-commit" + - "pytest" + - "pytest-cov" + - "pytest-qt" + - "pytest-xvfb" - pip: - "build ~=0.10" diff --git a/tests.py b/test/test_editor_loads_native.py similarity index 56% rename from tests.py rename to test/test_editor_loads_native.py index ac8d37f..03e44e9 100644 --- a/tests.py +++ b/test/test_editor_loads_native.py @@ -1,57 +1,80 @@ -import numpy as np +import json + +import pytest -from viscm.bezierbuilder import json from viscm.gui import Colormap, viscm_editor -cms = { - "viscm/examples/sample_linear.jscm", - "viscm/examples/sample_diverging.jscm", - "viscm/examples/sample_diverging_continuous.jscm", -} - - -def test_editor_loads_native(): - for k in cms: - with open(k) as f: - data = json.loads(f.read()) - cm = Colormap(None, "CatmulClark", "CAM02-UCS") - cm.load(k) - viscm = viscm_editor( - uniform_space=cm.uniform_space, - cmtype=cm.cmtype, - method=cm.method, - **cm.params, - ) - assert viscm.name == data["name"] - - extensions = data["extensions"]["https://matplotlib.org/viscm"] - xp, yp, fixed = viscm.control_point_model.get_control_points() - - assert extensions["fixed"] == fixed - assert len(extensions["xp"]) == len(xp) - assert len(extensions["yp"]) == len(yp) - assert len(xp) == len(yp) - for i in range(len(xp)): - assert extensions["xp"][i] == xp[i] - assert extensions["yp"][i] == yp[i] - assert extensions["min_Jp"] == viscm.min_Jp - assert extensions["max_Jp"] == viscm.max_Jp - assert extensions["filter_k"] == viscm.filter_k - assert extensions["cmtype"] == viscm.cmtype - - colors = data["colors"] - colors = [ - [int(c[i : i + 2], 16) / 256 for i in range(0, 6, 2)] - for c in [colors[i : i + 6] for i in range(0, len(colors), 6)] - ] - editor_colors = viscm.cmap_model.get_sRGB(num=256)[0].tolist() - for i in range(len(colors)): - for z in range(3): - assert colors[i][z] == np.rint(editor_colors[i][z] / 256) + +def approxeq(x, y, *, err=0.0001): + return abs(y - x) < err + + +@pytest.mark.parametrize( + "colormap_file", + [ + "viscm/examples/sample_linear.jscm", + "viscm/examples/sample_diverging.jscm", + "viscm/examples/sample_diverging_continuous.jscm", + ], +) +def test_editor_loads_native(colormap_file): + with open(colormap_file) as f: + data = json.loads(f.read()) + cm = Colormap(None, "CatmulClark", "CAM02-UCS") + cm.load(colormap_file) + viscm = viscm_editor( + uniform_space=cm.uniform_space, + cmtype=cm.cmtype, + method=cm.method, + **cm.params, + ) + assert viscm.name == data["name"] + + extensions = data["extensions"]["https://matplotlib.org/viscm"] + xp, yp, fixed = viscm.control_point_model.get_control_points() + + assert extensions["fixed"] == fixed + assert len(extensions["xp"]) == len(xp) + assert len(extensions["yp"]) == len(yp) + assert len(xp) == len(yp) + for i in range(len(xp)): + assert extensions["xp"][i] == xp[i] + assert extensions["yp"][i] == yp[i] + assert extensions["min_Jp"] == viscm.min_Jp + assert extensions["max_Jp"] == viscm.max_Jp + assert extensions["filter_k"] == viscm.cmap_model.filter_k + assert extensions["cmtype"] == viscm.cmtype + + # Decode hexadecimal-encoded colormap string (grouped in units of 3 pairs of + # two-character (0-255) values) to 3-tuples of floats (0-1). + colors_hex = data["colors"] + colors_hex = [colors_hex[i : i + 6] for i in range(0, len(colors_hex), 6)] + colors = [ + # TODO: Should we divide by 255 here instead of 256? The tests pass with a + # lower value for `err` if we do. + [int(c[i : i + 2], 16) / 256 for i in range(0, len(c), 2)] + for c in colors_hex + ] + + editor_colors = viscm.cmap_model.get_sRGB(num=256)[0].tolist() + + for i in range(len(colors)): + for z in range(3): + assert approxeq(colors[i][z], editor_colors[i][z], err=0.01) # import matplotlib as mpl -# from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas +# try: +# from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas +# except ImportError: +# try: +# from matplotlib.backends.backend_qt5agg import ( +# FigureCanvasQTAgg as FigureCanvas +# ) +# except ImportError: +# from matplotlib.backends.backend_qt4agg import ( +# FigureCanvasQTAgg as FigureCanvas +# ) # from matplotlib.backends.qt_compat import QtCore, QtGui # # def test_editor_add_point(): @@ -144,7 +167,3 @@ def test_editor_loads_native(): # print(linear.control_point_model.get_control_points()) # # print(linear.cmap_model.get_Jpapbp(3)) - - -def approxeq(x, y, err=0.0001): - return abs(y - x) < err From 70b4918434689b052aa6061c75281b1f12a376d6 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Fri, 2 Jun 2023 18:54:00 -0600 Subject: [PATCH 2/3] Fix hex decoding logic --- test/test_editor_loads_native.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/test_editor_loads_native.py b/test/test_editor_loads_native.py index 03e44e9..2f45ca8 100644 --- a/test/test_editor_loads_native.py +++ b/test/test_editor_loads_native.py @@ -50,10 +50,7 @@ def test_editor_loads_native(colormap_file): colors_hex = data["colors"] colors_hex = [colors_hex[i : i + 6] for i in range(0, len(colors_hex), 6)] colors = [ - # TODO: Should we divide by 255 here instead of 256? The tests pass with a - # lower value for `err` if we do. - [int(c[i : i + 2], 16) / 256 for i in range(0, len(c), 2)] - for c in colors_hex + [int(c[i : i + 2], 16) / 255 for i in range(0, len(c), 2)] for c in colors_hex ] editor_colors = viscm.cmap_model.get_sRGB(num=256)[0].tolist() From beb1a97f8b252b0a1cfdff3756b843b08b96d1e3 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Fri, 2 Jun 2023 18:54:11 -0600 Subject: [PATCH 3/3] Restore old assertion and mark xfail --- test/test_editor_loads_native.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test_editor_loads_native.py b/test/test_editor_loads_native.py index 2f45ca8..f360b04 100644 --- a/test/test_editor_loads_native.py +++ b/test/test_editor_loads_native.py @@ -1,5 +1,6 @@ import json +import numpy as np import pytest from viscm.gui import Colormap, viscm_editor @@ -17,6 +18,7 @@ def approxeq(x, y, *, err=0.0001): "viscm/examples/sample_diverging_continuous.jscm", ], ) +@pytest.mark.xfail(reason="Test very old; intent unclear") def test_editor_loads_native(colormap_file): with open(colormap_file) as f: data = json.loads(f.read()) @@ -57,7 +59,11 @@ def test_editor_loads_native(colormap_file): for i in range(len(colors)): for z in range(3): - assert approxeq(colors[i][z], editor_colors[i][z], err=0.01) + # FIXME: The right-hand side of this comparison will always be 0. + # https://github.com/matplotlib/viscm/pull/66#discussion_r1213818015 + assert colors[i][z] == np.rint(editor_colors[i][z] / 256) + # Should the test look more like this? + # assert approxeq(colors[i][z], editor_colors[i][z], err=0.005) # import matplotlib as mpl