diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5d8f37f9a173b9a61ccffbb611da8ba909d6fac6..e65636322528cc52687b64cd0acb4155d893ea93 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,3 +7,22 @@ include:
 before_script:
   - . /duneci/bin/duneci-init-job
   - duneci-install-module https://gitlab.dune-project.org/core/dune-common.git
+
+debian-11-gcc-9-17-python:
+  image: duneci/debian:11
+  script: duneci-standard-test
+  variables:
+    DUNECI_TOOLCHAIN:   gcc-9-17
+    # so we need some variables to build the dune-py module during execution of the first python test:
+    # we need to find the dune mdoule
+    DUNE_CONTROL_PATH:  /duneci/modules:$CI_PROJECT_DIR
+    # the position for the dune-py module
+    DUNE_PY_DIR:        /duneci/modules/dune-py
+    # during dune-py build this variable is used - do know a way to access
+    # the CMAKE_FLAGS used to build the modules...
+    DUNE_CMAKE_FLAGS:   "CC=gcc-9 CXX=g++-9 -DCMAKE_CXX_FLAGS='-std=c++17 -O2 -g -Wall -fdiagnostics-color=always' -DDUNE_ENABLE_PYTHONBINDINGS=ON -DDUNE_MAX_TEST_CORES=4 -DBUILD_SHARED_LIBS=TRUE -DDUNE_PYTHON_INSTALL_LOCATION=none -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_DISABLE_FIND_PACKAGE_LATEX=TRUE -DCMAKE_DISABLE_FIND_PACKAGE_Alberta=TRUE -DCMAKE_DISABLE_FIND_PACKAGE_Vc=TRUE -DCMAKE_DISABLE_DOCUMENTATION=TRUE"
+    # cmake flags we use for all dune moudle - important is that build shared libs is set (need some better way of doing this)
+    DUNECI_CMAKE_FLAGS: $DUNE_CMAKE_FLAGS
+    # finally set the python path to all modules
+    PYTHONPATH:         /duneci/modules/dune-common/build-cmake/python:/duneci/modules/dune-geometry/build-cmake/python:$CI_PROJECT_DIR/build-cmake/python
+  tags: [duneci]
diff --git a/dune/CMakeLists.txt b/dune/CMakeLists.txt
index 86feda5022f7e264e1ac0c8f91a7ddc42e0452ab..3b7d414bda4350bdf24bb5332abc14970eaff750 100644
--- a/dune/CMakeLists.txt
+++ b/dune/CMakeLists.txt
@@ -1,2 +1,5 @@
 add_subdirectory(geometry)
-add_subdirectory(python)
+# if Python bindings are enabled, include necessary sub directories.
+if( DUNE_ENABLE_PYTHONBINDINGS )
+  add_subdirectory("python")
+endif()
diff --git a/dune/python/CMakeLists.txt b/dune/python/CMakeLists.txt
index 933ff889d1110658837e180f86b2aaa8717e36cf..71d1b23cdddd91e2a4fb072187aa8fc4ace7a7de 100644
--- a/dune/python/CMakeLists.txt
+++ b/dune/python/CMakeLists.txt
@@ -1 +1,2 @@
 add_subdirectory(geometry)
