diff --git a/pyproject.toml b/pyproject.toml
index 34feb03f8cf3487250b55348ba749e47e1cb36ee..c15ef858b2d71cb0384ee75ad9b7a9372cb9f817 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -29,7 +29,8 @@ dependencies = [
 
 [project.optional-dependencies]
 test = [
-  'pytest >= 6'
+  'pytest >= 6',
+  'numdifftools >= 0.9',
 ]
 
 [tool.pytest.ini_options]
diff --git a/tests/test_basic.py b/tests/test_basic.py
index 0bd391e40cc79167b46d81876af45034fa5a0631..3ef1d58eb240159047061baae62e5da317f83a5b 100644
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -5,6 +5,11 @@ import numpy as np
 from numpy.testing import assert_allclose
 from scipy.linalg import expm
 
+try:
+    import numdifftools
+except ImportError:
+    numdifftools = None
+
 import usadelndsoc
 import usadelndsoc.solver
 
@@ -157,18 +162,26 @@ def test_gauge_invariance():
     div_J_y = J[1] - J[3]
     div_J = div_J_x + div_J_y
 
+    print("->", div_J)
+
     # Compute source term (numdiff)
-    Sa = s._core.eval(Phi)
+    def S_s(ds):
+        Phi2 = Phi.copy()
+        dW = expm(ds * t3)
+        idW = np.linalg.inv(dW)
+        Phi2[i, j, 0] = dW[:2, :2] @ Phi[i, j, 0] @ idW[2:, 2:]
+        Phi2[i, j, 1] = dW[2:, 2:] @ Phi[i, j, 1] @ idW[:2, :2]
+        return s._core.eval(Phi2)
 
-    Phi2 = Phi.copy()
     ds = 1e-7
-    dW = expm(ds * t3)
-    idW = np.linalg.inv(dW)
-    Phi2[i, j, 0] = dW[:2, :2] @ Phi[i, j, 0] @ idW[2:, 2:]
-    Phi2[i, j, 1] = dW[2:, 2:] @ Phi[i, j, 1] @ idW[:2, :2]
-
-    Sb = s._core.eval(Phi2)
-    dS_ds = (Sb - Sa) / ds / 16
+    dS_ds = (S_s(ds) - S_s(0)) / ds / 16
 
     # They must match
     assert_allclose(div_J, dS_ds, rtol=1e-6)
+
+    if numdifftools is not None:
+        # More accurate numdiff: the equality should hold to high
+        # numerical accuracy
+        D = numdifftools.Derivative(S_s)
+        dS_ds = D(0.0) / 16
+        assert_allclose(div_J, dS_ds, rtol=1e-12)