1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
#
# CamiTK python module test directly from python (outside the CamiTK python interpreter)
#
# To test manually:
# - cd build
# - PYTEST_SRC=../sdk/libraries/python/testing; PYTEST_VENV=sdk/libraries/python/testing/.venv;
# - get the output of pytest_discover_tests:
# ${PYTEST_VENV}/bin/python ${PYTEST_SRC}/pytest_discover_tests.py ${PYTEST_SRC}/camitk_python_test.py
# - to run a test called test_foo (name in ptest) / camitk-python-test-foo (name in ctest)
# - directly in pytest:
# PYTHONPATH=lib ${PYTEST_VENV}/bin/python -m pytest -vv ${PYTEST_SRC}/camitk_python_test.py -k test_foo
# (note PYTHONPATH is required so that the CamiTK python module can be found when "import camitk" is called)
# - from ctest:
# ctest -VV -R camitk-python-test-foo
#
import pytest
import re
import sys
if sys.platform == "win32":
# Preload camitkcore DLL on windows (this is required for python to be able to import camitk.pyd)
# This is required when the camitk python module is loaded (using "import camitk")
# outside the embedded python interpreter
import ctypes
import os
dll_dir = os.environ['PYTHONPATH'] # assume python path contains both camitkcore DLL and camitk python pyd file
assert os.path.exists(dll_dir), f"Pythonpath does not exist: {dll_dir}"
dll_path = dll_dir + r"\camitkcore.dll"
if not os.path.exists(dll_path):
dll_path = dll_dir + r"\camitkcore-debug.dll"
assert os.path.exists(dll_path), f"Cannot find camitkcore (Debug nor Release): {dll_path} in {dll_dir}"
ctypes.CDLL(dll_path, winmode=0)
import camitk
def test_debug_info():
camitk.startApplication()
debug_info = camitk.getDebugInfo()
print(debug_info)
pattern = 'Python version: ([0-9.]+)\\n'
matches = re.findall(pattern, debug_info)
assert len(matches) == 1, f"Cannot find any python version in\n{debug_info}"
version = matches[0]
current_version = ".".join(map(str, sys.version_info[0:3]))
assert version == current_version
python_intrepreter_version = camitk.getPythonVersion()
assert python_intrepreter_version == '' # as the CamiTK interpreter is not initialized
def test_import_numpy():
import traceback
print("Trying to import numpy...")
try:
import numpy
assert numpy.__version__ != ""
except ImportError as e:
print("Error importing numpy:", e)
traceback.print_exc()
pytest.fail("Error importing numpy:")
def test_get_date():
from datetime import datetime
assert datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') != ""
def test_numpy_random_numbers():
import numpy as np
assert len(np.random.rand(10).tolist()) == 10
def test_file_output(tmp_path):
# see https://docs.pytest.org/en/stable/how-to/tmp_path.html
from datetime import datetime
import numpy as np
written_string = "test_file_output on " + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') + ' ' + str(np.random.rand(10).tolist())
d = tmp_path / "camitk_python_test"
d.mkdir()
p = d / "test.txt"
p.write_text(written_string, encoding="utf-8")
assert p.read_text(encoding="utf-8") == written_string
assert len(list(tmp_path.iterdir())) == 1
### CAMITK BINDING
def test_print(capsys):
# see https://docs.pytest.org/en/stable/how-to/capture-stdout-stderr.html
camitk.startApplication()
print("Open components: " + str(len(camitk.Application.getTopLevelComponents())))
captured = capsys.readouterr()
assert "Open components: 0" in captured.out
def test_action():
camitk.startApplication()
# get a known action
action = camitk.Application.getAction("Resample")
assert str(type(action)) == "<class 'camitk.Action'>"
assert action.getName() == "Resample"
# test parameter values
assert action.getParameterValue("New Image X Dimension") == 256
action.setParameterValue("New Image X Dimension", -1)
assert action.getParameterValue("New Image X Dimension") == -1
# test camitk property
prop = action.getProperty("New Image X Dimension")
assert prop.getName() == "New Image X Dimension"
assert prop.getDescription() == "The new image width (in voxels)."
assert prop.getUnit() == ""
assert prop.getReadOnly() == False
assert prop.getAttribute("minimum") == 1
assert prop.getAttribute("maximum") == 2**31 - 1 # set as std::numeric_limits<int>::max() in the Resample action constructor
assert prop.getAttribute("singleStep") == 1
prop.setAttribute("minimum", -42)
assert prop.getAttribute("minimum") == -42
prop.setAttribute("maximum", 0)
assert prop.getAttribute("maximum") == 0
prop.setAttribute("singleStep", 5)
assert prop.getAttribute("singleStep") == 5
prop.setReadOnly(True)
assert prop.getReadOnly() == True
# Remove open component test for now
# Testing the CamiTK python module from outside the inner interpreter is not necessarily a good idea
# def test_application_open():
# camitk.startApplication()
# assert len(camitk.Application.getTopLevelComponents()) == 0
# # camitk.Application.open(camitk.Core.get_test_data_dir() + "/brain.mha")
# camitk.Application.open(camitk.Core.getTestDataDir() + "/amos_0336.camitk")
# # print("Number of top-level components:", len(camitk.Application.getTopLevelComponents()))
# assert len(camitk.Application.getTopLevelComponents()) == 16
# assert camitk.Application.getTopLevelComponents()[0].getName() == "amos_0336"
# def test_imagecomponent():
# import numpy
# camitk.startApplication()
# camitk.Application.open(camitk.Core.getTestDataDir() + "/FullHead.mhd")
# image = camitk.Application.getTopLevelComponents()[0]
# image_data = image.getImageDataAsNumpy()
# assert image_data.shape == (94, 256, 256) # as numpy is z-first
# print(image.getSpacing())
# spacing = image.getSpacing()
# expected = numpy.array([0.9375, 0.9375, 1.5], dtype='f')
# assert numpy.all(expected == spacing)
|