diff --git a/tests/executables_src/testExceptionHandling.cc b/tests/executables_src/testExceptionHandling.cc
index 59aacd73d60750859dca5d31195543eb45194dbd..ca74fd146e68740e21cea17898137cc2fe8ca7a4 100644
--- a/tests/executables_src/testExceptionHandling.cc
+++ b/tests/executables_src/testExceptionHandling.cc
@@ -20,111 +20,11 @@
 #include "ScalarAccessor.h"
 #include "TestFacility.h"
 #include "check_timeout.h"
+#include "fixtures.h"
 
 using namespace boost::unit_test_framework;
 namespace ctk = ChimeraTK;
-
-/*
- * This module polls device register on demand.
- */
-struct PollModule : ctk::ApplicationModule {
-  using ctk::ApplicationModule::ApplicationModule;
-
-  ctk::ScalarPollInput<int> fromDevice{this, "REG1", "", "", {"DEVICE"}};
-  ctk::ScalarOutput<int> toCs{this, "o1", "", "", {"CS"}};
-
-  void mainLoop() override {
-    while(true) {
-      if(block == true) {
-        boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
-        continue;
-      }
-      fromDevice.read();
-      toCs = static_cast<int>(fromDevice);
-      writeAll();
-      block = true;
-    }
-  }
-
-  /*
-   * trigger a poll type read on the device register: REG1
-   */
-  void triggerRead() {
-    block = false;
-    while(block == false) {
-      boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
-    }
-  }
-
-  std::atomic<bool> block{true};
-};
-
-struct DummyApplication : ctk::Application {
-  //   +----------+  poll_type_variable  +------+
-  //   |Module x<------------------------+Device|
-  //   +----------+                      +------+
-
-  constexpr static char const* ExceptionDummyCDD1 = "(ExceptionDummy:1?map=test.map)";
-  DummyApplication() : Application("DummyApplication") {}
-  ~DummyApplication() { shutdown(); }
-
-  PollModule pollModule{this, "", ""};
-
-  ctk::ControlSystemModule cs;
-  ctk::DeviceModule device{this, ExceptionDummyCDD1};
-
-  void defineConnections() override {
-    findTag("CS").connectTo(cs);
-    findTag("DEVICE").connectTo(device);
-  }
-};
-
-struct Fixture_noTestFacility {
-  Fixture_noTestFacility()
-  : deviceBackend(boost::dynamic_pointer_cast<ctk::ExceptionDummy>(
-        ChimeraTK::BackendFactory::getInstance().createBackend(DummyApplication::ExceptionDummyCDD1))) {
-    deviceBackend->open();
-    testFacitiy.runApplication();
-
-    hwRegister.replace(application.device.device.getScalarRegisterAccessor<int>("/REG1"));
-
-    status.replace(
-        testFacitiy.getScalar<int>(ctk::RegisterPath("/Devices") / DummyApplication::ExceptionDummyCDD1 / "status"));
-    message.replace(testFacitiy.getScalar<std::string>(
-        ctk::RegisterPath("/Devices") / DummyApplication::ExceptionDummyCDD1 / "message"));
-
-    //
-    // As a test precondition, the DeviceModule  must have completed its startup procedure. The
-    // device module writes status to 0 and message to "" once the initialization is complete and
-    // the device is functional.
-    //
-    // This behavior is used as a workaround to ensure we exit only after startup is complete
-    /************************************************************************************************/
-    CHECK_TIMEOUT(
-        [&]() {
-          status.readLatest();
-          return static_cast<int>(status);
-        }() == 0,
-        100000);
-    CHECK_TIMEOUT(
-        [&]() {
-          message.readLatest();
-          return static_cast<std::string>(message);
-        }() == "",
-        100000);
-    /************************************************************************************************/
-  }
-
-  ~Fixture_noTestFacility() { deviceBackend->throwExceptionRead = false; }
-
-  boost::shared_ptr<ctk::ExceptionDummy> deviceBackend;
-  DummyApplication application;
-  ctk::TestFacility testFacitiy{false};
-
-  ctk::ScalarRegisterAccessor<int> status;
-  ctk::ScalarRegisterAccessor<std::string> message;
-  ctk::ScalarRegisterAccessor<int> hwRegister;
-};
+using Fixture = fixture_with_poll_and_push_input<false>;
 
 /*
  * This test suite checks behavior on a device related runtime error.
@@ -143,7 +43,7 @@ BOOST_AUTO_TEST_SUITE(runtimeErrorHandling)
   *
   * \anchor testExceptionHandling_b_2_1 \ref exceptionHandling_b_2_1 "B.2.1"
   */
