Skip to content

Commit

Permalink
Skip tests with missing requirements (#1032)
Browse files Browse the repository at this point in the history
Skip tests with missing requirements

---------

Co-authored-by: Francesca L. Bleken <[email protected]>
  • Loading branch information
jesper-friis and francescalb authored Dec 14, 2024
1 parent 9890759 commit 5df5306
Show file tree
Hide file tree
Showing 15 changed files with 88 additions and 38 deletions.
10 changes: 2 additions & 8 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,15 @@ jobs:
run: |
python3 -c 'import numpy as np; print(np.get_include())'
- name: Workaround - install CMake 3.25.2 since 3.26.0 doesn't work
# Normally we would install cmake with the package manager, but
# ubuntu 20.04 doesn't seems to keep older versions of cmake around...
# Fortunately, there exists a pip package
run: |
python3 -m pip install cmake==3.25.2
cmake --version
- name: List installed Python packages
run: |
uname -a
python --version
pip freeze
- name: Configure
env:
DLITE_IMPORTSKIP_EXITCODE: 1
run: |
Python3_ROOT=$(python3 -c 'import sys; print(sys.exec_prefix)') \
CFLAGS='-Wno-missing-field-initializers' \
Expand Down
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,13 @@ if(WITH_PYTHON)
# endif()
# message(STATUS "ENV{Python3_LIBRARY}: $ENV{Python3_LIBRARY}")

add_custom_target(wheel
COMMAND ${Python3_EXECUTABLE} -m pip wheel -w dist
${dlite_SOURCE_DIR}/python
DEPENDS ${dlite}
COMMENT "Build Python wheels"
)


message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
message(STATUS "Python3_prefix = ${Python3_prefix}")
Expand Down Expand Up @@ -942,6 +949,7 @@ configure_package_config_file(
PATH_VARS ${DLITE_CONFIG_VARS}
)


#################################################################

# Install
Expand Down
2 changes: 2 additions & 0 deletions bindings/python/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ foreach(test ${tests})
ENVIRONMENT "DLITE_USE_BUILD_ROOT=YES")

# Skip tests that exit with return code 44
set_property(TEST ${name} APPEND PROPERTY
ENVIRONMENT "DLITE_IMPORTSKIP_EXITCODE=$ENV{DLITE_IMPORTSKIP_EXITCODE}")
set_property(TEST ${name} PROPERTY SKIP_RETURN_CODE 44)

