diff --git a/.github/workflows/container_build.yml b/.github/workflows/container_build.yml index 5c141da..db56b62 100644 --- a/.github/workflows/container_build.yml +++ b/.github/workflows/container_build.yml @@ -10,7 +10,7 @@ on: tags: - "v*.*.*" env: - TEST_TAG: ghcr.io/precimed/container_template:test + LATEST_TAG: ghcr.io/precimed/container_template:latest jobs: docker: @@ -51,13 +51,18 @@ jobs: with: context: "{{defaultContext}}:docker" load: true - tags: ${{ env.TEST_TAG }} + tags: ${{ env.LATEST_TAG }} file: ./dockerfiles/container_template/Dockerfile - - name: Run unit tests + - name: Run unit tests I run: | - docker run --rm -v ${{ github.workspace }}:/home ${{ env.TEST_TAG }} py.test -v tests + docker run --rm -v ${{ github.workspace }}:/home ${{ env.LATEST_TAG }} py.test -v tests + + - name: Run unit tests II + run: | + pip install -r test-requirements.txt + py.test -v tests - name: Build uses: docker/build-push-action@v6 diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000..e079f8a --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +pytest diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 0000000..8f2ad61 --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +cache_dir = /tmp/pytest-cache/ \ No newline at end of file diff --git a/tests/test_container_template.py b/tests/test_container_template.py index aab0bb7..1e50208 100644 --- a/tests/test_container_template.py +++ b/tests/test_container_template.py @@ -9,37 +9,52 @@ """ import os -import socket import subprocess +import tempfile -# port used by tests -sock = socket.socket() -sock.bind(('', 0)) -port = sock.getsockname()[1] - -# Check that (1) singularity exist, and (2) if not, check for docker. +# Check that (1) singularity or apptainer executables exist, +# and (2) if not, check for docker. # If neither are found, tests will fall back to plain python. +# This may be useful for testing on a local machine, but should +# be revised for the particular usecase. +cwd = os.getcwd() try: pth = os.path.join('containers', 'container_template.sif') - out = subprocess.run('singularity') - cwd = os.getcwd() - PREFIX = f'singularity run {pth} python' - PREFIX_MOUNT = f'singularity run --home={cwd}:/home/ {pth} python' + try: + runtime = 'apptainer' + out = subprocess.run(runtime, check=False) + except FileNotFoundError: + try: + runtime = 'singularity' + out = subprocess.run(runtime, check=False) + except FileNotFoundError as exc: + raise FileNotFoundError from exc + PREFIX = f'{runtime} run {pth} python' + PREFIX_MOUNT = f'{runtime} run --home={cwd}:/home/ {pth} python' + PREFIX_CUSTOM_MOUNT = f'{runtime} run --home={cwd}:/home/ ' + \ + '{custom_mount}' + f'{pth} python' except FileNotFoundError: try: - out = subprocess.run('docker') - pwd = os.getcwd() - PREFIX = (f'docker run -p {port}:{port} ' + + runtime = 'docker' + out = subprocess.run(runtime, check=False) + PREFIX = (f'{runtime} run ' + 'ghcr.io/precimed/container_template python') PREFIX_MOUNT = ( - f'docker run -p {port}:{port} ' + - f'--mount type=bind,source={pwd},target={pwd} ' + + f'{runtime} run ' + + f'--mount type=bind,source={cwd},target={cwd} ' + + 'ghcr.io/precimed/container_template python') + PREFIX_CUSTOM_MOUNT = ( + f'{runtime} run ' + + f'--mount type=bind,source={cwd},target={cwd} ' + + '{custom_mount} ' + 'ghcr.io/precimed/container_template python') except FileNotFoundError: # neither singularity nor docker found, fall back to plain python + runtime = None PREFIX = 'python' PREFIX_MOUNT = 'python' + PREFIX_CUSTOM_MOUNT = 'python' def test_assert(): @@ -56,12 +71,28 @@ def test_container_template_python(): def test_container_template_python_script(): '''test that Python can run a script''' - pwd = os.getcwd() if PREFIX.rfind('docker') >= 0 else '.' - call = f'''{PREFIX_MOUNT} {pwd}/tests/extras/hello.py''' + cwd = os.getcwd() if runtime == 'docker' else '.' + call = f'''{PREFIX_MOUNT} {cwd}/tests/extras/hello.py''' out = subprocess.run(call.split(' '), capture_output=True) assert out.returncode == 0 +def test_container_template_python_script_from_tempdir(): + '''test that the tempdir is working''' + with tempfile.TemporaryDirectory() as d: + os.system(f'cp {cwd}/tests/extras/hello.py {d}/') + if runtime == 'docker': + custom_mount = f'--mount type=bind,source={d},target={d}' + elif runtime in ['apptainer', 'singularity']: + custom_mount = f'--bind {d}:{d} ' + else: + custom_mount = '' + call = f'{PREFIX_CUSTOM_MOUNT.format(custom_mount=custom_mount)} ' + \ + f'{d}/hello.py' + out = subprocess.run(call, shell=True, check=False) + assert out.returncode == 0 + + def test_container_template_python_packages(): '''test that the Python packages are installed''' packages = [