-BOOST_FIXTURE_TEST_CASE(runtimeErrorHandling_testFaultReporting, Fixture_noTestFacility) {
+BOOST_FIXTURE_TEST_CASE(runtimeErrorHandling_testFaultReporting, Fixture) {
   std::cout << "runtimeErrorHandling_testFaultReporting" << std::endl;
 
   // These are instantiated in the fixture:
@@ -154,7 +54,7 @@ BOOST_FIXTURE_TEST_CASE(runtimeErrorHandling_testFaultReporting, Fixture_noTestF
   BOOST_CHECK_EQUAL(static_cast<std::string>(message), "");
 
   deviceBackend->throwExceptionRead = true;
-  application.pollModule.triggerRead(); // causes device exception
+  application.pollModule.pollInput.read(); // causes device exception
 
   CHECK_TIMEOUT(status.readNonBlocking() == true, 10000);
   CHECK_TIMEOUT(message.readNonBlocking() == true, 10000);
@@ -176,56 +76,52 @@ BOOST_FIXTURE_TEST_CASE(runtimeErrorHandling_testFaultReporting, Fixture_noTestF
  * For such a variable:
  *   - read is skipped till device recovers.
  *   - first skipped instance of read changes datavalidity flag to faulty and generates a new version
- *     number which stays the same till the device recovers
+ *     number. 
  */
-BOOST_FIXTURE_TEST_CASE(runtimeErrorHandling_testPolledRead, Fixture_noTestFacility) {
+BOOST_FIXTURE_TEST_CASE(runtimeErrorHandling_testPolledRead, Fixture) {
   std::cout << "runtimeErrorHandling_testPolledRead" << std::endl;
-
-  // since the testFacility cannot access the poll type process variable directly, we make use of
-  // proxy variable o1 that is linked with this poll type variable.
-  auto proxyVariable = testFacitiy.getScalar<int>("/o1");
+  auto& pollInput = application.pollModule.pollInput;
 
   // initialize to known value in deviceBackend register
-  hwRegister = 100;
-  hwRegister.write();
+  exceptionDummyRegister = 100;
+  exceptionDummyRegister.write();
 
   // verify normal operation
   /************************************************************************************************/
-  application.pollModule.triggerRead();
-  proxyVariable.read();
-  auto versionNumberBeforeRuntimeError = proxyVariable.getVersionNumber();
+  pollInput.read();
+  auto versionNumberBeforeRuntimeError = pollInput.getVersionNumber();
 
-  BOOST_CHECK_EQUAL(proxyVariable, 100);
-  BOOST_CHECK(proxyVariable.dataValidity() == ctk::DataValidity::ok);
+  BOOST_CHECK_EQUAL(pollInput, 100);
+  BOOST_CHECK(pollInput.dataValidity() == ctk::DataValidity::ok);
   /************************************************************************************************/
 
   // Behavior on Runtime error on device:
   /************************************************************************************************/
-  hwRegister = 10;
-  hwRegister.write();
+  exceptionDummyRegister = 10;
+  exceptionDummyRegister.write();
 
   deviceBackend->throwExceptionRead = true;
+  pollInput.read();
+
+  // Proceed only after device is gone down.
+  CHECK_TIMEOUT(
+      [&]() {
+        status.readLatest();
+        return static_cast<int>(status);
+      }() == 1,
+      10000);
+
 
-  application.pollModule.triggerRead();
-  proxyVariable.read();
-  auto versionNumberOnRuntimeError = proxyVariable.getVersionNumber();
+  auto versionNumberOnRuntimeError = pollInput.getVersionNumber();
 
-  BOOST_CHECK_EQUAL(proxyVariable, 100);
-  BOOST_CHECK(proxyVariable.dataValidity() == ctk::DataValidity::faulty);
+  BOOST_CHECK_EQUAL(pollInput, 100);
+  BOOST_CHECK(pollInput.dataValidity() == ctk::DataValidity::faulty);
   BOOST_CHECK(versionNumberOnRuntimeError > versionNumberBeforeRuntimeError);
   /************************************************************************************************/
 
-  // Behavior on persisting Runtime error:
-  /************************************************************************************************/
-  application.pollModule.triggerRead();
-  proxyVariable.read();
-  auto versionNumber = proxyVariable.getVersionNumber();
 
-  BOOST_CHECK_EQUAL(proxyVariable, 100);
-  BOOST_CHECK(proxyVariable.dataValidity() == ctk::DataValidity::faulty);
-  BOOST_CHECK(versionNumber == versionNumberOnRuntimeError);
+  // Behavior on device recovery
   /************************************************************************************************/
-
   deviceBackend->throwExceptionRead = false;
   // workaround: wait till device module recovey completes; assumption: status variable == 0 =>
   // device recovered.
@@ -236,14 +132,11 @@ BOOST_FIXTURE_TEST_CASE(runtimeErrorHandling_testPolledRead, Fixture_noTestFacil
       }() == 0,
       10000);
 
-  // Behavior on device recovery
-  /************************************************************************************************/
-  application.pollModule.triggerRead();
-  proxyVariable.read();
-  auto versionNumberAfterRecovery = proxyVariable.getVersionNumber();
+  pollInput.read();
+  auto versionNumberAfterRecovery = pollInput.getVersionNumber();
 
-  BOOST_CHECK_EQUAL((int)proxyVariable, 10);
-  BOOST_CHECK(proxyVariable.dataValidity() == ctk::DataValidity::ok);
+  BOOST_REQUIRE_EQUAL(pollInput, 10);
+  BOOST_CHECK(pollInput.dataValidity() == ctk::DataValidity::ok);
   BOOST_CHECK(versionNumberAfterRecovery > versionNumberOnRuntimeError);
   /************************************************************************************************/
 }