diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 524407119bc53be9dcfac5e0cddd9b957a4388fb..855abedabb0434d20384c114b7c9e2ab82c65c62 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -18,6 +18,8 @@ variables:
   BUILD_PROCESSES: "" # Empty string: builds all processes
   BUILD_TESTS: "true"
   BUILD_CTEST: "true"
+  # Test config
+  NUM_CTEST_ERROR_LINES: 1000 # tail this much lines from failed output
 
 workflow:
   rules:
diff --git a/scripts/ci/extends/template-build-linux.yml b/scripts/ci/extends/template-build-linux.yml
index e2ed2485e1fd37f475c3d38922758b31f24e8cde..40ee21c36b712d0ca89da45754107ac130d36b19 100644
--- a/scripts/ci/extends/template-build-linux.yml
+++ b/scripts/ci/extends/template-build-linux.yml
@@ -22,7 +22,17 @@
       if [[ -z "$TARGETS" ]]; then
           $BUILD_CMD_PREFIX cmake --build . --target package > >(tee make.output)
           if [ "$BUILD_TESTS" = true ] ; then $BUILD_CMD_PREFIX cmake --build . --target tests ; fi
-          if [ "$BUILD_CTEST" = true ] ; then $BUILD_CMD_PREFIX cmake --build . --target ctest ; fi
+
+          if [ "$BUILD_CTEST" = true ]; then
+            ctest_exit=0
+            ctest -T Test --no-compress-output --exclude-regex LARGE --timeout 900 || ctest_exit=$?
+            if [ $ctest_exit -ne 0 ]; then
+              echo "ctests failed (showing the last ${NUM_CTEST_ERROR_LINES} lines):"
+              xsltproc ${CI_PROJECT_DIR}/scripts/test/ctest-error-output.xsl Testing/*/Test.xml | tail -n ${NUM_CTEST_ERROR_LINES}
+              exit $ctest_exit
+            fi
+          fi
+
           if [ "$BUILD_CTEST_LARGE" = true ] ; then $BUILD_CMD_PREFIX cmake --build . --target ctest-large ; fi
           if [ "$BUILD_CTEST" = true ] ; then cp Testing/**/Test.xml Tests/ctest.xml ; fi
           if [ "$BUILD_CTEST_LARGE" = true ] ; then cp Testing/**/Test.xml Tests/ctest-large.xml ; fi
diff --git a/scripts/test/ctest-error-output.xsl b/scripts/test/ctest-error-output.xsl
new file mode 100644
index 0000000000000000000000000000000000000000..c7161d374271392cb7a49055ba877f67baf02787
--- /dev/null
+++ b/scripts/test/ctest-error-output.xsl
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!-- Was created with:
+       xmlstarlet sel -C -t \
+         -m "//*/Testing/Test[@Status='failed']" \
+         -o '[ctest]  ' -v './/Name' -o ':' -n -n  \
+         -v './/Results/Measurement/Value/text()' -n \
+         -o '[ctest end]' -n -n \
+         Testing/20210510-0943/Test.xml > ctest-error-output.xsl
+-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
+  <xsl:output omit-xml-declaration="yes" indent="no"/>
+  <xsl:template match="/">
+    <xsl:for-each select="//*/Testing/Test[@Status='failed']">
+      <xsl:text>[ctest]  </xsl:text>
+      <xsl:call-template name="value-of-template">
+        <xsl:with-param name="select" select=".//Name"/>
+      </xsl:call-template>
+      <xsl:text>:</xsl:text>
+      <xsl:value-of select="'&#10;'"/>
+      <xsl:value-of select="'&#10;'"/>
+      <xsl:call-template name="value-of-template">
+        <xsl:with-param name="select" select=".//Results/Measurement/Value/text()"/>
+      </xsl:call-template>
+      <xsl:value-of select="'&#10;'"/>
+      <xsl:text>[ctest end]</xsl:text>
+      <xsl:value-of select="'&#10;'"/>
+      <xsl:value-of select="'&#10;'"/>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template name="value-of-template">
+    <xsl:param name="select"/>
+    <xsl:value-of select="$select"/>
+    <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
+      <xsl:value-of select="'&#10;'"/>
+      <xsl:value-of select="."/>
+    </xsl:for-each>
+  </xsl:template>
+</xsl:stylesheet>