From 41733b935c9adc683c1a4655c2a77a0b6d9689f3 Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Tue, 30 Aug 2016 13:56:58 +0200
Subject: [PATCH] Introduce a formcompiler systemtest macro

---
 cmake/modules/DunePerftoolMacros.cmake        |   2 +
 cmake/modules/GeneratedSystemtests.cmake      |  76 ++++++++
 python/dune/perftool/options.py               |  14 +-
 test/heatequation/CMakeLists.txt              |  77 ++------
 test/heatequation/heatequation.mini           |  17 ++
 test/heatequation/heatequation_dg.mini        |  17 ++
 .../heatequation_dg_explicit.mini             |  11 --
 .../heatequation_dg_implicit.mini             |  11 --
 test/heatequation/heatequation_explicit.mini  |  15 --
 test/heatequation/heatequation_implicit.mini  |  11 --
 test/laplace/CMakeLists.txt                   |  36 +---
 test/laplace/laplace.mini                     |  11 ++
 test/laplace/laplace_dg.mini                  |  11 ++
 test/laplace/laplace_dg_numdiff.mini          |   7 -
 test/laplace/laplace_dg_symdiff.mini          |   8 -
 test/laplace/laplace_numdiff.mini             |   7 -
 test/laplace/laplace_symdiff.mini             |   7 -
 test/nonlinear/CMakeLists.txt                 |  28 +--
 ...{nonlinear_symdiff.mini => nonlinear.mini} |   0
 test/nonlinear/nonlinear_dg.mini              |   5 +
 test/poisson/CMakeLists.txt                   | 182 +++++-------------
 .../dimension-grid-variations/CMakeLists.txt  | 128 +++++-------
 .../poisson_1d_cg_interval.mini               |   5 +
 .../poisson_1d_dg_interval.mini               |   5 +
 .../poisson_2d_cg_quadrilateral.mini          |   5 +
 .../poisson_2d_cg_triangle.mini               |   5 +
 .../poisson_2d_dg_quadrilateral.mini          |   5 +
 .../poisson_2d_dg_triangle.mini               |   5 +
 .../poisson_3d_cg_hexahedron.mini             |   5 +
 .../poisson_3d_cg_tetrahedron.mini            |   5 +
 .../poisson_3d_dg_hexahedron.mini             |   5 +
 .../poisson_3d_dg_tetrahedron.mini            |   5 +
 ...sson_neumann_numdiff.mini => poisson.mini} |   6 +-
 test/poisson/poisson_cellwise_constant.mini   |   4 +
 ...g_neumann_symdiff.mini => poisson_dg.mini} |   6 +-
 test/poisson/poisson_dg_matrix_free.mini      |  16 ++
 ...g_numdiff.mini => poisson_dg_neumann.mini} |   6 +-
 test/poisson/poisson_dg_neumann_numdiff.mini  |  11 --
 .../poisson_dg_numdiff_matrix_free.mini       |  11 --
 test/poisson/poisson_dg_symdiff.mini          |  11 --
 .../poisson_dg_symdiff_matrix_free.mini       |  11 --
 test/poisson/poisson_matrix_free.mini         |  16 ++
 ...mann_symdiff.mini => poisson_neumann.mini} |   6 +-
 test/poisson/poisson_numdiff.mini             |  11 --
 test/poisson/poisson_numdiff_matrix_free.mini |  11 --
 test/poisson/poisson_symdiff.mini             |  11 --
 test/poisson/poisson_symdiff_matrix_free.mini |  11 --
 test/stokes/CMakeLists.txt                    |  73 ++-----
 ...stokes_stress_symdiff.mini => stokes.mini} |   6 +-
 ...{stokes_dg_numdiff.mini => stokes_dg.mini} |   6 +-
 test/stokes/stokes_dg_symdiff.mini            |  12 --
 test/stokes/stokes_numdiff.mini               |  12 --
 ...stokes_symdiff.mini => stokes_stress.mini} |   7 +-
 test/stokes/stokes_stress_numdiff.mini        |  12 --
 54 files changed, 414 insertions(+), 593 deletions(-)
 create mode 100644 cmake/modules/GeneratedSystemtests.cmake
 create mode 100644 test/heatequation/heatequation.mini
 create mode 100644 test/heatequation/heatequation_dg.mini
 delete mode 100644 test/heatequation/heatequation_dg_explicit.mini
 delete mode 100644 test/heatequation/heatequation_dg_implicit.mini
 delete mode 100644 test/heatequation/heatequation_explicit.mini
 delete mode 100644 test/heatequation/heatequation_implicit.mini
 create mode 100644 test/laplace/laplace.mini
 create mode 100644 test/laplace/laplace_dg.mini
 delete mode 100644 test/laplace/laplace_dg_numdiff.mini
 delete mode 100644 test/laplace/laplace_dg_symdiff.mini
 delete mode 100644 test/laplace/laplace_numdiff.mini
 delete mode 100644 test/laplace/laplace_symdiff.mini
 rename test/nonlinear/{nonlinear_symdiff.mini => nonlinear.mini} (100%)
 rename test/poisson/{poisson_neumann_numdiff.mini => poisson.mini} (54%)
 rename test/poisson/{poisson_dg_neumann_symdiff.mini => poisson_dg.mini} (54%)
 create mode 100644 test/poisson/poisson_dg_matrix_free.mini
 rename test/poisson/{poisson_dg_numdiff.mini => poisson_dg_neumann.mini} (53%)
 delete mode 100644 test/poisson/poisson_dg_neumann_numdiff.mini
 delete mode 100644 test/poisson/poisson_dg_numdiff_matrix_free.mini
 delete mode 100644 test/poisson/poisson_dg_symdiff.mini
 delete mode 100644 test/poisson/poisson_dg_symdiff_matrix_free.mini
 create mode 100644 test/poisson/poisson_matrix_free.mini
 rename test/poisson/{poisson_neumann_symdiff.mini => poisson_neumann.mini} (53%)
 delete mode 100644 test/poisson/poisson_numdiff.mini
 delete mode 100644 test/poisson/poisson_numdiff_matrix_free.mini
 delete mode 100644 test/poisson/poisson_symdiff.mini
 delete mode 100644 test/poisson/poisson_symdiff_matrix_free.mini
 rename test/stokes/{stokes_stress_symdiff.mini => stokes.mini} (58%)
 rename test/stokes/{stokes_dg_numdiff.mini => stokes_dg.mini} (64%)
 delete mode 100644 test/stokes/stokes_dg_symdiff.mini
 delete mode 100644 test/stokes/stokes_numdiff.mini
 rename test/stokes/{stokes_symdiff.mini => stokes_stress.mini} (57%)
 delete mode 100644 test/stokes/stokes_stress_numdiff.mini

diff --git a/cmake/modules/DunePerftoolMacros.cmake b/cmake/modules/DunePerftoolMacros.cmake
index 9a361de7..e2d7d1f2 100644
--- a/cmake/modules/DunePerftoolMacros.cmake
+++ b/cmake/modules/DunePerftoolMacros.cmake
@@ -115,3 +115,5 @@ function(add_generated_executable)
 
   add_dependencies(generation ${GEN_TARGET})
 endfunction()
