diff --git a/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp
index 1439b8b1ef04a2cdc73cda7a40c152b5e6fbcd37..671a9e7ece3198f766f5ceea45b27a4372e5dcc3 100644
--- a/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp
+++ b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp
@@ -47,11 +47,13 @@ readIBoundaryConditionDescriptor(const HighFive::Group& iboundaryconditiondecrip
                                                                    *ResumingData::instance().functionSymbolId(rhs_id));
     break;
   }
+    // LCOV_EXCL_START
   case IBoundaryConditionDescriptor::Type::external: {
     throw NotImplementedError("checkpoint/resume with sockets");
 
     break;
   }
+    // LCOV_EXCL_STOP
   case IBoundaryConditionDescriptor::Type::fourier: {
     const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>();
     const size_t rhs_id    = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>();
diff --git a/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp b/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp
index ad99b31934b88bdff44e6f4780c1bd334fe875b0..ca26fdf359c51050b5edc0f82818a2522b8dfb1e 100644
--- a/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp
+++ b/src/utils/checkpointing/WriteIBoundaryConditionDescriptor.cpp
@@ -46,11 +46,13 @@ writeIBoundaryConditionDescriptor(HighFive::Group& variable_group,
     variable_group.createAttribute("rhs_function_id", dirichlet_bc_descriptor.rhsSymbolId().id());
     break;
   }
+    // LCOV_EXCL_START
   case IBoundaryConditionDescriptor::Type::external: {
     throw NotImplementedError("checkpoint/resume with sockets");
 
     break;
   }
+    // LCOV_EXCL_STOP
   case IBoundaryConditionDescriptor::Type::fourier: {
     const FourierBoundaryConditionDescriptor& fourier_bc_descriptor =
       dynamic_cast<const FourierBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 95b6b15d1d349505c052f573273e9cd608337cd5..a3048e7c854018c0476f2796ed981f2a0ba3d1b7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -162,6 +162,7 @@ if(PUGS_HAS_HDF5)
   list(APPEND checkpointing_TESTS
     test_checkpointing_HFTypes.cpp
     test_checkpointing_IBoundaryDescriptor.cpp
+    test_checkpointing_IBoundaryConditionDescriptor.cpp
     test_checkpointing_IInterfaceDescriptor.cpp
     test_checkpointing_IZoneDescriptor.cpp
   )
diff --git a/tests/test_checkpointing_IBoundaryConditionDescriptor.cpp b/tests/test_checkpointing_IBoundaryConditionDescriptor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..abbe5151f1aa4e132adbae667f3b90b4d7a010eb
--- /dev/null
+++ b/tests/test_checkpointing_IBoundaryConditionDescriptor.cpp
@@ -0,0 +1,311 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <utils/Messenger.hpp>
+
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/NamedBoundaryDescriptor.hpp>
+#include <mesh/NumberedBoundaryDescriptor.hpp>
+#include <scheme/AxisBoundaryConditionDescriptor.hpp>
+#include <scheme/DirichletBoundaryConditionDescriptor.hpp>
+#include <scheme/ExternalBoundaryConditionDescriptor.hpp>
+#include <scheme/FixedBoundaryConditionDescriptor.hpp>
+#include <scheme/FourierBoundaryConditionDescriptor.hpp>
+#include <scheme/FreeBoundaryConditionDescriptor.hpp>
+#include <scheme/InflowBoundaryConditionDescriptor.hpp>
+#include <scheme/NeumannBoundaryConditionDescriptor.hpp>
+#include <scheme/OutflowBoundaryConditionDescriptor.hpp>
+#include <scheme/SymmetryBoundaryConditionDescriptor.hpp>
+#include <utils/checkpointing/ReadIBoundaryConditionDescriptor.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+#include <utils/checkpointing/WriteIBoundaryConditionDescriptor.hpp>
+
+#include <language/ast/ASTBuilder.hpp>
+#include <language/ast/ASTModulesImporter.hpp>
+#include <language/ast/ASTNodeDataTypeBuilder.hpp>
+#include <language/ast/ASTNodeExpressionBuilder.hpp>
+#include <language/ast/ASTNodeFunctionEvaluationExpressionBuilder.hpp>
+#include <language/ast/ASTNodeFunctionExpressionBuilder.hpp>
+#include <language/ast/ASTNodeTypeCleaner.hpp>
+#include <language/ast/ASTSymbolTableBuilder.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/BasicAffectationRegistrerFor.hpp>
+#include <language/utils/TypeDescriptor.hpp>
+#include <utils/GlobalVariableManager.hpp>
+
+// #include <utils/Demangle.hpp>
+
+#include <pegtl/string_input.hpp>
+
+#include <filesystem>
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("checkpointing_IBoundaryConditionDescriptor", "[utils/checkpointing]")
+{
+  std::string tmp_dirname;
+  {
+    {
+      if (parallel::rank() == 0) {
+        tmp_dirname = [&]() -> std::string {
+          std::string temp_filename = std::filesystem::temp_directory_path() / "pugs_checkpointing_XXXXXX";
+          return std::string{mkdtemp(&temp_filename[0])};
+        }();
+      }
+      parallel::broadcast(tmp_dirname, 0);
+    }
+    std::filesystem::path path = tmp_dirname;
+    const std::string filename = path / "checkpoint.h5";
+
+    HighFive::FileAccessProps fapl;
+    fapl.add(HighFive::MPIOFileAccess{MPI_COMM_WORLD, MPI_INFO_NULL});
+    fapl.add(HighFive::MPIOCollectiveMetadata{});
+    HighFive::File file = HighFive::File(filename, HighFive::File::Truncate, fapl);
+
+    SECTION("IBoundaryConditionDescriptor")
+    {
+      std::shared_ptr<SymbolTable> symbol_table;
+
+      std::string data =
+        R"(
+let f: R -> R, x -> 2*x;
+let g: R -> R, x -> 2*x+1;
+let h: R -> R, x -> -x;
+let i: R -> R, x -> x+3;
+)";
+
+      TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"};
+      auto ast = ASTBuilder::build(input);
+
+      ASTModulesImporter{*ast};
+      BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")};
+
+      ASTNodeTypeCleaner<language::import_instruction>{*ast};
+
+      ASTSymbolTableBuilder{*ast};
+      ASTNodeDataTypeBuilder{*ast};
+
+      ASTNodeTypeCleaner<language::var_declaration>{*ast};
+      ASTNodeTypeCleaner<language::fct_declaration>{*ast};
+      ASTNodeExpressionBuilder{*ast};
+
+      symbol_table = ast->m_symbol_table;
+
+      HighFive::Group checkpoint_group = file.createGroup("checkpoint");
+
+      HighFive::Group global_variables_group = checkpoint_group.createGroup("singleton/global_variables");
+      global_variables_group.createAttribute("connectivity_id", GlobalVariableManager::instance().getConnectivityId());
+      global_variables_group.createAttribute("mesh_id", GlobalVariableManager::instance().getMeshId());
+
+      HighFive::Group function_group = checkpoint_group.createGroup("functions");
+
+      {
+        HighFive::Group f = function_group.createGroup("f");
+        f.createAttribute("id", size_t{0});
+        f.createAttribute("symbol_table_id", size_t{0});
+
+        HighFive::Group g = function_group.createGroup("g");
+        g.createAttribute("id", size_t{1});
+        g.createAttribute("symbol_table_id", size_t{0});
+
+        HighFive::Group h = function_group.createGroup("h");
+        h.createAttribute("id", size_t{2});
+        h.createAttribute("symbol_table_id", size_t{0});
+
+        HighFive::Group i = function_group.createGroup("i");
+        i.createAttribute("id", size_t{3});
+        i.createAttribute("symbol_table_id", size_t{0});
+      }
+
+      HighFive::Group symbol_table_group = checkpoint_group.createGroup("symbol_table");
+
+      auto p_boundary_1 = std::make_shared<NamedBoundaryDescriptor>("bd1");
+      auto p_boundary_2 = std::make_shared<NumberedBoundaryDescriptor>(2);
+
+      HighFive::Group useless_group;
+
+      auto p_axis_bc_descriptor = std::make_shared<const AxisBoundaryConditionDescriptor>(p_boundary_1);
+      checkpointing::writeIBoundaryConditionDescriptor("axis_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_axis_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      auto p_sym_bc_descriptor = std::make_shared<const SymmetryBoundaryConditionDescriptor>(p_boundary_1);
+      checkpointing::writeIBoundaryConditionDescriptor("sym_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_sym_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      auto p_outflow_bc_descriptor = std::make_shared<const OutflowBoundaryConditionDescriptor>(p_boundary_2);
+      checkpointing::writeIBoundaryConditionDescriptor("outflow_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_outflow_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      auto p_free_bc_descriptor = std::make_shared<const FreeBoundaryConditionDescriptor>(p_boundary_2);
+      checkpointing::writeIBoundaryConditionDescriptor("free_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_free_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      auto p_fixed_bc_descriptor = std::make_shared<const FixedBoundaryConditionDescriptor>(p_boundary_2);
+      checkpointing::writeIBoundaryConditionDescriptor("fixed_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_fixed_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      const FunctionSymbolId dirichlet_function_id{3, symbol_table};
+      auto p_dirichlet_bc_descriptor =
+        std::make_shared<const DirichletBoundaryConditionDescriptor>("dirichlet_name", p_boundary_1,
+                                                                     dirichlet_function_id);
+      checkpointing::writeIBoundaryConditionDescriptor("dirichlet_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_dirichlet_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      const FunctionSymbolId neumann_function_id{1, symbol_table};
+      auto p_neumann_bc_descriptor =
+        std::make_shared<const NeumannBoundaryConditionDescriptor>("neumann_name", p_boundary_1, neumann_function_id);
+      checkpointing::writeIBoundaryConditionDescriptor("neumann_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_neumann_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      const FunctionSymbolId fourier_mass_function_id{0, symbol_table};
+      const FunctionSymbolId fourier_rhs_function_id{2, symbol_table};
+      auto p_fourier_bc_descriptor =
+        std::make_shared<const FourierBoundaryConditionDescriptor>("fourier_name", p_boundary_2,
+                                                                   fourier_mass_function_id, fourier_rhs_function_id);
+      checkpointing::writeIBoundaryConditionDescriptor("fourier_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_fourier_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      const FunctionSymbolId inflow_function_id{3, symbol_table};
+      auto p_inflow_bc_descriptor =
+        std::make_shared<const InflowBoundaryConditionDescriptor>(p_boundary_2, inflow_function_id);
+      checkpointing::writeIBoundaryConditionDescriptor("inflow_bc_descriptor",
+                                                       EmbeddedData{std::make_shared<
+                                                         DataHandler<const IBoundaryConditionDescriptor>>(
+                                                         p_inflow_bc_descriptor)},
+                                                       file, useless_group, symbol_table_group);
+
+      file.flush();
+
+      checkpointing::ResumingData::create();
+
+      checkpointing::ResumingData::instance().readData(checkpoint_group, symbol_table);
+
+      EmbeddedData read_axis_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("axis_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_sym_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("sym_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_outflow_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("outflow_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_free_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("free_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_fixed_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("fixed_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_dirichlet_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("dirichlet_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_neumann_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("neumann_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_fourier_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("fourier_bc_descriptor", symbol_table_group);
+
+      EmbeddedData read_inflow_bc_descriptor =
+        checkpointing::readIBoundaryConditionDescriptor("inflow_bc_descriptor", symbol_table_group);
+
+      auto get_value = [](const EmbeddedData& embedded_data) -> const IBoundaryConditionDescriptor& {
+        return *dynamic_cast<const DataHandler<const IBoundaryConditionDescriptor>&>(embedded_data.get()).data_ptr();
+      };
+
+      REQUIRE_NOTHROW(get_value(read_axis_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_sym_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_outflow_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_free_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_fixed_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_dirichlet_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_neumann_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_fourier_bc_descriptor));
+      REQUIRE_NOTHROW(get_value(read_inflow_bc_descriptor));
+
+      REQUIRE(get_value(read_axis_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::axis);
+      REQUIRE(get_value(read_sym_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::symmetry);
+      REQUIRE(get_value(read_outflow_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::outflow);
+      REQUIRE(get_value(read_free_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::free);
+      REQUIRE(get_value(read_fixed_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::fixed);
+      REQUIRE(get_value(read_dirichlet_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::dirichlet);
+      REQUIRE(get_value(read_neumann_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::neumann);
+      REQUIRE(get_value(read_fourier_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::fourier);
+      REQUIRE(get_value(read_inflow_bc_descriptor).type() == IBoundaryConditionDescriptor::Type::inflow);
+
+      REQUIRE_NOTHROW(dynamic_cast<const AxisBoundaryConditionDescriptor&>(get_value(read_axis_bc_descriptor)));
+      REQUIRE_NOTHROW(dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(get_value(read_sym_bc_descriptor)));
+      REQUIRE_NOTHROW(dynamic_cast<const OutflowBoundaryConditionDescriptor&>(get_value(read_outflow_bc_descriptor)));
+      REQUIRE_NOTHROW(dynamic_cast<const FreeBoundaryConditionDescriptor&>(get_value(read_free_bc_descriptor)));
+      REQUIRE_NOTHROW(dynamic_cast<const FixedBoundaryConditionDescriptor&>(get_value(read_fixed_bc_descriptor)));
+      REQUIRE_NOTHROW(
+        dynamic_cast<const DirichletBoundaryConditionDescriptor&>(get_value(read_dirichlet_bc_descriptor)));
+      REQUIRE_NOTHROW(dynamic_cast<const NeumannBoundaryConditionDescriptor&>(get_value(read_neumann_bc_descriptor)));
+      REQUIRE_NOTHROW(dynamic_cast<const FourierBoundaryConditionDescriptor&>(get_value(read_fourier_bc_descriptor)));
+      REQUIRE_NOTHROW(dynamic_cast<const InflowBoundaryConditionDescriptor&>(get_value(read_inflow_bc_descriptor)));
+
+      auto& read_axis_bc = dynamic_cast<const AxisBoundaryConditionDescriptor&>(get_value(read_axis_bc_descriptor));
+      auto& read_sym_bc  = dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(get_value(read_sym_bc_descriptor));
+      auto& read_outflow_bc =
+        dynamic_cast<const OutflowBoundaryConditionDescriptor&>(get_value(read_outflow_bc_descriptor));
+      auto& read_free_bc  = dynamic_cast<const FreeBoundaryConditionDescriptor&>(get_value(read_free_bc_descriptor));
+      auto& read_fixed_bc = dynamic_cast<const FixedBoundaryConditionDescriptor&>(get_value(read_fixed_bc_descriptor));
+      auto& read_dirichlet_bc =
+        dynamic_cast<const DirichletBoundaryConditionDescriptor&>(get_value(read_dirichlet_bc_descriptor));
+      auto& read_neumann_bc =
+        dynamic_cast<const NeumannBoundaryConditionDescriptor&>(get_value(read_neumann_bc_descriptor));
+      auto& read_fourier_bc =
+        dynamic_cast<const FourierBoundaryConditionDescriptor&>(get_value(read_fourier_bc_descriptor));
+      auto& read_inflow_bc =
+        dynamic_cast<const InflowBoundaryConditionDescriptor&>(get_value(read_inflow_bc_descriptor));
+
+      REQUIRE(read_axis_bc.boundaryDescriptor().type() == p_axis_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_sym_bc.boundaryDescriptor().type() == p_sym_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_outflow_bc.boundaryDescriptor().type() == p_outflow_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_free_bc.boundaryDescriptor().type() == p_free_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_fixed_bc.boundaryDescriptor().type() == p_fixed_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_dirichlet_bc.boundaryDescriptor().type() == p_dirichlet_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_dirichlet_bc.name() == p_dirichlet_bc_descriptor->name());
+      REQUIRE(read_dirichlet_bc.rhsSymbolId().id() == p_dirichlet_bc_descriptor->rhsSymbolId().id());
+      REQUIRE(read_neumann_bc.boundaryDescriptor().type() == p_neumann_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_neumann_bc.name() == p_neumann_bc_descriptor->name());
+      REQUIRE(read_neumann_bc.rhsSymbolId().id() == p_neumann_bc_descriptor->rhsSymbolId().id());
+      REQUIRE(read_fourier_bc.boundaryDescriptor().type() == p_fourier_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_fourier_bc.name() == p_fourier_bc_descriptor->name());
+      REQUIRE(read_fourier_bc.massSymbolId().id() == p_fourier_bc_descriptor->massSymbolId().id());
+      REQUIRE(read_fourier_bc.rhsSymbolId().id() == p_fourier_bc_descriptor->rhsSymbolId().id());
+      REQUIRE(read_inflow_bc.boundaryDescriptor().type() == p_inflow_bc_descriptor->boundaryDescriptor().type());
+      REQUIRE(read_inflow_bc.functionSymbolId().id() == p_inflow_bc_descriptor->functionSymbolId().id());
+
+      checkpointing::ResumingData::destroy();
+    }
+  }
+
+  parallel::barrier();
+  if (parallel::rank() == 0) {
+    std::filesystem::remove_all(std::filesystem::path{tmp_dirname});
+  }
+}