diff --git a/tests/test_TaylorPolynomial.cpp b/tests/test_TaylorPolynomial.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eec530eafeef396d12ff3c651881fa53c30249e8
--- /dev/null
+++ b/tests/test_TaylorPolynomial.cpp
@@ -0,0 +1,331 @@
+#include <Kokkos_Core.hpp>
+#include <algebra/TinyMatrix.hpp>
+#include <analysis/GaussQuadratureDescriptor.hpp>
+#include <analysis/QuadratureManager.hpp>
+#include <analysis/SquareGaussQuadrature.hpp>
+#include <analysis/TaylorPolynomial.hpp>
+#include <catch2/catch_approx.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <utils/PugsAssert.hpp>
+#include <utils/Types.hpp>
+
+// Instantiate to ensure full coverage is performed
+template class TaylorPolynomial<0, 2>;
+template class TaylorPolynomial<1, 2>;
+template class TaylorPolynomial<2, 2>;
+template class TaylorPolynomial<3, 2>;
+
+// clazy:excludeall=non-pod-global-static
+TinyVector<2> x0{1, -1};
+TinyVector<3> x1{1, -1, 1};
+
+TEST_CASE("TaylorPolynomial", "[analysis]")
+{
+  SECTION("construction")
+  {
+    TinyVector<6> coef(1, 2, 3, 4, 5, 6);
+    REQUIRE_NOTHROW(TaylorPolynomial<2, 2>(coef, x0));
+  }
+
+  SECTION("degree")
+  {
+    TinyVector<3> coef(1, 2, 3);
+    TaylorPolynomial<1, 2> P(coef, x0);
+    REQUIRE(P.degree() == 1);
+    REQUIRE(P.dim() == 2);
+  }
+
+  SECTION("equality")
+  {
+    TinyVector<6> coef(1, 2, 3, 4, 5, 6);
+    TinyVector<3> coef2(1, 2, 3);
+    TinyVector<6> coef3(1, 2, 3, 3, 3, 3);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    TaylorPolynomial<2, 2> Q(coef, x0);
+    TaylorPolynomial<2, 2> R(coef3, x0);
+
+    REQUIRE(P == Q);
+    REQUIRE(P != R);
+  }
+
+  SECTION("addition")
+  {
+    TinyVector<6> coef(1, 2, 3, 4, 5, 6);
+    TinyVector<6> coef2(1, 2, 3, -2, -1, -3);
+    TinyVector<6> coef3(2, 4, 6, 2, 4, 3);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    TaylorPolynomial<2, 2> Q(coef2, x0);
+    TaylorPolynomial<2, 2> R(coef3, x0);
+    REQUIRE(R == (P + Q));
+    REQUIRE((P + Q) == R);
+  }
+
+  SECTION("opposed")
+  {
+    TinyVector<6> coef(1, 2, 3, 4, 5, 6);
+    TinyVector<6> coef2(-1, -2, -3, -4, -5, -6);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    REQUIRE(-P == TaylorPolynomial<2, 2>(coef2, x0));
+  }
+
+  SECTION("difference")
+  {
+    TinyVector<6> coef(1, 2, 3, 4, 5, 6);
+    TinyVector<6> coef2(1, 2, 3, -2, -1, -3);
+    TinyVector<6> coef3(0, 0, 0, 6, 6, 9);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    TaylorPolynomial<2, 2> Q(coef2, x0);
+    TaylorPolynomial<2, 2> R(coef3, x0);
+    R = P - Q;
+    REQUIRE(R == TaylorPolynomial<2, 2>(coef3, x0));
+  }
+
+  SECTION("product_by_scalar")
+  {
+    TinyVector<6> coef(1, 2, 3, 4, 5, 6);
+    TinyVector<6> coef2(2, 4, 6, 8, 10, 12);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    TaylorPolynomial<2, 2> Q(coef2, x0);
+    REQUIRE(Q == (P * 2));
+    REQUIRE(Q == (2 * P));
+  }
+
+  SECTION("access_coef")
+  {
+    TinyVector<6> coef(1, -2, 10, 7, 2, 9);
+    TinyVector<10> coef2(2, -4, -1, -3, 3, -5, -6, 0, 1, 7);
+    TinyVector<10> coef3(2, -4, -1, -3, 3, -5, -6, 0, 1, 7);
+    TinyVector<20> coef4(2, -4, -1, -3, 3, -5, -6, -2, 1, 7, 3, -2, 1, 2.5, 6, -9, 0.5, 4, -5, -8);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    TaylorPolynomial<3, 2> Q(coef2, x0);
+    TaylorPolynomial<2, 3> R(coef3, x1);
+    TaylorPolynomial<3, 3> S(coef4, x1);
+    TinyVector<2, size_t> relative_coef(1, 1);
+    TinyVector<2, size_t> relative_coef2(1, 2);
+    TinyVector<3, size_t> relative_coef3(1, 0, 1);
+    TinyVector<3, size_t> relative_coef3b(0, 0, 2);
+    TinyVector<3, size_t> relative_coef4(1, 1, 1);
+    TinyVector<3, size_t> relative_coef5(0, 2, 1);
+    REQUIRE(P[relative_coef] == 2);
+    REQUIRE(Q[relative_coef2] == 1);
+    REQUIRE(Q[relative_coef] == 3);
+    REQUIRE(R[relative_coef3] == -6);
+    REQUIRE(R[relative_coef3b] == 7);
+    REQUIRE(S[relative_coef4] == 6);
+    REQUIRE(S[relative_coef5] == 4);
+  }
+
+  SECTION("evaluation")
+  {
+    TinyVector<6> coef(1, -2, 10, 7, 2, 9);
+    TinyVector<10> coef2(2, -4, -1, -3, 3, -5, -6, 0, 1, 7);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    TaylorPolynomial<3, 2> Q(coef2, x0);
+    TinyVector<6> coefx(1, -2, 0, 7, 0, 0);
+    TinyVector<6> coefy(2, 0, -2, 0, 0, 7);
+    TinyVector<2> pos(1, -1);
+    TinyVector<2> pos2(-1, 2);
+    TaylorPolynomial<2, 2> Px(coefx, x0);
+    TaylorPolynomial<2, 2> Py(coefy, x0);
+    REQUIRE(Px(pos) == 1);
+    REQUIRE(Py(pos) == 2);
+    REQUIRE(Px(pos2) == 33);
+    REQUIRE(P(pos2) == 132);
+    REQUIRE(Q(pos) == 2);
+  }
+
+  SECTION("derivation")
+  {
+    TinyVector<6> coef(1, -2, 10, 7, 2, 9);
+    TinyVector<6> coef2(-2, 14, 2, 0, 0, 0);
+    TinyVector<6> coef3(10, 2, 18, 0, 0, 0);
+    TinyVector<10> coef4(2, -4, -1, -3, 3, -5, -6, 1, 1, 7);
+    TinyVector<10> coef5(-1, -5, 2, 1, 0, 0, 0, 0, 0, 0);
+    TaylorPolynomial<2, 2> P(coef, x0);
+    TaylorPolynomial<2, 2> Q(coef2, x0);
+    TaylorPolynomial<2, 2> R(coef3, x0);
+    TaylorPolynomial<2, 3> S(coef4, x1);
+    TaylorPolynomial<2, 3> T(coef5, x1);
+
+    REQUIRE(Q == P.derivative(0));
+    REQUIRE(R == P.derivative(1));
+    REQUIRE(T == S.derivative(1));
+  }
+
+  SECTION("integrate")
+  {
+    TinyVector<6> coef(1, -2, 10, 7, 2, 9);
+    std::array<TinyVector<2>, 4> positions;
+    std::array<TinyVector<2>, 3> positions2;
+    std::array<TinyVector<2>, 4> positions3;
+    std::array<TinyVector<2>, 2> positions4;
+    positions[0]  = TinyVector<2>{0, 0};
+    positions[1]  = TinyVector<2>{0, 0.5};
+    positions[2]  = TinyVector<2>{0.3, 0.7};
+    positions[3]  = TinyVector<2>{0.4, 0.1};
+    positions2[0] = TinyVector<2>{0, 0};
+    positions2[1] = TinyVector<2>{0, 0.5};
+    positions2[2] = TinyVector<2>{0.3, 0.7};
+    positions3[0] = TinyVector<2>{0, 0};
+    positions3[1] = TinyVector<2>{1, 0};
+    positions3[2] = TinyVector<2>{1, 1};
+    positions3[3] = TinyVector<2>{0, 1};
+    positions4[0] = TinyVector<2>{0, 0.5};
+    positions4[1] = TinyVector<2>{0.3, 0.7};
+    TaylorPolynomial<2, 2> P(coef, x0);
+    auto p1 = [](const TinyVector<2>& X) {
+      const double x = X[0];
+      const double y = X[1];
+      return 1 - 2. * (x - 1.) + 10 * (y + 1) + 7 * (x - 1.) * (x - 1) + 2 * (x - 1) * (y + 1) + 9 * (y + 1) * (y + 1);
+    };
+    const QuadratureFormula<2>& l3 = QuadratureManager::instance().getSquareFormula(GaussQuadratureDescriptor(3));
+    auto point_list                = l3.pointList();
+    auto weight_list               = l3.weightList();
+    SquareTransformation<2> s{positions[0], positions[1], positions[2], positions[3]};
+    auto value = weight_list[0] * s.jacobianDeterminant(point_list[0]) * p1(s(point_list[0]));
+    for (size_t i = 1; i < weight_list.size(); ++i) {
+      value += weight_list[i] * s.jacobianDeterminant(point_list[i]) * p1(s(point_list[i]));
+    }
+    SquareTransformation<2> s3{positions3[0], positions3[1], positions3[2], positions3[3]};
+    auto value3 = weight_list[0] * s3.jacobianDeterminant(point_list[0]) * p1(s3(point_list[0]));
+    for (size_t i = 1; i < weight_list.size(); ++i) {
+      value3 += weight_list[i] * s3.jacobianDeterminant(point_list[i]) * p1(s3(point_list[i]));
+    }
+    const QuadratureFormula<2>& t3 = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor(3));
+    auto point_list2               = t3.pointList();
+    auto weight_list2              = t3.weightList();
+    TriangleTransformation<2> t{positions2[0], positions2[1], positions2[2]};
+    auto value2 = weight_list2[0] * p1(t(point_list2[0]));
+    for (size_t i = 1; i < weight_list2.size(); ++i) {
+      value2 += weight_list2[i] * p1(t(point_list2[i]));
+    }
+    const QuadratureFormula<1>& l1 = QuadratureManager::instance().getLineFormula(GaussQuadratureDescriptor(2));
+    const LineTransformation<2> u{positions4[0], positions4[1]};
+    double value4 = 0.;
+    for (size_t i = 0; i < l1.numberOfPoints(); ++i) {
+      value4 += l1.weight(i) * u.velocityNorm() * p1(u(l1.point(i)));
+    }
+
+    REQUIRE(value == Catch::Approx(integrate(P, positions)));
+    REQUIRE(value2 == Catch::Approx(integrate(P, positions2)));
+    REQUIRE(value3 == Catch::Approx(integrate(P, positions3)));
+    REQUIRE(value4 == Catch::Approx(integrate(P, positions4)));
+  }
+
+  // // SECTION("product")
+  // {
+  //   Polynomial<2> P(2, 3, 4);
+  //   Polynomial<3> Q(1, 2, -1, 1);
+  //   Polynomial<4 > R;
+  //   Polynomial<5> S;
+  //   R = P;
+  //   S = P;
+  //   S *= Q;
+  //   REQUIRE(Polynomial<5>(2, 7, 8, 7, -1, 4) == (P * Q));
+  //   REQUIRE(Polynomial<5>(2, 7, 8, 7, -1, 4) == S);
+  //   // REQUIRE_THROWS_AS(R *= Q, AssertError);
+  // }
+
+  // SECTION("divide")
+  // {
+  //   Polynomial<2> P(1, 0, 1);
+  //   Polynomial<1> Q(0, 1);
+  //   Polynomial<1> Q1(0, 1);
+
+  //   Polynomial<2> R;
+  //   Polynomial<2> S;
+  //   REQUIRE(P.realDegree() == 2);
+  //   REQUIRE(Q.realDegree() == 1);
+  //   REQUIRE(Q1.realDegree() == 1);
+
+  //   divide(P, Q1, R, S);
+  //   REQUIRE(Polynomial<2>{1, 0, 0} == S);
+  //   REQUIRE(Polynomial<2>{0, 1, 0} == R);
+  // }
+
+  // SECTION("primitive")
+  // {
+  //   Polynomial<2> P(2, -3, 4);
+  //   TinyVector<4> coefs = zero;
+  //   Polynomial<3> Q(coefs);
+  //   Q = primitive(P);
+  //   Polynomial<3> R(0, 2, -3. / 2, 4. / 3);
+  //   REQUIRE(Q == R);
+  // }
+
+  // SECTION("integrate")
+  // {
+  //   Polynomial<2> P(2, -3, 3);
+  //   double xinf   = -1;
+  //   double xsup   = 1;
+  //   double result = integrate(P, xinf, xsup);
+  //   REQUIRE(result == 6);
+  //   result = symmetricIntegrate(P, 2);
+  //   REQUIRE(result == 24);
+  // }
+
+  // SECTION("derivative")
+  // {
+  //   Polynomial<2> P(2, -3, 3);
+  //   Polynomial<1> Q = derivative(P);
+  //   REQUIRE(Q == Polynomial<1>(-3, 6));
+
+  //   Polynomial<0> P2(3);
+
+  //   Polynomial<0> R(0);
+  //   REQUIRE(derivative(P2) == R);
+  // }
+
+  // SECTION("affectation")
+  // {
+  //   Polynomial<2> Q(2, -3, 3);
+  //   Polynomial<4> R(2, -3, 3, 0, 0);
+  //   Polynomial<4> P(0, 1, 2, 3, 3);
+  //   P = Q;
+  //   REQUIRE(P == R);
+  // }
+
+  // SECTION("affectation addition")
+  // {
+  //   Polynomial<2> Q(2, -3, 3);
+  //   Polynomial<4> R(2, -2, 5, 3, 3);
+  //   Polynomial<4> P(0, 1, 2, 3, 3);
+  //   P += Q;
+  //   REQUIRE(P == R);
+  // }
+
+  // SECTION("power")
+  // {
+  //   Polynomial<2> P(2, -3, 3);
+  //   Polynomial<4> R(4, -12, 21, -18, 9);
+  //   Polynomial<1> Q(0, 2);
+  //   Polynomial<2> S = Q.pow<2>(2);
+  //   REQUIRE(P.pow<2>(2) == R);
+  //   REQUIRE(S == Polynomial<2>(0, 0, 4));
+  // }
+
+  // SECTION("composition")
+  // {
+  //   Polynomial<2> P(2, -3, 3);
+  //   Polynomial<1> Q(0, 2);
+  //   Polynomial<2> R(2, -1, 3);
+  //   Polynomial<2> S(1, 2, 2);
+  //   REQUIRE(P.compose(Q) == Polynomial<2>(2, -6, 12));
+  //   REQUIRE(P.compose2(Q) == Polynomial<2>(2, -6, 12));
+  //   REQUIRE(R(S) == Polynomial<4>(4, 10, 22, 24, 12));
+  // }
+
+  // SECTION("Lagrange polynomial")
+  // {
+  //   Polynomial<1> S(0.5, -0.5);
+  //   Polynomial<1> Q;
+  //   Q = lagrangePolynomial<1>(TinyVector<2>{-1, 1}, 0);
+  //   REQUIRE(S == Q);
+  //   Polynomial<2> P(0, -0.5, 0.5);
+  //   Polynomial<2> R;
+  //   R = lagrangePolynomial<2>(TinyVector<3>{-1, 0, 1}, 0);
+  //   REQUIRE(R == P);
+  //   const std::array<Polynomial<2>, 3> basis = lagrangeBasis(TinyVector<3>{-1, 0, 1});
+  //   REQUIRE(lagrangeToCanonical(TinyVector<3>{1, 0, 1}, basis) == Polynomial<2>(TinyVector<3>{0, 0, 1}));
+  // }
+}