+
+include(GeneratedSystemtests)
\ No newline at end of file
diff --git a/cmake/modules/GeneratedSystemtests.cmake b/cmake/modules/GeneratedSystemtests.cmake
new file mode 100644
index 00000000..f9c08544
--- /dev/null
+++ b/cmake/modules/GeneratedSystemtests.cmake
@@ -0,0 +1,76 @@
+# System testing for generated executables. All ideas taken from dune-testtools.
+#
+
+function(dune_add_formcompiler_system_test)
+  # parse arguments
+  set(OPTION DEBUG)
+  set(SINGLE INIFILE BASENAME SCRIPT UFLFILE)
+  set(MULTI CREATED_TARGETS)
+  cmake_parse_arguments(SYSTEMTEST "${OPTION}" "${SINGLE}" "${MULTI}" ${ARGN})
+
+  if(SYSTEMTEST_UNPARSED_ARGUMENTS)
+    message(WARNING "dune_add_system_test: Encountered unparsed arguments: This often indicates typos in named arguments")
+  endif()
+
+  # construct a string containg DEBUG to pass the debug flag to the other macros
+  set(DEBUG "")
+  if(SYSTEMTEST_DEBUG)
+    set(DEBUG "DEBUG")
+  endif()
+
+  # set a default for the script. call_executable.py just calls the executable.
+  # There, it is also possible to hook in things depending on the inifile
+  if(NOT SYSTEMTEST_SCRIPT)
+    set(SYSTEMTEST_SCRIPT dune_execute.py)
+  endif()
+
+  # we provide two signatures: either a source(s) is given or a target(s)
+  if(NOT SYSTEMTEST_UFLFILE)
+    message(FATAL_ERROR "UFLFILE must be given for dune_add_generated_system_test!")
+  endif()
+
+  # Configure a bogus file from the meta ini file. This is a trick to retrigger configuration on meta ini changes.
+  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${SYSTEMTEST_INIFILE} ${CMAKE_CURRENT_BINARY_DIR}/tmp_${SYSTEMTEST_INIFILE})
+
+  # expand the given meta ini file into the build tree
+  execute_process(COMMAND ${CMAKE_BINARY_DIR}/dune-env dune_expand_metaini.py --cmake --ini ${CMAKE_CURRENT_SOURCE_DIR}/${SYSTEMTEST_INIFILE} --dir ${CMAKE_CURRENT_BINARY_DIR} --section formcompiler
+                  OUTPUT_VARIABLE output)
+  parse_python_data(PREFIX INIINFO INPUT "${output}")
+
+  foreach(inifile ${INIINFO_names})
+    if(${INIINFO_${inifile}_suffix} STREQUAL "__empty")
+      set(tname ${SYSTEMTEST_BASENAME})
+    else()
+      set(tname ${SYSTEMTEST_BASENAME}_${INIINFO_${inifile}_suffix})
+      if(NOT TARGET ${SYSTEMTEST_BASENAME})
+        add_custom_target(${SYSTEMTEST_BASENAME})
+      endif()
+    endif()
+
+    add_generated_executable(TARGET ${tname}
+                             UFLFILE ${SYSTEMTEST_UFLFILE}
+                             FORM_COMPILER_ARGS --ini-file ${inifile}
+                             )
+
+    # Exclude the target from all
+    set_property(TARGET ${tname} PROPERTY EXCLUDE_FROM_ALL 1)
+
+    # Add dependency on the metatarget for this systemtest
+    if(NOT ${INIINFO_${inifile}_suffix} STREQUAL "__empty")
+      add_dependencies(${SYSTEMTEST_BASENAME} ${tname})
+    endif()
+
+    # and have it depend on the metatarget build_tests
+    add_dependencies(build_tests ${tname})
+
+    _add_test(NAME ${tname}
+              COMMAND ${CMAKE_BINARY_DIR}/dune-env ${SYSTEMTEST_SCRIPT}
+                    --exec ${tname}
+                    --ini "${CMAKE_CURRENT_BINARY_DIR}/${inifile}"
+                    --source ${CMAKE_CURRENT_SOURCE_DIR}
+              )
+
+    set_tests_properties(${tname} PROPERTIES SKIP_RETURN_CODE 77)
+    set_tests_properties(${tname} PROPERTIES TIMEOUT 20)
+  endforeach()
+endfunction()
\ No newline at end of file
diff --git a/python/dune/perftool/options.py b/python/dune/perftool/options.py
index 375d3ab9..5441bb47 100644
--- a/python/dune/perftool/options.py
+++ b/python/dune/perftool/options.py
@@ -66,12 +66,18 @@ def init_option_dict():
         _arguments_read = True
 
         # Read arguments from the given inifile
-        if args["ini_file"]:
+        if _option_dict["ini_file"]:
             from dune.common.parametertree.parser import parse_ini_file
-            inifile = parse_ini_file(args["ini_file"])
-            for key, value in inifile["formcompiler"]:
-                if key not in _option_dict:
+            inifile = parse_ini_file(_option_dict["ini_file"])
+            for key, value in inifile.get("formcompiler", {}).items():
+                if key not in _option_dict or _option_dict[key] is None:
                     _option_dict[key] = value
+                elif not _option_dict[key]:
+                    # As `bool("0")` is True, we need to eval bools
+                    if isinstance(_option_dict[key], bool):
+                        _option_dict[key] = eval(value)
+                    else:
+                        _option_dict[key] = type(_option_dict[key])(value)
 
 
 def set_option(key, value):
diff --git a/test/heatequation/CMakeLists.txt b/test/heatequation/CMakeLists.txt
index 9afc1a3e..7cddb801 100644
--- a/test/heatequation/CMakeLists.txt
+++ b/test/heatequation/CMakeLists.txt
@@ -1,59 +1,24 @@
-#============
-# CG implicit
-#============
-
-add_generated_executable(UFLFILE heatequation.ufl
-                         TARGET heatequation_implicit
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-l2errorsquared 1e-7
-                         )
-
-
-dune_add_system_test(TARGET heatequation_implicit
-                     INIFILE heatequation_implicit.mini
-                     )
-
-#============
-# CG explicit
-#============
-
-add_generated_executable(UFLFILE heatequation.ufl
-                         TARGET heatequation_explicit
-                         FORM_COMPILER_ARGS --explicit-time-stepping --exact-solution-expression g --compare-l2errorsquared 1e-7
-                         )
-
-
-dune_add_system_test(TARGET heatequation_explicit
-                     INIFILE heatequation_explicit.mini
-                     )
-
-#============
-# DG implicit
-#============
-
-add_generated_executable(UFLFILE heatequation_dg.ufl
-                         TARGET heatequation_dg_implicit
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-l2errorsquared 1e-5
-                         )
-
-
-dune_add_system_test(TARGET heatequation_dg_implicit
-                     INIFILE heatequation_dg_implicit.mini
-                     )
-
-#============
-# DG explicit
-#============
-
-add_generated_executable(UFLFILE heatequation_dg.ufl
-                         TARGET heatequation_dg_explicit
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-l2errorsquared 1e-5
-                         )
-
-
-dune_add_system_test(TARGET heatequation_dg_explicit
-                     INIFILE heatequation_dg_explicit.mini
-                     )
-
+#=====
+# CG
+#=====
+
+dune_add_formcompiler_system_test(UFLFILE heatequation.ufl
+                                  BASENAME heatequation
+                                  INIFILE heatequation.mini
+                                  )
+
+#=====
+# DG
+#=====
+
+dune_add_formcompiler_system_test(UFLFILE heatequation_dg.ufl
+                                  BASENAME heatequation_dg
+                                  INIFILE heatequation_dg.mini
+                                  )
+
+#====================
+# Reference solutions
+#====================
 
 # Hand written reference solutions
 add_executable(heatequation_implicit_ref heatequation_implicit_ref.cc)
