diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d7ce5e758be3ce2a5a9574dba96807fd1f076911..c181d83507c6818fe9fee74e6bb8fe3a76badaeb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,6 @@
 stages:
   - build
+  - test
 
 variables:
   BUILD_ENV_DOCKER_IMAGE: docker-registry.ebrains.eu/tc/ebrains-spack-build-env/okd:okd_23.06
@@ -180,6 +181,10 @@ build-spack-env-on-runner:
   script:
     # run installation script
     - . install_spack_env.sh $CI_PROJECT_DIR $SPACK_VERSION $CI_PROJECT_DIR $SPACK_DEV_ENV $SPACK_PATH_GITLAB
+    # re-activate envionment and run tests
+    - spack env activate $SPACK_DEV_ENV
+    # TODO: run all tests when test dependency issue is fixed
+    - spack test run -x wf-brainscales2-demos wf-multi-area-model
   after_script:
     - mkdir -p $CI_PROJECT_DIR/spack_logs/installed $CI_PROJECT_DIR/spack_logs/not_installed
       # for succesfully installed packages: keep the spack logs for any package modified during this CI job
@@ -187,9 +192,11 @@ build-spack-env-on-runner:
     - if cd $PKG_DIR; then find . \( -name ".spack" -o -name ".build" -o -name ".spack_test_results" \) -exec cp -r --parents "{}" $CI_PROJECT_DIR/spack_logs/installed \;; fi
       # for not succesfully installed packages: also keep the spack logs for any packages that failed
     - if cd /tmp/$(whoami)/spack-stage/; then find . -maxdepth 2 -name "*.txt" -exec cp --parents "{}" $CI_PROJECT_DIR/spack_logs/not_installed \;; fi
+    - if [ -d /tmp/spack_tests ]; then mv /tmp/spack_tests $CI_PROJECT_DIR; fi
   artifacts:
     paths:
       - spack_logs
+      - spack_tests
     when: always
   timeout: 2 days
   except:
@@ -225,3 +232,30 @@ sync-gitlab-spack-instance:
   rules:
     - if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "experimental_rel" || $CI_COMMIT_BRANCH =~ /^ebrains/) && $CI_PROJECT_NAMESPACE =~ /technical-coordination/
       when: manual
+
+test-gitlab-spack-instance:
+  stage: test
+  tags:
+    - docker-runner
+    - read-write
+  image: $GITLAB_BUILD_ENV_DOCKER_IMAGE
+  variables:
+    SPACK_NFS_ENV: ebrains-runner-build
+    SPACK_REPO_PATH: $SPACK_PATH_GITLAB/ebrains-spack-builds
+    SPACK_USER_CACHE_PATH: $SPACK_PATH_GITLAB/spack/.spack
+    SPACK_USER_CONFIG_PATH: $SPACK_PATH_GITLAB/spack/.spack
+  script:
+    - source $SPACK_PATH_GITLAB/spack/share/spack/setup-env.sh
+    - spack env activate $SPACK_NFS_ENV
+    # TODO: run all tests when test dependency issue is fixed
+    - spack test run -x wf-brainscales2-demos wf-multi-area-model
+  after_script:
+    - if [ -d /tmp/spack_tests ]; then mv /tmp/spack_tests $CI_PROJECT_DIR; fi
+  artifacts:
+    paths:
+      - spack_tests
+    when: always
+  rules:
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PROJECT_NAMESPACE =~ /technical-coordination/
+    - if: $CI_PIPELINE_SOURCE == "schedule" && $TEST_DEPLOYMENT == "true"
+
diff --git a/packages/wf-brainscales2-demos/package.py b/packages/wf-brainscales2-demos/package.py
index a879c609f6ceebf48dcb4aebdc46f455501ef28d..5acf551cb328cf87a9d2942de1baa612fd044c4d 100644
--- a/packages/wf-brainscales2-demos/package.py
+++ b/packages/wf-brainscales2-demos/package.py
@@ -37,16 +37,13 @@ class WfBrainscales2Demos(Package):
     depends_on('py-pandas@1.4.2:', type=("run", "test"))
 
     def install(self, spec, prefix):
-        # sanity_check_prefix requires something in the install directory
-        mkdirp(prefix + "/.spack_test_results")
+        install_tree(".", join_path(prefix, "notebooks"))
 
-    def _run_notebooks(self):
-        # TODO: remove debug output
-        cmd_env = which("env")
-        cmd_env()
+    def _run_notebooks(self, output_dir):
+        mkdirp(output_dir)
         # execute notebook and save
         jupyter = Executable("jupyter")
