diff --git a/.gitignore b/.gitignore
index e53b5370e9e2ce635df0b3508e5da3c8a71eb3bf..2516bb9f9be92eb7b9dfd9ebf0b705e9857edcb7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 build*/
 *.sw[op]
 tags
+.ExternalData_*
diff --git a/.travis.yml b/.travis.yml
index e61fc9054f172b3a2db8df11ce08d244eada3ef2..3f9790d38b91b0b18c1b0ff79252b7d208fa7968 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,8 +29,9 @@ before_install:
   - travis_retry sudo apt-get install libboost1.55-dev libboost-date-time1.55-dev libboost-filesystem1.55-dev libboost-program-options1.55-dev libboost-system1.55-dev
 
   # CMake
-  - travis_retry wget https://launchpad.net/ubuntu/+source/cmake/2.8.8-2ubuntu1/+build/3441442/+files/cmake_2.8.8-2ubuntu1_amd64.deb; travis_retry wget https://launchpad.net/ubuntu/+archive/primary/+files/cmake-data_2.8.8-2ubuntu1_all.deb
-  - sudo apt-get remove cmake-data cmake; sudo dpkg --install cmake-data_2.8.8-2ubuntu1_all.deb cmake_2.8.8-2ubuntu1_amd64.deb
+  - sudo apt-get remove cmake-data cmake
+  - travis_retry wget http://www.opengeosys.org/images/dev/cmake-2.8.12.2-Linux-x86_64.deb
+  - sudo sudo dpkg --install cmake-2.8.12.2-Linux-x86_64.deb
 
   # Qt and VTK
   - if [[ "$CASE" == "GUI" ]]; then travis_retry sudo apt-get install qt4-dev-tools libshp-dev libgeotiff-dev libxt-dev; fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1cb91d27654b6db5d0aaec0e976a2cd68cc758f9..28763f81e40252d07f2920ad6fa69feaf539dea5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,7 +37,9 @@ INCLUDE(scripts/cmake/Find.cmake)
 INCLUDE(scripts/cmake/SubmoduleSetup.cmake)
 INCLUDE(scripts/cmake/ProjectSetup.cmake)
 INCLUDE(scripts/cmake/DocumentationSetup.cmake)
-INCLUDE(scripts/cmake/Test.cmake)
+IF(CMAKE_VERSION VERSION_GREATER 2.8.10)
+	INCLUDE(scripts/cmake/test/Test.cmake)
+ENDIF()
 IF(OGS_COVERAGE AND NOT IS_SUBPROJECT)
 	INCLUDE(scripts/cmake/Coverage.cmake)
 ENDIF()
@@ -148,12 +150,20 @@ IF( OGS_BUILD_CLI )
 	ADD_SUBDIRECTORY( OGS )
 ENDIF() # OGS_BUILD_CLI
 IF( OGS_BUILD_TESTS AND NOT IS_SUBPROJECT )
+	IF(CMAKE_VERSION VERSION_LESS 2.8.11)
+		MESSAGE(FATAL_ERROR "CMAKE 2.8.11 or higher is required to build the tests!")
+	ENDIF()
 	ADD_SUBDIRECTORY( Tests )
-	ADD_SUBDIRECTORY( SimpleTests/MatrixTests )
-	ADD_SUBDIRECTORY( SimpleTests/MeshTests )
+	ADD_SUBDIRECTORY( SimpleTests/MatrixTests EXCLUDE_FROM_ALL )
+	ADD_SUBDIRECTORY( SimpleTests/MeshTests EXCLUDE_FROM_ALL )
 	IF(NOT MSVC AND BLAS_FOUND AND LAPACK_FOUND)
-		ADD_SUBDIRECTORY( SimpleTests/SolverTests )
+		ADD_SUBDIRECTORY( SimpleTests/SolverTests EXCLUDE_FROM_ALL )
 	ENDIF()
