diff --git a/tests/executables_src/testVariableGroup.cc b/tests/executables_src/testVariableGroup.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6604b5da986db3a4f083709fa8a2218bcc6ec779
--- /dev/null
+++ b/tests/executables_src/testVariableGroup.cc
@@ -0,0 +1,195 @@
+/*
+ * testVariableGroup.cc
+ *
+ *  Created on: Nov 8, 2016
+ *      Author: Martin Hierholzer
+ */
+
+#include <future>
+#include <chrono>
+
+#define BOOST_TEST_MODULE testVariableGroup
+
+#include <boost/test/included/unit_test.hpp>
+#include <boost/test/test_case_template.hpp>
+#include <boost/mpl/list.hpp>
+
+#include "ScalarAccessor.h"
+#include "ApplicationModule.h"
+#include "VariableGroup.h"
+
+using namespace boost::unit_test_framework;
+namespace ctk = ChimeraTK;
+
+/*********************************************************************************************************************/
+/* the ApplicationModule for the test is a template of the user type */
+
+struct TestModule : public ctk::ApplicationModule {
+  
+  struct MixedGroup : public ctk::VariableGroup {
+    SCALAR_INPUT(int, consumingPush, "MV/m", ctk::UpdateMode::push);
+    SCALAR_INPUT(int, consumingPush2, "MV/m", ctk::UpdateMode::push);
+    SCALAR_INPUT(int, consumingPush3,  "MV/m", ctk::UpdateMode::push);
+    SCALAR_INPUT(int, consumingPoll, "MV/m", ctk::UpdateMode::poll);
+    SCALAR_INPUT(int, consumingPoll2, "MV/m", ctk::UpdateMode::poll);
+    SCALAR_INPUT(int, consumingPoll3, "MV/m", ctk::UpdateMode::poll);
+  };
+  MixedGroup mixedGroup;
+
+  SCALAR_OUTPUT(int, feedingPush, "MV/m");
+  SCALAR_OUTPUT(int, feedingPush2, "MV/m");
+  SCALAR_OUTPUT(int, feedingPush3,  "MV/m");
+  SCALAR_OUTPUT(int, feedingPoll, "MV/m");
+  SCALAR_OUTPUT(int, feedingPoll2, "MV/m");
+  SCALAR_OUTPUT(int, feedingPoll3, "MV/m");
+  
+  void mainLoop() {}
+};
+
+/*********************************************************************************************************************/
+/* dummy application */
+
+class TestApplication : public ctk::Application {
+public:
+  TestApplication() : Application("test suite") {}
+  ~TestApplication() { shutdown(); }
+  
+  using Application::makeConnections;     // we call makeConnections() manually in the tests to catch exceptions etc.
+  void initialise() {}                    // the setup is done in the tests
+  
+  TestModule testModule;
+};
+
+/*********************************************************************************************************************/
+/* test trigger by app variable when connecting a polled device register to an app variable */
+
+BOOST_AUTO_TEST_CASE( testMixedGroup ) {
+  std::cout << "*********************************************************************************************************************" << std::endl;
+  std::cout << "==> testMixedGroup" << std::endl;
+  
+  TestApplication app;
+  
+  app.testModule.feedingPush >> app.testModule.mixedGroup.consumingPush;
+  app.testModule.feedingPush2 >> app.testModule.mixedGroup.consumingPush2;
+  app.testModule.feedingPush3 >> app.testModule.mixedGroup.consumingPush3;
+  app.testModule.feedingPoll >> app.testModule.mixedGroup.consumingPoll;
+  app.testModule.feedingPoll2 >> app.testModule.mixedGroup.consumingPoll2;
+  app.testModule.feedingPoll3 >> app.testModule.mixedGroup.consumingPoll3;
+  
+  app.run();
+  
+  // single theaded test
+  app.testModule.feedingPush = 0;
+  app.testModule.feedingPush2 = 42;
+  app.testModule.feedingPush3 = 120;
+  app.testModule.feedingPoll = 10;
+  app.testModule.feedingPoll2 = 11;
+  app.testModule.feedingPoll3 = 12;
+  app.testModule.feedingPoll.write();
+  app.testModule.feedingPoll2.write();
+  app.testModule.feedingPoll3.write();
+  
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 0);
+
+  // test a single write
+  app.testModule.feedingPush2.write();
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 0);
+  app.testModule.mixedGroup.readAny();
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 42);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
+
+  // two changes at a time
+  app.testModule.feedingPush2 = 666;
+  app.testModule.feedingPush2.write();
+  app.testModule.feedingPush3.write();
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 42);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
+  app.testModule.mixedGroup.readAny();
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
+
+  // launch readAny() asynchronously and make sure it does not yet receive anything
+  auto futRead = std::async(std::launch::async, [&app]{ app.testModule.mixedGroup.readAny(); });
+  BOOST_CHECK(futRead.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
+
+  // write something  
+  app.testModule.feedingPush = 3;
+  app.testModule.feedingPush.write();
+  
+  // check that the group now receives the just written value
+  BOOST_CHECK(futRead.wait_for(std::chrono::milliseconds(2000)) == std::future_status::ready);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
+  
+  // launch another readAny() asynchronously and make sure it does not yet receive anything
+  auto futRead2 = std::async(std::launch::async, [&app]{ app.testModule.mixedGroup.readAny(); });
+  BOOST_CHECK(futRead2.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
+  
+  // write to the poll-type variables
+  app.testModule.feedingPoll = 66;
+  app.testModule.feedingPoll.write();
+  app.testModule.feedingPoll2 = 77;
+  app.testModule.feedingPoll2.write();
+  app.testModule.feedingPoll3 = 88;
+  app.testModule.feedingPoll3.write();
+  
+  // make sure readAny still does not receive anything
+  BOOST_CHECK(futRead2.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
+  
+  // write something to the push-type variables
+  app.testModule.feedingPush2 = 123;
+  app.testModule.feedingPush2.write();
+  
+  // check that the group now receives the just written values
+  BOOST_CHECK(futRead2.wait_for(std::chrono::milliseconds(2000)) == std::future_status::ready);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 123);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 66);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 77);
+  BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 88);
+}