diff --git a/test/heatequation/heatequation.mini b/test/heatequation/heatequation.mini
new file mode 100644
index 00000000..6087d416
--- /dev/null
+++ b/test/heatequation/heatequation.mini
@@ -0,0 +1,17 @@
+__name = heatequation_{__exec_suffix}
+__exec_suffix = implicit, explicit | expand scheme
+
+lowerleft = 0.0 0.0
+upperright = 1.0 1.0
+elements = 32 32
+elementType = simplical
+
+[wrapper.vtkcompare]
+name = {__name}
+reference = heatequation_ref
+extension = vtu
+
+[formcompiler]
+explicit_time_stepping = 0, 1 | expand scheme
+exact_solution_expression = g
+compare_l2errorsquared = 1e-7
diff --git a/test/heatequation/heatequation_dg.mini b/test/heatequation/heatequation_dg.mini
new file mode 100644
index 00000000..e2a45537
--- /dev/null
+++ b/test/heatequation/heatequation_dg.mini
@@ -0,0 +1,17 @@
+__name = heatequation_dg_{__exec_suffix}
+__exec_suffix = implicit, explicit | expand scheme
+
+lowerleft = 0.0 0.0
+upperright = 1.0 1.0
+elements = 32 32
+elementType = simplical
+
+[wrapper.vtkcompare]
+name = {__name}
+reference = heatequation_ref
+extension = vtu
+
+[formcompiler]
+explicit_time_stepping = 0, 1 | expand scheme
+exact_solution_expression = g
+compare_l2errorsquared = 1e-5
diff --git a/test/heatequation/heatequation_dg_explicit.mini b/test/heatequation/heatequation_dg_explicit.mini
deleted file mode 100644
index 7374c7b6..00000000
--- a/test/heatequation/heatequation_dg_explicit.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = heatequation_dg_explicit
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = heatequation_ref
-extension = vtu
diff --git a/test/heatequation/heatequation_dg_implicit.mini b/test/heatequation/heatequation_dg_implicit.mini
deleted file mode 100644
index 9296d825..00000000
--- a/test/heatequation/heatequation_dg_implicit.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = heatequation_dg_implicit
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = heatequation_ref
-extension = vtu
diff --git a/test/heatequation/heatequation_explicit.mini b/test/heatequation/heatequation_explicit.mini
deleted file mode 100644
index 2360fb6b..00000000
--- a/test/heatequation/heatequation_explicit.mini
+++ /dev/null
@@ -1,15 +0,0 @@
-__name = heatequation_explicit
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 8 8
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = heatequation_ref
-extension = vtu
-
-[instat]
-T = 1.0
-dt = 0.01
\ No newline at end of file
diff --git a/test/heatequation/heatequation_implicit.mini b/test/heatequation/heatequation_implicit.mini
deleted file mode 100644
index c49499f7..00000000
--- a/test/heatequation/heatequation_implicit.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = heatequation_implicit
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = heatequation_ref
-extension = vtu
diff --git a/test/laplace/CMakeLists.txt b/test/laplace/CMakeLists.txt
index d58b9c54..5ae3a857 100644
--- a/test/laplace/CMakeLists.txt
+++ b/test/laplace/CMakeLists.txt
@@ -1,34 +1,10 @@
-add_generated_executable(UFLFILE laplace.ufl
-                         TARGET laplace_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
+dune_add_formcompiler_system_test(UFLFILE laplace.ufl
+                                  BASENAME laplace
+                                  INIFILE laplace.mini)
 
-dune_add_system_test(TARGET laplace_numdiff
-                     INIFILE laplace_numdiff.mini)
-
-
-add_generated_executable(UFLFILE laplace.ufl
-                         TARGET laplace_symdiff
-                         )
-
-dune_add_system_test(TARGET laplace_symdiff
-                     INIFILE laplace_symdiff.mini)
-
-
-add_generated_executable(UFLFILE laplace_dg.ufl
-                         TARGET laplace_dg_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET laplace_dg_numdiff
-                     INIFILE laplace_dg_numdiff.mini)
-
-add_generated_executable(UFLFILE laplace_dg.ufl
-                         TARGET laplace_dg_symdiff
-                         )
-
-dune_add_system_test(TARGET laplace_dg_symdiff
-                     INIFILE laplace_dg_symdiff.mini)
+dune_add_formcompiler_system_test(UFLFILE laplace_dg.ufl
+                                  BASENAME laplace_dg
+                                  INIFILE laplace_dg.mini)
 
 add_executable(laplace_dg_ref reference_main.cc)
 set_target_properties(laplace_dg_ref PROPERTIES EXCLUDE_FROM_ALL 1)
diff --git a/test/laplace/laplace.mini b/test/laplace/laplace.mini
new file mode 100644
index 00000000..1db0ffd8
--- /dev/null
+++ b/test/laplace/laplace.mini
@@ -0,0 +1,11 @@
+__name = laplace_{__exec_suffix}
+__exec_suffix = symdiff, numdiff | expand num
+
+lowerleft = 0.0 0.0
+upperright = 1.0 1.0
+elements = 4 4
+elementType = simplical
+printmatrix = true
+
+[formcompiler]
+numerical_jacobian = 0, 1 | expand num
diff --git a/test/laplace/laplace_dg.mini b/test/laplace/laplace_dg.mini
new file mode 100644
index 00000000..04a3c3dd
--- /dev/null
+++ b/test/laplace/laplace_dg.mini
@@ -0,0 +1,11 @@
+__name = laplace_dg_{__exec_suffix}
+__exec_suffix = numdiff, symdiff | expand num
+
+lowerleft = 0.0 0.0
+upperright = 1.0 1.0
+elements = 2 2
+elementType = simplical
+printmatrix = true
+
+[formcompiler]
+numerical_jacobian = 1, 0 | expand num
diff --git a/test/laplace/laplace_dg_numdiff.mini b/test/laplace/laplace_dg_numdiff.mini
deleted file mode 100644
index ba1e0014..00000000
--- a/test/laplace/laplace_dg_numdiff.mini
+++ /dev/null
@@ -1,7 +0,0 @@
-__name = laplace_dg_numdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 2 2
-elementType = simplical
-printmatrix = true
diff --git a/test/laplace/laplace_dg_symdiff.mini b/test/laplace/laplace_dg_symdiff.mini
deleted file mode 100644
index b03b5ada..00000000
--- a/test/laplace/laplace_dg_symdiff.mini
+++ /dev/null
@@ -1,8 +0,0 @@
-__name = laplace_dg_symdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 2 2
-elementType = simplical
-printmatrix = true
-
diff --git a/test/laplace/laplace_numdiff.mini b/test/laplace/laplace_numdiff.mini
deleted file mode 100644
index 8ee48e24..00000000
--- a/test/laplace/laplace_numdiff.mini
+++ /dev/null
@@ -1,7 +0,0 @@
-__name = laplace_numdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 4 4
-elementType = simplical
-printmatrix = true
diff --git a/test/laplace/laplace_symdiff.mini b/test/laplace/laplace_symdiff.mini
deleted file mode 100644
index c0ee0dd3..00000000
--- a/test/laplace/laplace_symdiff.mini
+++ /dev/null
@@ -1,7 +0,0 @@
-__name = laplace_symdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 4 4
-elementType = simplical
-printmatrix = true
diff --git a/test/nonlinear/CMakeLists.txt b/test/nonlinear/CMakeLists.txt
index cd481d31..f5e524fd 100644
--- a/test/nonlinear/CMakeLists.txt
+++ b/test/nonlinear/CMakeLists.txt
@@ -1,21 +1,13 @@
-add_generated_executable(UFLFILE nonlinear.ufl
-                         TARGET nonlinear_symdiff
-                         FORM_COMPILER_ARGS
-                         )
-
-dune_add_system_test(TARGET nonlinear_symdiff
-                     INIFILE nonlinear_symdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-add_generated_executable(UFLFILE nonlinear_dg.ufl
-                         TARGET nonlinear_dg
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-1 --compare-l2errorsquared 1e-3
-                         )
-
-dune_add_system_test(TARGET nonlinear_dg
-                     INIFILE nonlinear_dg.mini
-                     )
+dune_add_formcompiler_system_test(UFLFILE nonlinear.ufl
+                                  BASENAME nonlinear
+                                  INIFILE nonlinear.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+dune_add_formcompiler_system_test(UFLFILE nonlinear_dg.ufl
+                                  BASENAME nonlinear_dg
+                                  INIFILE nonlinear_dg.mini
+                                  )
 
 # Add the reference code with the PDELab localoperator that produced
 # the reference vtk file
diff --git a/test/nonlinear/nonlinear_symdiff.mini b/test/nonlinear/nonlinear.mini
similarity index 100%
rename from test/nonlinear/nonlinear_symdiff.mini
rename to test/nonlinear/nonlinear.mini
diff --git a/test/nonlinear/nonlinear_dg.mini b/test/nonlinear/nonlinear_dg.mini
index d2b26e27..d79cf357 100644
--- a/test/nonlinear/nonlinear_dg.mini
+++ b/test/nonlinear/nonlinear_dg.mini
@@ -9,3 +9,8 @@ elementType = simplical
 name = {__name}
 reference = nonlinear_dg
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-1
+compare_l2errorsquared = 1e-3
diff --git a/test/poisson/CMakeLists.txt b/test/poisson/CMakeLists.txt
index 2bc18c5c..4455f6ca 100644
--- a/test/poisson/CMakeLists.txt
+++ b/test/poisson/CMakeLists.txt
@@ -6,141 +6,53 @@ dune_symlink_to_source_files(FILES poisson_ref.vtu
                              )
 
 
-# 1. Poisson Test Case: source f, bc g + numerical differentiation
-add_generated_executable(UFLFILE poisson.ufl
-                         TARGET poisson_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET poisson_numdiff
-                     INIFILE poisson_numdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-
-# 2. Poisson Test Case: source f, bc g + symbolic differentiation
-add_generated_executable(UFLFILE poisson.ufl
-                         TARGET poisson_symdiff
-                         )
-
-dune_add_system_test(TARGET poisson_symdiff
-                     INIFILE poisson_symdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-# 3. Poisson Test Case: source f, mixed neumann/dirichlet boundary + numerical differentiation
-add_generated_executable(UFLFILE poisson_neumann.ufl
-                         TARGET poisson_neumann_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET poisson_neumann_numdiff
-                     INIFILE poisson_neumann_numdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-# 4. Poisson Test Case: source f, mixed neumann/dirichlet boundary + symbolic differentiation
-add_generated_executable(UFLFILE poisson_neumann.ufl
-                         TARGET poisson_neumann_symdiff
-                         )
-
-dune_add_system_test(TARGET poisson_neumann_symdiff
-                     INIFILE poisson_neumann_symdiff.mini
-                     )
-
-# 5. Poisson Test Case: DG, f + pure dirichlet, numeric differentiation
-add_generated_executable(UFLFILE poisson_dg.ufl
-                         TARGET poisson_dg_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET poisson_dg_numdiff
-                     INIFILE poisson_dg_numdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-# 6. Poisson Test Case: DG, f + pure dirichlet, symbolic differentiation
-add_generated_executable(UFLFILE poisson_dg.ufl
-                         TARGET poisson_dg_symdiff
-                         )
-
-dune_add_system_test(TARGET poisson_dg_symdiff
-                     INIFILE poisson_dg_symdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-# 7. Poisson Test Case: DG, mixed bc, numeric differentiation
-add_generated_executable(UFLFILE poisson_dg_neumann.ufl
-                         TARGET poisson_dg_neumann_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET poisson_dg_neumann_numdiff
-                     INIFILE poisson_dg_neumann_numdiff.mini
-                     )
-
-# 8. Poisson Test Case: DG, mixed bc, symbolic differentiation
-add_generated_executable(UFLFILE poisson_dg_neumann.ufl
-                         TARGET poisson_dg_neumann_symdiff
-                         )
-
-dune_add_system_test(TARGET poisson_dg_neumann_symdiff
-                     INIFILE poisson_dg_neumann_symdiff.mini
-                     )
-
-# 9. Poisson Test Case: matrix free, numeric differentiation
-add_generated_executable(UFLFILE poisson.ufl
-                         TARGET poisson_numdiff_matrix_free
-                         FORM_COMPILER_ARGS --numerical-jacobian --matrix-free
-                         )
-
-dune_add_system_test(TARGET poisson_numdiff_matrix_free
-                     INIFILE poisson_numdiff_matrix_free.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-# 10. Poisson Test Case: matrix free, symbolic differentiation
-add_generated_executable(UFLFILE poisson.ufl
-                         TARGET poisson_symdiff_matrix_free
-                         FORM_COMPILER_ARGS --matrix-free
-                         )
-
-dune_add_system_test(TARGET poisson_symdiff_matrix_free
-                     INIFILE poisson_symdiff_matrix_free.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-# # 11. Poisson Test Case: dg, matrix free, numeric differentiation
-# add_generated_executable(UFLFILE poisson_dg.ufl
-#                          TARGET poisson_dg_numdiff_matrix_free
-#                          FORM_COMPILER_ARGS --numerical-jacobian --matrix-free
-#                          )
-
-# dune_add_system_test(TARGET poisson_dg_numdiff_matrix_free
-#                      INIFILE poisson_dg_numdiff_matrix_free.mini
-#                      SCRIPT dune_vtkcompare.py
-#                      )
-
-# # 12. Poisson Test Case: dg, matrix free, symbolic differentiation
-# add_generated_executable(UFLFILE poisson_dg.ufl
-#                          TARGET poisson_dg_symdiff_matrix_free
-#                          FORM_COMPILER_ARGS --matrix-free
-#                          )
-
-# dune_add_system_test(TARGET poisson_dg_symdiff_matrix_free
-#                      INIFILE poisson_dg_symdiff_matrix_free.mini
-#                      SCRIPT dune_vtkcompare.py
-#                      )
-
-
-# 13. Poisson Test Case: test constant expressions
-add_generated_executable(UFLFILE poisson_cellwise_constant.ufl
-                         TARGET poisson_cellwise_constant
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-l2errorsquared 1e-6
-                         )
-dune_add_system_test(TARGET poisson_cellwise_constant
-                     INIFILE poisson_cellwise_constant.mini
-                     )
+# 1. Poisson Test Case: source f, bc g
+dune_add_formcompiler_system_test(UFLFILE poisson.ufl
+                                  BASENAME poisson
+                                  INIFILE poisson.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+# 2. Poisson Test Case: source f, mixed neumann/dirichlet boundary
+dune_add_formcompiler_system_test(UFLFILE poisson_neumann.ufl
+                                  BASENAME poisson_neumann
+                                  INIFILE poisson_neumann.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+# 3. Poisson Test Case: DG, f + pure dirichlet
+dune_add_formcompiler_system_test(UFLFILE poisson_dg.ufl
+                                  BASENAME poisson_dg
+                                  INIFILE poisson_dg.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+# 4. Poisson Test Case: DG, mixed bc
+dune_add_formcompiler_system_test(UFLFILE poisson_dg_neumann.ufl
+                                  BASENAME poisson_dg_neumann
+                                  INIFILE poisson_dg_neumann.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+# 5. Poisson Test Case: matrix free
+dune_add_formcompiler_system_test(UFLFILE poisson.ufl
+                                  BASENAME poisson_matrix_free
+                                  INIFILE poisson_matrix_free.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+# 6. Poisson Test Case: DG, matrix free
+#dune_add_formcompiler_system_test(UFLFILE poisson_dg.ufl
+#                                  BASENAME poisson_dg_matrix_free
+#                                  INIFILE poisson_dg_matrix_free.mini
+#                                  SCRIPT dune_vtkcompare.py
+#                                  )
+
+# 7. Poisson Test Case: test constant expressions
+dune_add_formcompiler_system_test(UFLFILE poisson_cellwise_constant.ufl
+                                  BASENAME poisson_cellwise_constant
+                                  INIFILE poisson_cellwise_constant.mini
+                                  )
 
 # Add the reference code with the PDELab localoperator that produced
 # the reference vtk file
diff --git a/test/poisson/dimension-grid-variations/CMakeLists.txt b/test/poisson/dimension-grid-variations/CMakeLists.txt
index 9f2229d0..9ef05b56 100644
--- a/test/poisson/dimension-grid-variations/CMakeLists.txt
+++ b/test/poisson/dimension-grid-variations/CMakeLists.txt
@@ -2,102 +2,60 @@
 # 1D Tests: cg/dg
 #================
 
-add_generated_executable(UFLFILE poisson_1d_cg_interval.ufl
-                         TARGET poisson_1d_cg_interval
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-14 --compare-l2errorsquared 1e-7
-                         )
-
-dune_add_system_test(TARGET poisson_1d_cg_interval
-                     INIFILE poisson_1d_cg_interval.mini
-                     )
-
-add_generated_executable(UFLFILE poisson_1d_dg_interval.ufl
-                         TARGET poisson_1d_dg_interval
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-2 --compare-l2errorsquared 1e-5
-                         )
-
-dune_add_system_test(TARGET poisson_1d_dg_interval
-                     INIFILE poisson_1d_dg_interval.mini
-                     )
+dune_add_formcompiler_system_test(UFLFILE poisson_1d_cg_interval.ufl
+                                  BASENAME poisson_1d_cg_interval
+                                  INIFILE poisson_1d_cg_interval.mini
+                                  )
 
+dune_add_formcompiler_system_test(UFLFILE poisson_1d_dg_interval.ufl
+                                  BASENAME poisson_1d_dg_interval
+                                  INIFILE poisson_1d_dg_interval.mini
+                                  )
 
 #========================================
 # 2D Tests: cg/dg, triangle/quadrilateral
 #========================================
 
-add_generated_executable(UFLFILE poisson_2d_cg_triangle.ufl
-                         TARGET poisson_2d_cg_triangle
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-14 --compare-l2errorsquared 1e-6
-                         )
-
-dune_add_system_test(TARGET poisson_2d_cg_triangle
-                     INIFILE poisson_2d_cg_triangle.mini
-                     )
-
-add_generated_executable(UFLFILE poisson_2d_dg_triangle.ufl
-                         TARGET poisson_2d_dg_triangle
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-1 --compare-l2errorsquared 1e-4
-                         )
-
-dune_add_system_test(TARGET poisson_2d_dg_triangle
-                     INIFILE poisson_2d_dg_triangle.mini
-                     )
-
-add_generated_executable(UFLFILE poisson_2d_cg_quadrilateral.ufl
-                         TARGET poisson_2d_cg_quadrilateral
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-14 --compare-l2errorsquared 1e-6
-                         )
-
-dune_add_system_test(TARGET poisson_2d_cg_quadrilateral
-                     INIFILE poisson_2d_cg_quadrilateral.mini
-                     )
+dune_add_formcompiler_system_test(UFLFILE poisson_2d_cg_triangle.ufl
+                                  BASENAME poisson_2d_cg_triangle
+                                  INIFILE poisson_2d_cg_triangle.mini
+                                  )
 
-add_generated_executable(UFLFILE poisson_2d_dg_quadrilateral.ufl
-                         TARGET poisson_2d_dg_quadrilateral
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-1 --compare-l2errorsquared 1e-4
-                         )
+dune_add_formcompiler_system_test(UFLFILE poisson_2d_dg_triangle.ufl
+                                  BASENAME poisson_2d_dg_triangle
+                                  INIFILE poisson_2d_dg_triangle.mini
+                                  )
 
-dune_add_system_test(TARGET poisson_2d_dg_quadrilateral
-                     INIFILE poisson_2d_dg_quadrilateral.mini
-                     )
+dune_add_formcompiler_system_test(UFLFILE poisson_2d_cg_quadrilateral.ufl
+                                  BASENAME poisson_2d_cg_quadrilateral
+                                  INIFILE poisson_2d_cg_quadrilateral.mini
+                                  )
 
+dune_add_formcompiler_system_test(UFLFILE poisson_2d_dg_quadrilateral.ufl
+                                  BASENAME poisson_2d_dg_quadrilateral
+                                  INIFILE poisson_2d_dg_quadrilateral.mini
+                                  )
 
 #========================================
 # 3D Tests: cg/dg, tetrahedron/hexahedron
 #========================================
 
-add_generated_executable(UFLFILE poisson_3d_cg_tetrahedron.ufl
-                         TARGET poisson_3d_cg_tetrahedron
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-14 --compare-l2errorsquared 1e-4
-                         )
-
-dune_add_system_test(TARGET poisson_3d_cg_tetrahedron
-                     INIFILE poisson_3d_cg_tetrahedron.mini
-                     )
-
-add_generated_executable(UFLFILE poisson_3d_dg_tetrahedron.ufl
-                         TARGET poisson_3d_dg_tetrahedron
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-2 --compare-l2errorsquared 1e-4
-                         )
-
-dune_add_system_test(TARGET poisson_3d_dg_tetrahedron
-                     INIFILE poisson_3d_dg_tetrahedron.mini
-                     )
-
-add_generated_executable(UFLFILE poisson_3d_cg_hexahedron.ufl
-                         TARGET poisson_3d_cg_hexahedron
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1e-14 --compare-l2errorsquared 1e-4
-                         )
-
-dune_add_system_test(TARGET poisson_3d_cg_hexahedron
-                     INIFILE poisson_3d_cg_hexahedron.mini
-                     )
-
-add_generated_executable(UFLFILE poisson_3d_dg_hexahedron.ufl
-                         TARGET poisson_3d_dg_hexahedron
-                         FORM_COMPILER_ARGS --exact-solution-expression g --compare-dofs 1 --compare-l2errorsquared 1e-3
-                         )
-
-dune_add_system_test(TARGET poisson_3d_dg_hexahedron
-                     INIFILE poisson_3d_dg_hexahedron.mini
-                     )
+dune_add_formcompiler_system_test(UFLFILE poisson_3d_cg_tetrahedron.ufl
+                                  BASENAME poisson_3d_cg_tetrahedron
+                                  INIFILE poisson_3d_cg_tetrahedron.mini
+                                  )
+
+dune_add_formcompiler_system_test(UFLFILE poisson_3d_dg_tetrahedron.ufl
+                                  BASENAME poisson_3d_dg_tetrahedron
+                                  INIFILE poisson_3d_dg_tetrahedron.mini
+                                  )
+
+dune_add_formcompiler_system_test(UFLFILE poisson_3d_cg_hexahedron.ufl
+                                  BASENAME poisson_3d_cg_hexahedron
+                                  INIFILE poisson_3d_cg_hexahedron.mini
+                                  )
+
+dune_add_formcompiler_system_test(UFLFILE poisson_3d_dg_hexahedron.ufl
+                                  BASENAME poisson_3d_dg_hexahedron
+                                  INIFILE poisson_3d_dg_hexahedron.mini
+                                  )
diff --git a/test/poisson/dimension-grid-variations/poisson_1d_cg_interval.mini b/test/poisson/dimension-grid-variations/poisson_1d_cg_interval.mini
index 016ce0b6..a3680f2c 100644
--- a/test/poisson/dimension-grid-variations/poisson_1d_cg_interval.mini
+++ b/test/poisson/dimension-grid-variations/poisson_1d_cg_interval.mini
@@ -6,3 +6,8 @@ extension = 1.
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-14
+compare_l2errorsquared = 1e-7
diff --git a/test/poisson/dimension-grid-variations/poisson_1d_dg_interval.mini b/test/poisson/dimension-grid-variations/poisson_1d_dg_interval.mini
index f053c732..c1f1e96a 100644
--- a/test/poisson/dimension-grid-variations/poisson_1d_dg_interval.mini
+++ b/test/poisson/dimension-grid-variations/poisson_1d_dg_interval.mini
@@ -6,3 +6,8 @@ extension = 1.
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-2
+compare_l2errorsquared = 1e-5
diff --git a/test/poisson/dimension-grid-variations/poisson_2d_cg_quadrilateral.mini b/test/poisson/dimension-grid-variations/poisson_2d_cg_quadrilateral.mini
index d0ede694..8f5e193a 100644
--- a/test/poisson/dimension-grid-variations/poisson_2d_cg_quadrilateral.mini
+++ b/test/poisson/dimension-grid-variations/poisson_2d_cg_quadrilateral.mini
@@ -6,3 +6,8 @@ extension = 1. 1.
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-14
+compare_l2errorsquared = 1e-6
diff --git a/test/poisson/dimension-grid-variations/poisson_2d_cg_triangle.mini b/test/poisson/dimension-grid-variations/poisson_2d_cg_triangle.mini
index bf7adf0a..3ba74596 100644
--- a/test/poisson/dimension-grid-variations/poisson_2d_cg_triangle.mini
+++ b/test/poisson/dimension-grid-variations/poisson_2d_cg_triangle.mini
@@ -8,3 +8,8 @@ elementType = simplical
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-14
+compare_l2errorsquared = 1e-6
diff --git a/test/poisson/dimension-grid-variations/poisson_2d_dg_quadrilateral.mini b/test/poisson/dimension-grid-variations/poisson_2d_dg_quadrilateral.mini
index 4bea6834..ca35eccb 100644
--- a/test/poisson/dimension-grid-variations/poisson_2d_dg_quadrilateral.mini
+++ b/test/poisson/dimension-grid-variations/poisson_2d_dg_quadrilateral.mini
@@ -6,3 +6,8 @@ extension = 1. 1.
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-1
+compare_l2errorsquared = 1e-4
diff --git a/test/poisson/dimension-grid-variations/poisson_2d_dg_triangle.mini b/test/poisson/dimension-grid-variations/poisson_2d_dg_triangle.mini
index dedd6a3f..94fcda9c 100644
--- a/test/poisson/dimension-grid-variations/poisson_2d_dg_triangle.mini
+++ b/test/poisson/dimension-grid-variations/poisson_2d_dg_triangle.mini
@@ -8,3 +8,8 @@ elementType = simplical
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-1
+compare_l2errorsquared = 1e-4
diff --git a/test/poisson/dimension-grid-variations/poisson_3d_cg_hexahedron.mini b/test/poisson/dimension-grid-variations/poisson_3d_cg_hexahedron.mini
index ee7893ca..ca47f1c9 100644
--- a/test/poisson/dimension-grid-variations/poisson_3d_cg_hexahedron.mini
+++ b/test/poisson/dimension-grid-variations/poisson_3d_cg_hexahedron.mini
@@ -6,3 +6,8 @@ extension = 1. 1. 1.
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-14
+compare_l2errorsquared = 1e-4
diff --git a/test/poisson/dimension-grid-variations/poisson_3d_cg_tetrahedron.mini b/test/poisson/dimension-grid-variations/poisson_3d_cg_tetrahedron.mini
index 6a788f16..178cd983 100644
--- a/test/poisson/dimension-grid-variations/poisson_3d_cg_tetrahedron.mini
+++ b/test/poisson/dimension-grid-variations/poisson_3d_cg_tetrahedron.mini
@@ -8,3 +8,8 @@ elementType = simplical
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-14
+compare_l2errorsquared = 1e-4
diff --git a/test/poisson/dimension-grid-variations/poisson_3d_dg_hexahedron.mini b/test/poisson/dimension-grid-variations/poisson_3d_dg_hexahedron.mini
index 82c8faec..4c195f8e 100644
--- a/test/poisson/dimension-grid-variations/poisson_3d_dg_hexahedron.mini
+++ b/test/poisson/dimension-grid-variations/poisson_3d_dg_hexahedron.mini
@@ -6,3 +6,8 @@ extension = 1. 1. 1.
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1
+compare_l2errorsquared = 1e-3
diff --git a/test/poisson/dimension-grid-variations/poisson_3d_dg_tetrahedron.mini b/test/poisson/dimension-grid-variations/poisson_3d_dg_tetrahedron.mini
index 16f1adaf..0d497ae5 100644
--- a/test/poisson/dimension-grid-variations/poisson_3d_dg_tetrahedron.mini
+++ b/test/poisson/dimension-grid-variations/poisson_3d_dg_tetrahedron.mini
@@ -8,3 +8,8 @@ elementType = simplical
 [wrapper.vtkcompare]
 name = {__name}
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_dofs = 1e-2
+compare_l2errorsquared = 1e-4
diff --git a/test/poisson/poisson_neumann_numdiff.mini b/test/poisson/poisson.mini
similarity index 54%
rename from test/poisson/poisson_neumann_numdiff.mini
rename to test/poisson/poisson.mini
index 5c779a14..eb8c175b 100644
--- a/test/poisson/poisson_neumann_numdiff.mini
+++ b/test/poisson/poisson.mini
@@ -1,4 +1,5 @@
-__name = poisson_neumann_numdiff
+__name = poisson_{__exec_suffix}
+__exec_suffix = numdiff, symdiff | expand num
 
 lowerleft = 0.0 0.0
 upperright = 1.0 1.0
@@ -9,3 +10,6 @@ elementType = simplical
 name = {__name}
 reference = poisson_ref
 extension = vtu
+
+[formcompiler]
+numerical_jacobian = 1, 0 | expand num
diff --git a/test/poisson/poisson_cellwise_constant.mini b/test/poisson/poisson_cellwise_constant.mini
index 5b1ceb7d..86827ea4 100644
--- a/test/poisson/poisson_cellwise_constant.mini
+++ b/test/poisson/poisson_cellwise_constant.mini
@@ -9,3 +9,7 @@ elementType = simplical
 name = {__name}
 reference = poisson_ref
 extension = vtu
+
+[formcompiler]
+exact_solution_expression = g
+compare_l2errorsquared = 1e-6
diff --git a/test/poisson/poisson_dg_neumann_symdiff.mini b/test/poisson/poisson_dg.mini
similarity index 54%
rename from test/poisson/poisson_dg_neumann_symdiff.mini
rename to test/poisson/poisson_dg.mini
index 4dd175dd..fb3c992b 100644
--- a/test/poisson/poisson_dg_neumann_symdiff.mini
+++ b/test/poisson/poisson_dg.mini
@@ -1,4 +1,5 @@
-__name = poisson_dg_neumann_symdiff
+__name = poisson_dg_{__exec_suffix}
+__exec_suffix = numdiff, symdiff | expand num
 
 lowerleft = 0.0 0.0
 upperright = 1.0 1.0
@@ -9,3 +10,6 @@ elementType = simplical
 name = {__name}
 reference = poisson_dg_ref
 extension = vtu
+
+[formcompiler]
+numerical_jacobian = 1, 0 | expand num
diff --git a/test/poisson/poisson_dg_matrix_free.mini b/test/poisson/poisson_dg_matrix_free.mini
new file mode 100644
index 00000000..e07d58b9
--- /dev/null
+++ b/test/poisson/poisson_dg_matrix_free.mini
@@ -0,0 +1,16 @@
+__name = poisson_dg_matrix_free_{__exec_suffix}
+__exec_suffix = numdiff, symdiff | expand num
+
+lowerleft = 0.0 0.0
+upperright = 1.0 1.0
+elements = 32 32
+elementType = simplical
+
+[wrapper.vtkcompare]
+name = {__name}
+reference = poisson_dg_ref
+extension = vtu
+
+[formcompiler]
+numerical_jacobian = 1, 0 | expand num
+matrix_free = 1
diff --git a/test/poisson/poisson_dg_numdiff.mini b/test/poisson/poisson_dg_neumann.mini
similarity index 53%
rename from test/poisson/poisson_dg_numdiff.mini
rename to test/poisson/poisson_dg_neumann.mini
index 146955e8..41a09182 100644
--- a/test/poisson/poisson_dg_numdiff.mini
+++ b/test/poisson/poisson_dg_neumann.mini
@@ -1,4 +1,5 @@
-__name = poisson_dg_numdiff
+__name = poisson_dg_neumann_{__exec_suffix}
+__exec_suffix = numdiff, symdiff | expand num
 
 lowerleft = 0.0 0.0
 upperright = 1.0 1.0
@@ -9,3 +10,6 @@ elementType = simplical
 name = {__name}
 reference = poisson_dg_ref
 extension = vtu
+
+[formcompiler]
+numerical_jacobian = 1, 0 | expand num
diff --git a/test/poisson/poisson_dg_neumann_numdiff.mini b/test/poisson/poisson_dg_neumann_numdiff.mini
deleted file mode 100644
index b0847a74..00000000
--- a/test/poisson/poisson_dg_neumann_numdiff.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_dg_neumann_numdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_dg_ref
-extension = vtu
diff --git a/test/poisson/poisson_dg_numdiff_matrix_free.mini b/test/poisson/poisson_dg_numdiff_matrix_free.mini
deleted file mode 100644
index b45d4a86..00000000
--- a/test/poisson/poisson_dg_numdiff_matrix_free.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_dg_numdiff_matrix_free
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_dg_ref
-extension = vtu
diff --git a/test/poisson/poisson_dg_symdiff.mini b/test/poisson/poisson_dg_symdiff.mini
deleted file mode 100644
index fe696b11..00000000
--- a/test/poisson/poisson_dg_symdiff.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_dg_symdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_dg_ref
-extension = vtu
diff --git a/test/poisson/poisson_dg_symdiff_matrix_free.mini b/test/poisson/poisson_dg_symdiff_matrix_free.mini
deleted file mode 100644
index c3fcaf7f..00000000
--- a/test/poisson/poisson_dg_symdiff_matrix_free.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_dg_symdiff_matrix_free
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_dg_ref
-extension = vtu
diff --git a/test/poisson/poisson_matrix_free.mini b/test/poisson/poisson_matrix_free.mini
new file mode 100644
index 00000000..6e58960a
--- /dev/null
+++ b/test/poisson/poisson_matrix_free.mini
@@ -0,0 +1,16 @@
+__name = poisson_matrix_free_{__exec_suffix}
+__exec_suffix = numdiff, symdiff | expand num
+
+lowerleft = 0.0 0.0
+upperright = 1.0 1.0
+elements = 32 32
+elementType = simplical
+
+[wrapper.vtkcompare]
+name = {__name}
+reference = poisson_ref
+extension = vtu
+
+[formcompiler]
+numerical_jacobian = 1, 0 | expand num
+matrix_free = 1
diff --git a/test/poisson/poisson_neumann_symdiff.mini b/test/poisson/poisson_neumann.mini
similarity index 53%
rename from test/poisson/poisson_neumann_symdiff.mini
rename to test/poisson/poisson_neumann.mini
index 8e2c2fb0..d5cb21ff 100644
--- a/test/poisson/poisson_neumann_symdiff.mini
+++ b/test/poisson/poisson_neumann.mini
@@ -1,4 +1,5 @@
-__name = poisson_neumann_symdiff
+__name = poisson_neumann_{__exec_suffix}
+__exec_suffix = numdiff, symdiff | expand num
 
 lowerleft = 0.0 0.0
 upperright = 1.0 1.0
@@ -9,3 +10,6 @@ elementType = simplical
 name = {__name}
 reference = poisson_ref
 extension = vtu
+
+[formcompiler]
+numerical_jacobian = 1, 0 | expand num
diff --git a/test/poisson/poisson_numdiff.mini b/test/poisson/poisson_numdiff.mini
deleted file mode 100644
index 6d450718..00000000
--- a/test/poisson/poisson_numdiff.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_numdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_ref
-extension = vtu
diff --git a/test/poisson/poisson_numdiff_matrix_free.mini b/test/poisson/poisson_numdiff_matrix_free.mini
deleted file mode 100644
index 4662d838..00000000
--- a/test/poisson/poisson_numdiff_matrix_free.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_numdiff_matrix_free
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_ref
-extension = vtu
diff --git a/test/poisson/poisson_symdiff.mini b/test/poisson/poisson_symdiff.mini
deleted file mode 100644
index e3fa2f3f..00000000
--- a/test/poisson/poisson_symdiff.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_symdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_ref
-extension = vtu
diff --git a/test/poisson/poisson_symdiff_matrix_free.mini b/test/poisson/poisson_symdiff_matrix_free.mini
deleted file mode 100644
index 8d288ef3..00000000
--- a/test/poisson/poisson_symdiff_matrix_free.mini
+++ /dev/null
@@ -1,11 +0,0 @@
-__name = poisson_symdiff_matrix_free
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 32 32
-elementType = simplical
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = poisson_ref
-extension = vtu
diff --git a/test/stokes/CMakeLists.txt b/test/stokes/CMakeLists.txt
index 57cf3d01..8d6fa96d 100644
--- a/test/stokes/CMakeLists.txt
+++ b/test/stokes/CMakeLists.txt
@@ -2,59 +2,20 @@ dune_symlink_to_source_files(FILES hagenpoiseuille_ref.vtu
                                    hagenpoiseuille_dg_ref.vtu
                              )
 
-add_generated_executable(UFLFILE stokes.ufl
-                         TARGET stokes_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET stokes_numdiff
-                     INIFILE stokes_numdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-add_generated_executable(UFLFILE stokes.ufl
-                         TARGET stokes_symdiff
-                         )
-
-dune_add_system_test(TARGET stokes_symdiff
-                     INIFILE stokes_symdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-add_generated_executable(UFLFILE stokes_dg.ufl
-                         TARGET stokes_dg_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET stokes_dg_numdiff
-                     INIFILE stokes_dg_numdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-add_generated_executable(UFLFILE stokes_dg.ufl
-                         TARGET stokes_dg_symdiff
-                         )
-
-dune_add_system_test(TARGET stokes_dg_symdiff
-                     INIFILE stokes_dg_symdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-add_generated_executable(UFLFILE stokes_stress.ufl
-                         TARGET stokes_stress_numdiff
-                         FORM_COMPILER_ARGS --numerical-jacobian
-                         )
-
-dune_add_system_test(TARGET stokes_stress_numdiff
-                     INIFILE stokes_stress_numdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
-
-add_generated_executable(UFLFILE stokes_stress.ufl
-                         TARGET stokes_stress_symdiff
-                         )
-
-dune_add_system_test(TARGET stokes_stress_symdiff
-                     INIFILE stokes_stress_symdiff.mini
-                     SCRIPT dune_vtkcompare.py
-                     )
+dune_add_formcompiler_system_test(UFLFILE stokes.ufl
+                                  BASENAME stokes
+                                  INIFILE stokes.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+dune_add_formcompiler_system_test(UFLFILE stokes_dg.ufl
+                                  BASENAME stokes_dg
+                                  INIFILE stokes_dg.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
+
+dune_add_formcompiler_system_test(UFLFILE stokes_stress.ufl
+                                  BASENAME stokes_stress
+                                  INIFILE stokes_stress.mini
+                                  SCRIPT dune_vtkcompare.py
+                                  )
diff --git a/test/stokes/stokes_stress_symdiff.mini b/test/stokes/stokes.mini
similarity index 58%
rename from test/stokes/stokes_stress_symdiff.mini
rename to test/stokes/stokes.mini
index 5fdeccef..23a79329 100644
--- a/test/stokes/stokes_stress_symdiff.mini
+++ b/test/stokes/stokes.mini
@@ -1,4 +1,5 @@
-__name = stokes_stress_symdiff
+__name = stokes_{__exec_suffix}
+__exec_suffix = symdiff, numdiff | expand num
 
 lowerleft = 0.0 0.0
 upperright = 1.0 1.0
@@ -10,3 +11,6 @@ printmatrix = false
 name = {__name}
 reference = hagenpoiseuille_ref
 extension = vtu
+
+[formcompiler]
+numerical_jacobian = 0, 1 | expand num
diff --git a/test/stokes/stokes_dg_numdiff.mini b/test/stokes/stokes_dg.mini
similarity index 64%
rename from test/stokes/stokes_dg_numdiff.mini
rename to test/stokes/stokes_dg.mini
index 9b6a05f1..6448f4f5 100644
--- a/test/stokes/stokes_dg_numdiff.mini
+++ b/test/stokes/stokes_dg.mini
@@ -1,4 +1,5 @@
-__name = stokes_dg_numdiff
+__name = stokes_dg_{__exec_suffix}
+__exec_suffix = symdiff, numdiff | expand num
 
 lowerleft = 0.0 0.0
 upperright = 1.0 1.0
@@ -12,3 +13,6 @@ reference = hagenpoiseuille_dg_ref
 extension = vtu
 zeroThreshold.data_0 = 1e-6
 zeroThreshold.data_1 = 1e-6
+
+[formcompiler]
+numerical_jacobian = 0, 1 | expand num
diff --git a/test/stokes/stokes_dg_symdiff.mini b/test/stokes/stokes_dg_symdiff.mini
deleted file mode 100644
index 42767d55..00000000
--- a/test/stokes/stokes_dg_symdiff.mini
+++ /dev/null
@@ -1,12 +0,0 @@
-__name = stokes_dg_symdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 16 16
-elementType = simplical
-printmatrix = false
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = hagenpoiseuille_dg_ref
-extension = vtu
diff --git a/test/stokes/stokes_numdiff.mini b/test/stokes/stokes_numdiff.mini
deleted file mode 100644
index 0f52d135..00000000
--- a/test/stokes/stokes_numdiff.mini
+++ /dev/null
@@ -1,12 +0,0 @@
-__name = stokes_numdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 16 16
-elementType = simplical
-printmatrix = false
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = hagenpoiseuille_ref
-extension = vtu
diff --git a/test/stokes/stokes_symdiff.mini b/test/stokes/stokes_stress.mini
similarity index 57%
rename from test/stokes/stokes_symdiff.mini
rename to test/stokes/stokes_stress.mini
index c5b554e8..642ef6d2 100644
--- a/test/stokes/stokes_symdiff.mini
+++ b/test/stokes/stokes_stress.mini
@@ -1,4 +1,5 @@
-__name = stokes_symdiff
+__name = stokes_stress_{__exec_suffix}
+__exec_suffix = symdiff, numdiff | expand num
 
 lowerleft = 0.0 0.0
 upperright = 1.0 1.0
@@ -7,7 +8,9 @@ elementType = simplical
 printmatrix = false
 
 [wrapper.vtkcompare]
-zeroThreshold.data_0 = 1e-7
 name = {__name}
 reference = hagenpoiseuille_ref
 extension = vtu
+
+[formcompiler]
+numerical_jacobian = 0, 1 | expand num
diff --git a/test/stokes/stokes_stress_numdiff.mini b/test/stokes/stokes_stress_numdiff.mini
deleted file mode 100644
index 06431fc3..00000000
--- a/test/stokes/stokes_stress_numdiff.mini
+++ /dev/null
@@ -1,12 +0,0 @@
-__name = stokes_stress_numdiff
-
-lowerleft = 0.0 0.0
-upperright = 1.0 1.0
-elements = 16 16
-elementType = simplical
-printmatrix = false
-
-[wrapper.vtkcompare]
-name = {__name}
-reference = hagenpoiseuille_ref
-extension = vtu
-- 
GitLab