+	# Create a target 'data', which downloads all referenced data sets into the build tree
+	# This has to be defined after all tests are defined
+	ExternalData_Add_Target(data)
+	SET_TARGET_PROPERTIES(data PROPERTIES EXCLUDE_FROM_ALL 1)
+	ADD_DEPENDENCIES(ctest data)
 ENDIF() # OGS_BUILD_TESTS
 IF(OGS_BUILD_UTILS AND NOT IS_SUBPROJECT)
 	ADD_SUBDIRECTORY( Utils/SimpleMeshCreation )
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.bc.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.bc.md5
new file mode 100644
index 0000000000000000000000000000000000000000..68ac2e096d661d2c82bcc7280cc19c3ca6755aa6
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.bc.md5
@@ -0,0 +1 @@
+6c5a67ef6572bbe5070fc331b1fc9a69
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.cnd.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.cnd.md5
new file mode 100644
index 0000000000000000000000000000000000000000..7d308ccba74a509289b970a0791c8303cda311de
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.cnd.md5
@@ -0,0 +1 @@
+55bfc26fbcf45b779af3d0d688fb83b9
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.gli.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.gli.md5
new file mode 100644
index 0000000000000000000000000000000000000000..877049f4b96b86a1a4c28f3c2425642833129a00
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.gli.md5
@@ -0,0 +1 @@
+e0e57cd16d19acea8a29d4c964dfb924
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.gml.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.gml.md5
new file mode 100644
index 0000000000000000000000000000000000000000..a543c1af91087efe9fe4df1a1795dc397e58d786
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.gml.md5
@@ -0,0 +1 @@
+a054fc73631ae534b814184eb60977c7
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.ic.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.ic.md5
new file mode 100644
index 0000000000000000000000000000000000000000..9c6e57ad21b81e23e0575d6bc58069b4b5c8d96a
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.ic.md5
@@ -0,0 +1 @@
+28e65510cf287ebd30821075d8e09ca8
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.mfp.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.mfp.md5
new file mode 100644
index 0000000000000000000000000000000000000000..b4244e260c1a8ea375b3eb8fa2520e915a9d446d
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.mfp.md5
@@ -0,0 +1 @@
+29685f8dd61734ead5632b545726758c
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.mmp.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.mmp.md5
new file mode 100644
index 0000000000000000000000000000000000000000..c7df570ffb08e7944efb5ffff4cfb7465fb1df91
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.mmp.md5
@@ -0,0 +1 @@
+5835b975206ba98627a1b6f1dd6be7af
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.msh.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.msh.md5
new file mode 100644
index 0000000000000000000000000000000000000000..31884ad24753a0636533fa1503033bf7d5e1c574
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.msh.md5
@@ -0,0 +1 @@
+e4c0846e14eeeb1807dd5a52bb98a8ea
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.msp.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.msp.md5
new file mode 100644
index 0000000000000000000000000000000000000000..c8f475148d64a1ecb3fca88b32700af64de72265
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.msp.md5
@@ -0,0 +1 @@
+95ebb6b241466ad0b3c73167755a9b3b
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.num.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.num.md5
new file mode 100644
index 0000000000000000000000000000000000000000..1c4025904aea6d6c72c2a14b194e4a3b04772306
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.num.md5
@@ -0,0 +1 @@
+2116bc15e48e7acabe5ffc3d0c5361fb
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.out.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.out.md5
new file mode 100644
index 0000000000000000000000000000000000000000..cb0e363a6bd1bfe25ae8a092ca6bfc33d84520d1
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.out.md5
@@ -0,0 +1 @@
+5964016dd01863a99dac25487287b58a
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.pcs.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.pcs.md5
new file mode 100644
index 0000000000000000000000000000000000000000..3cbbb8486ad9e55165a5f2d556e89fe1055bc4fd
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.pcs.md5
@@ -0,0 +1 @@
+4eeb3894145d1b4821f23ed9a6d7f238
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.pvd.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.pvd.md5
new file mode 100644
index 0000000000000000000000000000000000000000..c63313d0e70a350da7b6feaf8b9307b79d953d96
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.pvd.md5
@@ -0,0 +1 @@
+a74b042e3eccb2d4758068a8c289df14
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.rfd.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.rfd.md5
new file mode 100644
index 0000000000000000000000000000000000000000..c8f475148d64a1ecb3fca88b32700af64de72265
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.rfd.md5
@@ -0,0 +1 @@
+95ebb6b241466ad0b3c73167755a9b3b
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.st.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.st.md5
new file mode 100644
index 0000000000000000000000000000000000000000..c8f475148d64a1ecb3fca88b32700af64de72265
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.st.md5
@@ -0,0 +1 @@
+95ebb6b241466ad0b3c73167755a9b3b
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.tim.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.tim.md5
new file mode 100644
index 0000000000000000000000000000000000000000..a7edd5624ca40043ae293a0e613f9247eaf85307
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.tim.md5
@@ -0,0 +1 @@
+d671b92bd9c665a82dc0cdc20da91320
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.vtu.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.vtu.md5
new file mode 100644
index 0000000000000000000000000000000000000000..d252f598965091c56278b76dfcc6670d87c6fe23
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case.vtu.md5
@@ -0,0 +1 @@
+a615a23368e4cae2d0e794681ba18677
diff --git a/Tests/Data/Elliptic/2d-quads-x1000-y1000/case_expected_result.vtu.md5 b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case_expected_result.vtu.md5
new file mode 100644
index 0000000000000000000000000000000000000000..d753d6982a58c5c578e95734f36b400e4c3ed5f2
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x1000-y1000/case_expected_result.vtu.md5
@@ -0,0 +1 @@
+9bf2ebcfb38dae40c0a146c34724b463
diff --git a/Tests/Data/Elliptic/2d-quads-x200-y100/case.mcp.md5 b/Tests/Data/Elliptic/2d-quads-x200-y100/case.mcp.md5
new file mode 100644
index 0000000000000000000000000000000000000000..34cdc644eb6280dbd9dd6105f1fae823f652e4d2
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x200-y100/case.mcp.md5
@@ -0,0 +1 @@
+def4b0dfb8cd564a290fa534ea567291
diff --git a/Tests/Data/Elliptic/2d-quads-x200-y100/case.msp.md5 b/Tests/Data/Elliptic/2d-quads-x200-y100/case.msp.md5
new file mode 100644
index 0000000000000000000000000000000000000000..f9b8e0746941383c03a6190c7a6aee93d14641d8
--- /dev/null
+++ b/Tests/Data/Elliptic/2d-quads-x200-y100/case.msp.md5
@@ -0,0 +1 @@
+61c67e135d14f97cf717294aebff0495
diff --git a/scripts/cmake/Test.cmake b/scripts/cmake/Test.cmake
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/scripts/cmake/test/AddTest.cmake b/scripts/cmake/test/AddTest.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..06972349a4b23e28c3ae8f65a3b0eb1fafa3fd00
--- /dev/null
+++ b/scripts/cmake/test/AddTest.cmake
@@ -0,0 +1,61 @@
+FUNCTION (AddOgsBenchmark name project_name)
+
+	ExternalData_Add_Test(data
+		NAME "${name}-${project_name}"
+		COMMAND ogs DATA{${ExternalData_SOURCE_ROOT}/${project_name}} ${ARGN}
+	)
+
+ENDFUNCTION()
+
+FUNCTION (AddTest executable case_path case_name wrapper)
+
+	SET(tester ${ARGV4})
+
+	# Implement wrappers
+	IF(wrapper STREQUAL "TIME")
+		SET(WRAPPER_COMMAND time)
+	ELSEIF(wrapper STREQUAL "MEMCHECK" AND VALGRIND_TOOL_PATH)
+		SET(WRAPPER_COMMAND "${VALGRIND_TOOL_PATH} --tool=memcheck --log-file=${case_path}/${case_name}_memcheck.log -v --leak-check=full --show-reachable=yes --track-origins=yes --malloc-fill=0xff --free-fill=0xff")
+		SET(tester MEMCHECK)
+	ELSEIF(wrapper STREQUAL "CALLGRIND" AND VALGRIND_TOOL_PATH)
+		SET(WRAPPER_COMMAND "${VALGRIND_TOOL_PATH} --tool=callgrind --branch-sim=yes --cache-sim=yes --dump-instr=yes --collect-jumps=yes")
+		UNSET(tester)
+	ENDIF()
+
+	# Implement testers
+	IF(tester STREQUAL "DIFF")
+		SET(TESTER_COMMAND "${DIFF_TOOL_PATH} -sbB ${case_path}/${case_name}_expected_result.vtu ${case_path}/${case_name}_with_results.vtu")
+	ELSEIF(tester STREQUAL "MEMCHECK")
+		SET(TESTER_COMMAND "! ${GREP_TOOL_PATH} definitely ${case_path}/${case_name}_memcheck.log")
+	ENDIF()
+
+	## -----------
+
+	ExternalData_Add_Test(data
+		NAME "${executable}-${case_path}-${wrapper}"
+		COMMAND ${CMAKE_COMMAND}
+		-Dexecutable=$<TARGET_FILE:${executable}>
+		-Dcase_path=${case_path}
+		-Dcase_name=${case_name}
+		-Dwrapper=${wrapper}
+		-DWRAPPER_COMMAND=${WRAPPER_COMMAND}
+		-DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}
+		-P ${PROJECT_SOURCE_DIR}/scripts/cmake/test/AddTestWrapper.cmake
+		DATA{${case_path}/${case_name}.cnd, ${case_path}/${case_name}.gml, ${case_path}/${case_name}.vtu}
+	)
+
+	IF(NOT tester)
+		RETURN()
+	ENDIF()
+
+	ADD_TEST(NAME "${executable}-${case_path}-${wrapper}-${tester}"
+		COMMAND ${CMAKE_COMMAND}
+		-Dcase_path=${case_path}
+		-Dcase_name=${case_name}
+		-Dtester=${tester}
+		-DTESTER_COMMAND=${TESTER_COMMAND}
+		-DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}
+		-P ${PROJECT_SOURCE_DIR}/scripts/cmake/test/AddTestTester.cmake
+	)
+
+ENDFUNCTION()
diff --git a/scripts/cmake/test/AddTestTester.cmake b/scripts/cmake/test/AddTestTester.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..d0f30840c729dc02527880a4fb3a3f262366b081
--- /dev/null
+++ b/scripts/cmake/test/AddTestTester.cmake
@@ -0,0 +1,15 @@
+#message("tester: ${TESTER_COMMAND}")
+#STRING(REPLACE " " ";" TESTER_COMMAND ${TESTER_COMMAND})
+#set(list ${TESTER_COMMAND})
+#message("tester: ${list}")
+
+
+EXECUTE_PROCESS(
+	COMMAND bash -c ${TESTER_COMMAND}
+	WORKING_DIRECTORY ${case_path}
+	RESULT_VARIABLE EXIT_CODE
+)
+
+IF(NOT EXIT_CODE STREQUAL "0")
+	MESSAGE(FATAL_ERROR "Error exit code: ${EXIT_CODE}")
+ENDIF()
diff --git a/scripts/cmake/test/AddTestWrapper.cmake b/scripts/cmake/test/AddTestWrapper.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..0b900a6fdae56b9c6cfea412be96cebddba6f1c9
--- /dev/null
+++ b/scripts/cmake/test/AddTestWrapper.cmake
@@ -0,0 +1,12 @@
+SET(ARGS --boundary_condition ${case_path}/${case_name}.cnd -g ${case_path}/${case_name}.gml -m ${case_path}/${case_name}.vtu)
+
+STRING(REPLACE " " ";" WRAPPER_COMMAND ${WRAPPER_COMMAND})
+EXECUTE_PROCESS(
+	COMMAND ${WRAPPER_COMMAND} ${executable} ${ARGS}
+	WORKING_DIRECTORY ${case_path}
+	RESULT_VARIABLE EXIT_CODE
+)
+
+IF(NOT EXIT_CODE STREQUAL "0")
+	MESSAGE(FATAL_ERROR "Test wrapper exited with code: ${EXIT_CODE}")
+ENDIF()
diff --git a/scripts/cmake/test/CTestCustom.cmake.in b/scripts/cmake/test/CTestCustom.cmake.in
new file mode 100644
index 0000000000000000000000000000000000000000..66887f9e0f6e240f9d9a1e4fd53152d6d7a6eb36
--- /dev/null
+++ b/scripts/cmake/test/CTestCustom.cmake.in
@@ -0,0 +1,2 @@
+# SET(CTEST_CUSTOM_POST_TEST "cat ${CMAKE_BINARY_DIR}/Testing/Temporary/LastTestTester.log 2>&1")
+SET(CTEST_CUSTOM_TESTS_IGNORE ${CTEST_CUSTOM_TESTS_IGNORE}) # logog
diff --git a/scripts/cmake/test/Data.cmake b/scripts/cmake/test/Data.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..4b411d95c726de5d6eb21cdba4dad20c6aa9e82c
--- /dev/null
+++ b/scripts/cmake/test/Data.cmake
@@ -0,0 +1,25 @@
+INCLUDE(ExternalData)
+
+SET(ExternalData_OBJECT_STORES "${ExternalData_OBJECT_STORES_DEFAULT}" CACHE STRING
+	"Semicolon-separated list of local directories holding test data files in the layout %(algo)/%(hash).")
+MARK_AS_ADVANCED(ExternalData_OBJECT_STORES)
+IF(NOT ExternalData_OBJECT_STORES)
+	SET(ExternalData_OBJECT_STORES "${CMAKE_SOURCE_DIR}/../ogs6-data")
+	FILE(MAKE_DIRECTORY "${ExternalData_OBJECT_STORES}")
+ENDIF()
+
+SET(ExternalData_SOURCE_ROOT ${CMAKE_SOURCE_DIR}/Tests/Data)
+SET(ExternalData_BINARY_ROOT ${CMAKE_BINARY_DIR}/Tests/Data)
+SET(ExternalData_LINK_CONTENT MD5)
+
+SET(ExternalData_URL_TEMPLATES "http://www.opengeosys.org/images/dev/%(algo)/%(hash)")
+
+ADD_CUSTOM_TARGET(
+	move-data
+	COMMAND ${CMAKE_COMMAND}
+	-DExternalData_SOURCE_ROOT=${ExternalData_SOURCE_ROOT}
+	-DExternalData_LINK_CONTENT=${ExternalData_LINK_CONTENT}
+	-DExternalData_OBJECT_STORES=${ExternalData_OBJECT_STORES}
+	-P ${PROJECT_SOURCE_DIR}/scripts/cmake/test/MoveDataToStore.cmake
+	VERBATIM
+)
diff --git a/scripts/cmake/test/MoveDataToStore.cmake b/scripts/cmake/test/MoveDataToStore.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..2e70b1720a31f35996a37d1f6c47a46589454d11
--- /dev/null
+++ b/scripts/cmake/test/MoveDataToStore.cmake
@@ -0,0 +1,7 @@
+# Get all files matching .ExternalData_<algo>_<hash>
+FILE(GLOB_RECURSE FILES "" ${ExternalData_SOURCE_ROOT}/.ExternalData_${ExternalData_LINK_CONTENT}_*)
+FOREACH(HASH_FILE ${FILES})
+	STRING(REGEX MATCH [^_]+$ HASH ${HASH_FILE})
+	MESSAGE("Copying ${HASH_FILE} to ${ExternalData_OBJECT_STORES}/${HASH}")
+	FILE(RENAME ${HASH_FILE} ${ExternalData_OBJECT_STORES}/${ExternalData_LINK_CONTENT}/${HASH})
+ENDFOREACH()
diff --git a/scripts/cmake/test/README.md b/scripts/cmake/test/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7c75291c2136d79c69e6bc3ce6ef2a5998766a4
--- /dev/null
+++ b/scripts/cmake/test/README.md
@@ -0,0 +1,17 @@
+Required tools:
+
+- `time`
+- `diff`
+- `valgrind`
+- `grep`
+- `bash`
+
+Test data is searched for in `ogs6-sources/../ogs6-data`.
+
+In the build directory run `ctest` with `–-output-on-failure` and `-R` for includes and `-E` for excludes:
+
+```bash
+ctest --output-on-failure -R "MEMCHECK|VALGRIND" -E DIFF
+```
+
+Wrapper and tester are implemented in `AddTest.cmake`.
diff --git a/scripts/cmake/test/Test.cmake b/scripts/cmake/test/Test.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..083d338e82086e3c489a59d994b90187ac5ae86b
--- /dev/null
+++ b/scripts/cmake/test/Test.cmake
@@ -0,0 +1,34 @@
+# Find tools and data
+FIND_PROGRAM(DIFF_TOOL_PATH diff)
+FIND_PROGRAM(GREP_TOOL_PATH grep)
+FIND_PROGRAM(BASH_TOOL_PATH bash)
+FIND_PROGRAM(VALGRIND_TOOL_PATH valgrind)
+
+ENABLE_TESTING() # Enable CTest
+
+# See http://www.vtk.org/Wiki/CMake/Testing_With_CTest for some customization options
+SET(CTEST_CUSTOM_TESTS_IGNORE test-harness) # ignore logog test
+CONFIGURE_FILE(
+	${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/test/CTestCustom.cmake.in
+	${CMAKE_BINARY_DIR}/CTestCustom.cmake
+)
+
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/test/AddTest.cmake)
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/test/Data.cmake)
+
+IF(CMAKE_CONFIGURATION_TYPES)
+	ADD_CUSTOM_TARGET(
+		ctest
+		COMMAND ${CMAKE_CTEST_COMMAND}
+		--force-new-ctest-process --output-on-failure
+		--build-config "$<CONFIGURATION>"
+		DEPENDS data
+	)
+ELSE()
+	ADD_CUSTOM_TARGET(
+		ctest
+		COMMAND ${CMAKE_CTEST_COMMAND}
+		--force-new-ctest-process --output-on-failure
+		DEPENDS data
+	)
+ENDIF()