endforeach()
Expand Down
34 changes: 32 additions & 2 deletions bindings/python/testutils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Some utilities for testing."""
import importlib
import os
import socket
import sys

Expand Down Expand Up @@ -71,15 +72,44 @@ def importcheck(module_name, package=None):
return None


def importskip(module_name, package=None, exitcode=44):
def importskip(module_name, package=None, exitcode=44,
env_exitcode="DLITE_IMPORTSKIP_EXITCODE"):
"""Import and return the requested module.
Calls `sys.exit()` with given exitcode if the module cannot be imported.
Arguments:
module_name: Name of module to try to import.
package: Optional package name that the module might reside in.
exitcode: The default exit code of `sys.exit()` if the module cannot
be imported.
env_exitcode: Name of environment variable containing an exitcode
to call `sys.exit()` with if the module cannot be imported.
This overrides `exitcode`.
Notes:
If you want to run the tests and get an error if a module
cannot be imported, set environment variable
`DLITE_IMPORTSKIP_EXITCODE=1` before running the tests (if you
run with ctest, set `DLITE_IMPORTSKIP_EXITCODE` at configure
time).
For packages that depend on external services like postgresql,
call `importskip()` with `env_exitcode=None` to skip the test
regardless of whether `DLITE_IMPORTSKIP_EXITCODE` is set or not.
"""
try:
return importlib.import_module(module_name, package=package)
except ModuleNotFoundError as exc:
print(f"{exc}: skipping test", file=sys.stderr)
if env_exitcode and env_exitcode in os.environ:
try:
exitcode = int(os.environ[env_exitcode])
except:
pass
else:
print(f"{exc}: skipping test", file=sys.stderr)

sys.exit(exitcode)


Expand Down
5 changes: 5 additions & 0 deletions doc/user_guide/environment_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ DLITE_USE_BUILD_ROOT is set).
- a glob pattern (/path/to/*.json)
In the two last cases, the file extension must match the driver name.

- **DLITE_IMPORTSKIP_EXITCODE**: Exit code from tests that fail to
load a python module with `importskip()`. Define this to 1 at
configure time if you want the tests not to be skipped if they
cannot import a needed module.


Environment variables for controlling error handling
----------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ if(FORCE_EXAMPLES OR EXISTS ${CMAKE_INSTALL_PREFIX}/share/dlite/examples)
endif()
set_property(TEST ${name} APPEND PROPERTY
ENVIRONMENT "DLITE_USE_BUILD_ROOT=YES")
set_property(TEST ${name} APPEND PROPERTY
ENVIRONMENT "DLITE_IMPORTSKIP_EXITCODE=$ENV{DLITE_IMPORTSKIP_EXITCODE}")

set_property(TEST ${name} PROPERTY
SKIP_RETURN_CODE 44)
endforeach()
Expand Down
19 changes: 10 additions & 9 deletions examples/mappings/oteexample.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
"""Mapping example using OTELib."""
from pathlib import Path

try:
from tripper import EMMO, MAP, Triplestore
from otelib import OTEClient
import oteapi_dlite # To check that it is installed
except ModuleNotFoundError as exc:
print(f"Skipping OTE example because of missing module: {exc}")
import sys
sys.exit(44) # Exit code 44 -> skip test because of missing dependencies

import dlite
from dlite.testutils import importskip

importskip("tripper")
from tripper import EMMO, MAP, Triplestore

importskip("otelib", env_exitcode=None)
from otelib import OTEClient

oteapi_dlite = importskip("oteapi_dlite", env_exitcode=None)



# Paths
Expand Down
7 changes: 0 additions & 7 deletions examples/read-csv/main.py
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
try:
import pandas # noqa: F401
import tables # noqa: F401
except ImportError:
import sys
sys.exit(44) # skip this test if pandas is not available

import readcsv # noqa: F401
5 changes: 5 additions & 0 deletions examples/read-csv/readcsv.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from pathlib import Path

import dlite
from dlite.testutils import importskip

importskip("pandas")
importskip("tables")
importskip("yaml")


# Set up some paths
Expand Down
2 changes: 2 additions & 0 deletions storages/python/tests-python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ foreach(test ${python-tests})
set_property(TEST ${test} APPEND PROPERTY
ENVIRONMENT "LD_LIBRARY_PATH=${dlite_LD_LIBRARY_PATH_NATIVE}")
endif()
set_property(TEST ${name} APPEND PROPERTY
ENVIRONMENT "DLITE_IMPORTSKIP_EXITCODE=$ENV{DLITE_IMPORTSKIP_EXITCODE}")

# Skip tests that exit with return code 44
set_property(TEST ${test} PROPERTY SKIP_RETURN_CODE 44)
Expand Down
8 changes: 4 additions & 4 deletions storages/python/tests-python/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from pathlib import Path

import numpy as np

import dlite
from dlite.testutils import importskip

try:
import skimage
except ImportError:
sys.exit(44) # skip test
importskip("scipy")
importskip("skimage")


thisdir = Path(__file__).absolute().parent
Expand Down
5 changes: 5 additions & 0 deletions storages/python/tests-python/test_mongodb-atlas_python.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import sys
import os
from pathlib import Path

import dlite
from dlite.testutils import importskip

importskip("pymongo", env_exitcode=None)


# Get the current file path
current_file = Path(__file__).resolve()
Expand Down
6 changes: 4 additions & 2 deletions storages/python/tests-python/test_mongodb_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
from dlite.options import Options
from dlite.testutils import importskip

importskip("pymongo")
mongomock = importskip("mongomock")
importskip("pymongo", env_exitcode=None)
mongomock = importskip("mongomock", env_exitcode=None)

from dlite.testutils import importskip


@mongomock.patch(servers=(('localhost', 27017),))
Expand Down
10 changes: 5 additions & 5 deletions storages/python/tests-python/test_postgresql_storage_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from pathlib import Path

sys.dont_write_bytecode = True
try:
import psycopg2
except ImportError:
sys.exit(44)
from psycopg2 import sql

import dlite
from dlite.utils import instance_from_dict
from dlite.testutils import importskip

psycopg2 = importskip("psycopg2", env_exitcode=None)
from psycopg2 import sql

from run_python_storage_tests import print_test_exception


Expand Down
2 changes: 1 addition & 1 deletion storages/python/tests-python/test_redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import dlite
from dlite.testutils import importskip, serverskip

importskip("redis") # skip this test if redis is not available
importskip("redis", env_exitcode=None) # skip this test if redis is not available
serverskip("localhost", 6379) # skip test if redis is down


Expand Down

0 comments on commit 5df5306

Please sign in to comment.