-        for fn in glob("ts*.ipynb") + glob("tp*.ipynb"):
+        for fn in glob(join_path(prefix, "notebooks", "ts*.ipynb")) + glob(join_path(prefix, "notebooks", "tp*.ipynb")):
             jupyter("nbconvert",
                 "--ExecutePreprocessor.kernel_name=python3",
                 "--execute",
@@ -55,7 +52,7 @@ class WfBrainscales2Demos(Package):
                 "notebook",
                 fn,
                 "--output",
-                prefix + "/.spack_test_results/" + fn)
+                join_path(output_dir, os.path.basename(fn)))
 
     def _set_collab_things(self):
         # enable "EBRAINS lab" mode
@@ -69,8 +66,8 @@ class WfBrainscales2Demos(Package):
     def installcheck(self):
         self._set_collab_things()
         # TODO (ECM): Provide a selection of notebooks that perform local-only tests.
-        #self._run_notebooks()
+        #self._run_notebooks(join_path(self.prefix, ".spack_test_results"))
 
     def test_notebooks(self):
         self._set_collab_things()
-        self._run_notebooks()
+        self._run_notebooks(join_path(self.test_suite.stage, self.spec.format("out-{name}-{version}-{hash:7}")))
diff --git a/packages/wf-multi-area-model/package.py b/packages/wf-multi-area-model/package.py
index 01ffda36e18216b0037e7d4fc043830fb8cbd2b7..3b6c6c24cb686d641ec81c0b14c91bad8c72e8f5 100644
--- a/packages/wf-multi-area-model/package.py
+++ b/packages/wf-multi-area-model/package.py
@@ -17,23 +17,37 @@ class WfMultiAreaModel(Package):
     version("master",  branch="master")
     version("ebrains",  branch="lab.ebrains.eu")
 
-    depends_on("py-nested-dict")
-    depends_on("py-dicthash")
-    depends_on("py-matplotlib")
-    depends_on("py-numpy")
-    depends_on("py-scipy")
-    depends_on("py-future")
-    depends_on("nest")
-    depends_on("r-aod")
-    depends_on("py-notebook", type="test")
+    depends_on("py-nested-dict", type=("run", "test"))
+    depends_on("py-dicthash", type=("run", "test"))
+    depends_on("py-matplotlib", type=("run", "test"))
+    depends_on("py-numpy", type=("run", "test"))
+    depends_on("py-scipy", type=("run", "test"))
+    depends_on("py-future", type=("run", "test"))
+    depends_on("nest", type=("run", "test"))
+    depends_on("r-aod", type=("run", "test"))
+    depends_on("py-notebook", type=("run", "test"))
 
     def install(self, spec, prefix):
-        # sanity_check_prefix requires something in the install directory
-        mkdirp(prefix + "/.spack_test_results")
+        install_tree(".", join_path(prefix, "notebooks"))
+
+    def _run_notebooks(self, output_dir):
+        mkdirp(output_dir)
+        # execute notebook and save
+        jupyter = Executable("jupyter")
+        jupyter("nbconvert",
+            "--ExecutePreprocessor.kernel_name=python3",
+            "--execute",
+            "--allow-errors",
+            "--to",
+            "notebook",
+            join_path(self.prefix, "notebooks", "multi-area-model.ipynb"),
+            "--output",
+            join_path(output_dir, "multi-area-model.ipynb"))
 
     @run_after("install")
     @on_package_attributes(run_tests=True)
     def installcheck(self):
-        # execute notebook and save
-        jupyter = Executable("jupyter")
-        jupyter("nbconvert", "--ExecutePreprocessor.kernel_name=python3", "--execute", "--allow-errors", "--to", "notebook", "multi-area-model.ipynb", "--output", prefix+"/.spack_test_results/multi-area-model.ipynb")
+        self._run_notebooks(join_path(self.prefix, ".spack_test_results"))
+
+    def test_notebook(self):
+        self._run_notebooks(join_path(self.test_suite.stage, self.spec.format("out-{name}-{version}-{hash:7}")))
diff --git a/site-config/ebrainslab/config.yaml b/site-config/ebrainslab/config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8e58bc0377128adb64c3c25f790da18e19cd3316
--- /dev/null
+++ b/site-config/ebrainslab/config.yaml
@@ -0,0 +1,2 @@
+config:
+  test_stage: /tmp/spack_tests