+add_subdirectory(test)
diff --git a/dune/python/test/CMakeLists.txt b/dune/python/test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2decb23b40e554b112b644ce7b1a9cf4425c82ab
--- /dev/null
+++ b/dune/python/test/CMakeLists.txt
@@ -0,0 +1,12 @@
+dune_python_add_test(NAME pyrefelement
+                     COMMAND ${PYTHON_EXECUTABLE} refelement.py
+                     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+                     LABELS quick)
+dune_python_add_test(NAME pygeometrytype
+                     COMMAND ${PYTHON_EXECUTABLE} geometrytype.py
+                     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+                     LABELS quick)
+dune_python_add_test(NAME pytestquad
+                     COMMAND ${PYTHON_EXECUTABLE} test_quad.py
+                     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+                     LABELS quick)
diff --git a/dune/python/test/geometrytype.py b/dune/python/test/geometrytype.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd43abeb3530ef8505a734eef77b5fc7a2288400
--- /dev/null
+++ b/dune/python/test/geometrytype.py
@@ -0,0 +1,20 @@
+from dune.geometry import *
+
+# make sure t can be reconstructed from str(t)
+for t in (vertex, line, triangle, quadrilateral, tetrahedron, pyramid, prism, hexahedron):
+    assert GeometryType(str(t)) == t
+
+for d in range(10):
+    assert GeometryType(str(simplex(d))) == simplex(d)
+    assert GeometryType(str(cube(d))) == cube(d)
+    assert GeometryType(str(none(d))) == none(d)
+
+# make sure simplices with special names can be constructed by general mechanism
+for d, t in enumerate((vertex, line, triangle, tetrahedron)):
+    assert GeometryType("simplex(" + str(d) + ")") == t
+    assert GeometryType("general( 0, " + str(d) + ")") == t
+
+# make sure cube with special names can be constructed by general mechanism
+for d, t in enumerate((vertex, line, quadrilateral, hexahedron)):
+    assert GeometryType("cube(" + str(d) + ")") == t
+    assert GeometryType("general( " + str(2**d-1) + ", " + str(d) + ")") == t
diff --git a/dune/python/test/refelement.py b/dune/python/test/refelement.py
new file mode 100644
index 0000000000000000000000000000000000000000..74ca8d2ac5fac7618ec62b33ff5f3e1b13ce2cd6
--- /dev/null
+++ b/dune/python/test/refelement.py
@@ -0,0 +1,40 @@
+from dune.geometry import referenceElement
+from dune.geometry import vertex, line, triangle, quadrilateral, tetrahedron, pyramid, prism, hexahedron, none
+
+def test(r):
+    for codim in range(r.dimension+1):
+        types = r.types(codim)
+        if len(types) != r.size(codim):
+            raise Exception("types tuple has wrong size")
+        for i in range(len(types)):
+            if types[i] != r.type(i, codim):
+                raise Exception("types tuple has wrong content")
+
+    for codim in range(r.dimension+1):
+        positions = r.positions(codim)
+        if len(positions) != r.size(codim):
+            raise Exception("positions tuple has wrong size")
+        for i in range(len(positions)):
+            if positions[i] != r.position(i, codim):
+                raise Exception("positions tuple has wrong content")
+
+    if r.dimension > 0:
+        normals = r.integrationOuterNormals
+        if len(normals) != r.size(1):
+            raise Exception("integrationOuterNormals has wrong size")
+        for i in range(len(normals)):
+            if normals[i] != r.integrationOuterNormal(i):
+                raise Exception("integrationOuterNormals has wrong content")
+
+test(referenceElement(vertex))
+test(referenceElement(line))
+test(referenceElement(triangle))
+test(referenceElement(quadrilateral))
+test(referenceElement(tetrahedron))
+test(referenceElement(pyramid))
+test(referenceElement(prism))
+test(referenceElement(hexahedron))
+
+for dim in range(4):
+    if referenceElement(none(dim)) is not None:
+        raise Exception("got reference element for geometry type none")
diff --git a/dune/python/test/test_quad.py b/dune/python/test/test_quad.py
new file mode 100644
index 0000000000000000000000000000000000000000..466a8c13d96a2f719fbf52fae3bd6ce795d9432c
--- /dev/null
+++ b/dune/python/test/test_quad.py
@@ -0,0 +1,44 @@
+import time, math, numpy
+import dune.geometry as geo
+
+def monomial(p):
+    def function(point):
+        return sum( x**p for x in point)
+    return function
+
+result = {3:   # integral for sum_i x_i^p over reference element
+           {geo.line: 1./4.,
+            geo.triangle: 0.1,
+            geo.quadrilateral: 1./2.,
+            geo.tetrahedron: 1./40.,
+            geo.pyramid: None,
+            geo.prism: None,
+            geo.hexahedron: 3./4.,
+           },
+          4:
+           {geo.line: 1./5.,
+            geo.triangle: 1./15.,
+            geo.quadrilateral: 2./5.,
+            geo.tetrahedron: 1./70.,
+            geo.pyramid: None,
+            geo.prism: None,
+            geo.hexahedron: 3./5.,
+           },
+         }
+
+
+
+for order in [3,4]:
+    rules = geo.quadratureRules(order)
+    p = monomial(order)
+    for t in (geo.line, geo.triangle, geo.quadrilateral,
+              geo.tetrahedron, geo.pyramid, geo.prism, geo.hexahedron):
+        value1 = 0
+        for q in rules(t):
+            value1 += p(q.position)*q.weight
+        hatxs, hatws = rules(t).get()
+        value2 = numpy.sum(p(hatxs) * hatws, axis=-1)
+        # print(order,t,value2)
+        assert abs(value1-value2)<1e-14
+        if result[order][t] is not None:
+            assert abs(result[order][t] - value1)<1e-12