# Test extension in Docker

**URL:** https://discourse.slicer.org/t/test-extension-in-docker/8120
**Category:** Support
**Tags:** extensions-manager, docker, testing
**Created:** [August 21, 2019, 12:23pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120 "2019-08-21T12:23:49Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 21, 2019, 12:23pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/1 "2019-08-21T12:23:50Z")

</div>

Hello everyone,

I’d like to set up a CI-pipeline with **Gitlab CI** , which should enable continuous testing of our extension (in python). However, it’s not quite obvious to me which dependencies I therefore have to integrate. The imports i need from Slicer are basically `slicer` and `qt`.

To fasten up the process, I’ve used the docker-image `slicer/slicer-build` mentioned in [this thread](https://discourse.slicer.org/t/slicer-docker-images/508) and described on [github](https://github.com/thewtex/SlicerDocker).

However, I still have the following questions:

1. Is it correct that [these images](https://github.com/thewtex/SlicerDocker) are the **official** slicer docker-images?
2. Is it correct that they represent the lastest **nightly build**?
3. What is the **path** I have to add to `PYTHONPATH`, in order to import these distributions? (I’d have guessed `/usr/src/Slicer-build/Slicer-build/bin/Python` but I’m not quite sure…)

Thank you for any help or suggestions in advance!

Once I have everything in place, I’d like to share it so that others can profit as well.

---

<div class="post-metadata">

### Author: ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)
#### Post date: [August 21, 2019, 12:38pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/2 "2019-08-21T12:38:59Z")

</div>

> [@unnmdnwb3](#):
>
> - Is it correct that [these images](https://github.com/thewtex/SlicerDocker) are the **official** slicer docker-images?

There are two type of official images:

- The [slicer/slicer-base](https://github.com/thewtex/SlicerDocker) image is published daily and only contain the dependencies of Slicer in the form of build trees (VTK, ITK, …). It is used to make sure the changes proposed as Slicer pull request can compile. This image depends on `slicer/buildenv-qt5-centos7`

- The [slicer/buildenv-\*](https://github.com/Slicer/SlicerBuildEnvironment/#docker-based-environments) images are used to build Slicer.

> [@unnmdnwb3](#):
>
> - Is it correct that they represent the lastest **nightly build**?

yes

> [@unnmdnwb3](#):
>
> - What is the **path** I have to add to `PYTHONPATH` , in order to import these distributions?

To clarify, we are not yet publishing an official image that contain Slicer binaries.

To have a usable image for CI, I suggest to build on the following work:

- from @ihnorton: [dockerfiles/slicer2binder at master · ihnorton/dockerfiles · GitHub](https://github.com/ihnorton/dockerfiles/tree/master/slicer2binder)

- from @pieper : [SlicerDockers/slicer at master · pieper/SlicerDockers · GitHub](https://github.com/pieper/SlicerDockers/tree/master/slicer)

- from @thewtex: [GitHub - thewtex/docker-opengl: A docker image that supports rendering graphical applications.](https://github.com/thewtex/docker-opengl/tree/master)

---

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 22, 2019, 11:10am UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/3 "2019-08-22T11:10:39Z")

</div>

Hi @jcfr, thanks for your answer!

If I understand you correctly though, `slicer/slicer-build` should already include the compiled build, right? Since it can also be used for [circle-ci](https://github.com/Slicer/Slicer/blob/master/.circleci/config.yml)?

I’ve also taken a look into for testing from **[SlicerITKUltrasound](https://github.com/KitwareMedical/SlicerITKUltrasound/blob/master/Docker/test.sh#L15)**, which is based on `slicer/slicer-base`.

The only piece failing for me is `import qt`. Do you know where I can import `qt` from?

Thanks in advance!

---

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 22, 2019, 2:28pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/4 "2019-08-22T14:28:56Z")

</div>

Short update:

I’ve now built a docker image based on `slicer/slicer-build`, to which I copy my extension into (also via a container).

Using the `cmake` command from [SlicerITKUltrasound](https://github.com/KitwareMedical/SlicerITKUltrasound/blob/master/Docker/test.sh#L15), I managed to build my extension.

I think the only thing I now need is to set up a `CTestTestfile.cmake` for my **python tests** , that I have already written and which run trough locally.

Do you agree with my thought process?

Btw. my `Dockerfile` currently looks like this:

```auto
FROM alpine:latest as base 

RUN apk add git

RUN git clone my_extension

FROM slicer/slicer-build as build

RUN cd /usr/src && mkdir my_extension-build

COPY --from=base /my_extension /usr/src/my_extension

RUN cd /usr/src/ && mkdir my_extension-build && cmake -DSlicer_DIR:PATH=/usr/src/Slicer-build/Slicer-build -DBUILDNAME:STRING=my_extension /usr/src/my_extension

RUN cd MyExtension && make
```

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [August 22, 2019, 4:15pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/5 "2019-08-22T16:15:38Z")

</div>

Thanks for the update.

I cannot comment on that if it is correct or optimal (@jcfr should give feedback on that), but we should probably use this in our extensions and also add it to our extension template. @jcfr @pieper what do you think?

---

<div class="post-metadata">

### Author: ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)
#### Post date: [August 22, 2019, 6:07pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/6 "2019-08-22T18:07:58Z")

</div>

I don’t think there should be anything special about running in the container - if you build the extension structure using the wizard then all the build and test infrastructure should be set up automatically. But yes, if there’s a way to build containerized testing infrastructure into the extension template we should.

@unnmdnwb3 - do you really want to do the cmake/make commands in the `RUN` statement? I’d think you’d want this container to be doing the checkout and build in the instance and not in the `docker build` step.

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [August 22, 2019, 6:33pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/7 "2019-08-22T18:33:33Z")

</div>

> [@pieper](#):
>
> if there’s a way to build containerized testing infrastructure into the extension template we should.

We could add all the necessary files to the extension template (docker subfolder, travis & circleci configuration files, badges in the readme.md file, etc.). It should be easy if there is a good example to follow.

---

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 23, 2019, 5:59am UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/8 "2019-08-23T05:59:53Z")

</div>

> [@lassoan](#):
>
> We could add all the necessary files to the extension template (docker subfolder, travis & circleci configuration files, badges in the readme.md file, etc.). It should be easy if there is a good example to follow.

That’s a great idea! Everything that automates testing is awesome. Facilitating the CI could support teams to start using it, which supposedly results in better tested and hence more robust extensions.

I’d be happy to later contribute by `Dockerfile` and `gitlab-ci.yml` once everything’s in place - if you’re interested of course. And I could also propose a `.travis.yml` for those working with Github.

> [@pieper](#):
>
> @unnmdnwb3 - do you really want to do the cmake/make commands in the `RUN` statement? I’d think you’d want this container to be doing the checkout and build in the instance and not in the `docker build` step.

Thanks for pointing that out. I honestly don’t have a rich experience with `cmake` and joined the extension project a few days ago. If you advice me to do it differently, I’ll follow your suggestion!

---

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 23, 2019, 11:29am UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/9 "2019-08-23T11:29:32Z")

</div>

I’ve now managed to get a correct build (as described in the [wiki](https://www.slicer.org/wiki/Documentation/Nightly/Developers/FAQ#How_to_build_an_extension_.3F)) and configuration in my `CMakeLists.txt`, so that the correct tests are run.

But now I have the following issue:

```auto
3: Test command: /usr/src/Slicer-build/Slicer-build/Slicer "--no-splash" "--testing" "--launcher-additional-settings" "/usr/src/extension-build/AdditionalLauncherSettings.ini" "--additional-module-paths" "/usr/src/extension-build/lib/Slicer-4.9/qt-scripted-modules" "/usr/src/extension-build/lib/Slicer-4.9/cli-modules" "/usr/src/extension-build/lib/Slicer-4.9/qt-loadable-modules" "--python-code" "import slicer.testing; slicer.testing.runUnitTest(['/usr/src/extension-build/Extension', '/usr/src/extension/Extension'], 'extensionTest')"
3: Test timeout computed to be: 1500
3: SlicerApp-real: cannot connect to X server 
3: vtkDebugLeaks has found no leaks.
3/3 Test #3: py_extensionTest ...................................***Failed 0.38 sec

```

However, **X11** is installed in `/etc/X11`…

---

<div class="post-metadata">

### Author: ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)
#### Post date: [August 23, 2019, 1:56pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/10 "2019-08-23T13:56:48Z")

</div>

@unnmdnwb3, looks close, but you need to have X up running for slicer to run.

If you look at the X11 example in [the SlicerDockers repository](https://github.com/pieper/SlicerDockers) you can see how to set this up. Also in the readme there is an example of running a script inside the instance that uses Slicer and the X server. This approach could be adapted to run the testing as well, probably using the [build images](https://github.com/thewtex/SlicerDocker).

There’s clearly a lot of potential benefit here, but things aren’t really documented or coordinated. It’ll be good to see a good clean end to end solution.

---

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 27, 2019, 1:57pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/11 "2019-08-27T13:57:16Z")

</div>

Short update: I’ve now managed to (mostly) resolve the X issues.

When running `ctest -V` though, the following error occurs:

```auto
2: Test command: /usr/src/Slicer-build/Slicer-build/Slicer "--no-splash" "--testing" "--launcher-additional-settings" "/usr/src/extension-build/AdditionalLauncherSettings.ini" "--additional-module-paths" "/usr/src/extension-build/lib/Slicer-4.9/qt-scripted-modules" "/usr/src/extension-build/lib/Slicer-4.9/cli-modules" "/usr/src/extension-build/lib/Slicer-4.9/qt-loadable-modules" "--python-code" "import slicer.testing; slicer.testing.runUnitTest(['/usr/src/extension-build/Extension/Logic', '/usr/src/extension/Extension/Logic'], 'DExtensionTest')"
2: Test timeout computed to be: 1500
Could not init font path element unix/:7100, removing from list!
2: Number of registered modules: 101 
2: Traceback (most recent call last):
2: File "<string>", line 1, in <module>
2: File "/usr/src/extension-build/lib/Slicer-4.9/qt-scripted-modules/Extension.py", line 15, in <module>
2: from pathlib import Path
2: ImportError: No module named pathlib
2: loadSourceAsModule - Failed to load file "/usr/src/extension-build/lib/Slicer-4.9/qt-scripted-modules/Extension.py" as module "Extension" ! 
2: Fail to instantiate module "Extension" 
2: Number of instantiated modules: 100 
2: Number of loaded modules: 100 
2: Switch to module: "Welcome" 
2: -------------------------------------------
2: path: ['/usr/src/extension-build/Extension/Logic', '/usr/src/extension/Extension/Logic']
2: testname: ExtensionTest
2: -------------------------------------------
2: Traceback (most recent call last):
2: File "<string>", line 1, in <module>
2: File "/usr/src/Slicer-build/Slicer-build/bin/Python/slicer/testing.py", line 22, in runUnitTest
2: suite = unittest.TestLoader().loadTestsFromName(testname)
2: File "/usr/src/Slicer-build/python-install/lib/python2.7/unittest/loader.py", line 91, in loadTestsFromName
2: module = __import__ ('.'.join(parts_copy))
2: File "/usr/src/extension/Extension/Logic/ExtensionTest.py", line 3, in <module>
2: from .ExtensionLogic import *
2: ValueError: Attempted relative import in non-package
2: Switch to module: "" 
error opening security policy file /usr/lib64/xserver/SecurityPolicy
2: vtkDebugLeaks has found no leaks.

```

It seems like a **relative import** is not possible. However the Slicer Python should be **3.+** , right?  
Possibly, this is because Slicer is not correctly integrated into the project and uses the default installation?

```auto
which python
> /usr/local/bin/python

```

Do you have any insight into this?

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [August 27, 2019, 2:03pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/12 "2019-08-27T14:03:58Z")

</div>

> [@unnmdnwb3](#):
>
> However the Slicer Python should be **3.+** , right?

Slicer-4.10 and earlier uses Python2. From Slicer-4.11.x Slicer uses Python3.

> [@unnmdnwb3](#):
>
> ```auto
> which python
> > /usr/local/bin/python
> 
> ```
> 
> Do you have any insight into this?

Slicer’s Python executable is called `PythonSlicer` and not `python`.

---

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 29, 2019, 9:22am UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/13 "2019-08-29T09:22:14Z")

</div>

Thank you for the information!

Accordingly to your answer, cloning from [https://github.com/Slicer/Slicer/tree/master](https://github.com/Slicer/Slicer/tree/master) results in a `v4.10.2`, which only supports `python2`. Whereas, pulling from [https://github.com/Slicer/Slicer/tree/nightly-master](https://github.com/Slicer/Slicer/tree/nightly-master) results in a `v4.11.x`, which supports `python3` - right?

And is it correct, that [slicer/slicer-base](https://github.com/thewtex/SlicerDocker/tree/master/slicer-base) pulls from the `master` and hence ends up with `python2`?

I tried to find `PythonSlicer` (and found it locally on my mac), but wasn’t able to locate it on the `slicer/slicer-build` image. However, I found a `SlicerPython` which is an executable as well. Can you elaborate on the difference between them?

---

<div class="post-metadata">

### Author: ![unnmdnwb3](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/unnmdnwb3/32/4527_2.png) [@unnmdnwb3](https://discourse.slicer.org/u/unnmdnwb3)
#### Post date: [August 30, 2019, 7:26am UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/14 "2019-08-30T07:26:31Z")

</div>

Nevermind. I’ve build a docker image, which builds `Slicer/Slicer#nightly-build` from the [official repo](https://github.com/Slicer/Slicer/tree/nightly-master), and can now use `python3`!

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [August 30, 2019, 12:40pm UTC](https://discourse.slicer.org/t/test-extension-in-docker/8120/15 "2019-08-30T12:40:38Z")

</div>

> [@unnmdnwb3](#):
>
> tried to find `PythonSlicer` (and found it locally on my mac), but wasn’t able to locate it on the `slicer/slicer-build` image. However, I found a `SlicerPython` which is an executable as well. Can you elaborate on the difference between them?

We renamed “SlicerPython” to “PythonSlicer” , because PyCharm only accepts custom Python interpreter names that start with “python”. We kept “SlicerPython” for backward compatibility for a while, but it will be removed in the future. The two processes do exactly the same.
