diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt
index 36678737fbdb4e4027a77bf4a4bd65481c24eda9..80146db8c5a314ffa848258085b72f327ca779b1 100644
--- a/test/common/CMakeLists.txt
+++ b/test/common/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(boundingboxtree)
 add_subdirectory(functions)
 add_subdirectory(geometry)
+add_subdirectory(integrate)
 add_subdirectory(math)
 add_subdirectory(parameters)
 add_subdirectory(propertysystem)
diff --git a/test/common/integrate/CMakeLists.txt b/test/common/integrate/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..54f255b05100a9714fe6b8ecd2fbbbb253feacaa
--- /dev/null
+++ b/test/common/integrate/CMakeLists.txt
@@ -0,0 +1 @@
+dumux_add_test(SOURCES test_integratescalar.cc LABELS unit)
diff --git a/test/common/integrate/test_integratescalar.cc b/test/common/integrate/test_integratescalar.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9841040ef4b9d6b10782b1f36d8dcd5458dee16f
--- /dev/null
+++ b/test/common/integrate/test_integratescalar.cc
@@ -0,0 +1,90 @@
+#include <config.h>
+
+#include <iostream>
+#include <iomanip>
+#include <cmath>
+
+#include <dune/common/exceptions.hh>
+#include <dune/common/float_cmp.hh>
+#include <dumux/common/integrate.hh>
+#include <dumux/nonlinear/findscalarroot.hh>
+
+namespace Dumux {
+
+class VanGenuchtenKrw
+{
+public:
+    VanGenuchtenKrw(double alpha, double n, double l = 0.5)
+    : alpha_(alpha), n_(n), m_(1.0 - 1.0/n), l_(l)
+    {}
+
+    double operator()(double pw) const
+    {
+        using std::pow;
+        const auto pc = 1.0e5-pw;
+        const auto swe = pow(pow(alpha_*pc, n_) + 1.0, -m_);
+        const auto r = 1.0 - pow(1.0 - pow(swe, 1.0/m_), m_);
+        return pow(swe, l_)*r*r;
+    }
+
+private:
+    double alpha_, n_, m_, l_;
+};
+
+} // end namespace Dumux
+
+int main(int argc, char* argv[]) try
+{
+    using namespace Dumux;
+
+    {
+        // test some integral where we know the analytical expression
+        const auto func = [](const double x){ return std::exp(2.0*x); };
+        const auto exactIntegral = 0.5*(std::exp(10.0)-std::exp(-2.0));
+        const auto numIntegral = integrateScalarFunction(func, -1.0, 5.0, 1e-8);
+        if (Dune::FloatCmp::ne<double, Dune::FloatCmp::CmpStyle::absolute>(exactIntegral, numIntegral, 1e-8))
+            DUNE_THROW(Dune::Exception, "Wrong integral: " << numIntegral << ", should be " << exactIntegral);
+    }
+
+    {
+        // test some integral where we know the analytical expression
+        const auto func = [](const double x){ return pow(1.0 - x, 5.0)*pow(x, -1.0/3.0); };
+        const auto exactIntegral = 2187.0/5236.0;
+        const auto numIntegral = integrateScalarFunction(func, 0.0, 1.0, 1e-8);
+        if (Dune::FloatCmp::ne<double, Dune::FloatCmp::CmpStyle::absolute>(exactIntegral, numIntegral, 1e-8))
+            DUNE_THROW(Dune::Exception, "Wrong integral: " << numIntegral << ", should be " << exactIntegral);
+    }
+
+    {
+        // relative permeability function of water pressure
+        const auto krFunc = VanGenuchtenKrw(/*alpha=*/1e-4, /*n=*/3.0);
+
+        // introduce a transformed variable u(p) = int_{-1.5e6}^{p} kr(q)dq
+        const auto kirchhoffTransform = [&](const double p){
+            return integrateScalarFunction(krFunc, -1.5e6, p, 1e-16);
+        };
+
+        // compute the inverse of the transformation numerically
+        const auto inverseTransform = [&](const auto u){
+            const auto residual = [&, u](const auto& p){ return u - kirchhoffTransform(p); };
+            return findScalarRootBrent(-1.6e6, 1.0e5, residual, 1e-10, 200000);
+        };
+
+        // compute transformation and inverse for several pressures
+        for (const auto p : {0.9e5, 0.1e5, 0.0, -5.0e5, -1.5e6})
+        {
+            const auto u = kirchhoffTransform(p);
+            const auto pNum = inverseTransform(u);
+            if (Dune::FloatCmp::ne<double, Dune::FloatCmp::CmpStyle::absolute>(p, pNum, 0.001))
+                DUNE_THROW(Dune::Exception, "Inverse did not recover original pressure value: "
+                           << std::setprecision(15) << pNum << ", should be " << p);
+        }
+    }
+
+    return 0;
+}
+catch (const Dune::Exception& e)
+{
+    std::cout << e << std::endl;
+    return 1;
+}