diff --git a/tests/executables_src/testVirtualHierarchy.cc b/tests/executables_src/testVirtualHierarchy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ad688eb75a2aee4ccab4c5e9d3191be96ce43d6c
--- /dev/null
+++ b/tests/executables_src/testVirtualHierarchy.cc
@@ -0,0 +1,223 @@
+
+#define BOOST_TEST_MODULE testVirtualHierarchy
+#include <boost/test/included/unit_test.hpp>
+
+#include "Application.h"
+#include "ApplicationModule.h"
+#include "ModuleGroup.h"
+#include "TestFacility.h"
+
+using namespace boost::unit_test_framework;
+
+namespace ctk = ChimeraTK;
+
+struct TestModule : public ctk::ApplicationModule {
+  using ctk::ApplicationModule::ApplicationModule;
+
+  ctk::ScalarPushInput<int> input{this, "input", "", {"CS"}};
+  ctk::ScalarOutput<int> output{this, "output", "", {"CS"}};
+
+  void mainLoop() override {}
+};
+
+struct TestModule2 : public ctk::ApplicationModule {
+  using ctk::ApplicationModule::ApplicationModule;
+
+  ctk::ScalarPushInput<int> input2{this, "input2", "", {"CS"}};
+  ctk::ScalarOutput<int> output2{this, "output2", "", {"CS"}};
+
+  void mainLoop() override {}
+};
+
+struct TestModule3 : public ctk::ApplicationModule {
+  using ctk::ApplicationModule::ApplicationModule;
+
+  ctk::ScalarPushInput<int> input3{this, "input3", "", {"CS"}};
+  ctk::ScalarOutput<int> output3{this, "output3", "", {"CS"}};
+
+  void mainLoop() override {}
+};
+
+struct InnerGroup : public ctk::ModuleGroup {
+  using ctk::ModuleGroup::ModuleGroup;
+
+  TestModule innerModule{this, "innerModule", "", ctk::HierarchyModifier::none};
+  TestModule2 innerModuleOneUpAndHide{this, "innerModuleOneUpAndHide", "", ctk::HierarchyModifier::oneUpAndHide};
+  TestModule3 innerModuleMoveToRoot{this, "innerModuleMoveToRoot", "", ctk::HierarchyModifier::moveToRoot};
+  TestModule3 innerModuleSameNameAsGroup{this, "innerModuleGroup", "", ctk::HierarchyModifier::oneLevelUp};
+};
+
+struct OuterGroup : public ctk::ModuleGroup {
+  OuterGroup(EntityOwner* owner, const std::string& name, const std::string& description,
+      ctk::HierarchyModifier modifier, ctk::HierarchyModifier innerGroupModifier = ctk::HierarchyModifier::none)
+  : ModuleGroup{owner, name, description, modifier}, innerGroup{this, "innerModuleGroup", "", innerGroupModifier} {
+    // Here, findTag should give proper exceptions if HierarchyModifiers are used illegally
+    auto allAccessors = getOwner()->findTag(".*").getAccessorListRecursive();
+
+    //    for(auto acc : allAccessors) {
+    //      std::cout << "      -- Accessor: " << acc.getName() << " of module: " << acc.getOwningModule()->getName()
+    //                << std::endl;
+    //    }
+  }
+  virtual ~OuterGroup() {}
+
+  TestModule outerModule{this, "outerModuleInGroup", "", ctk::HierarchyModifier::oneLevelUp};
+  InnerGroup innerGroup;
+};
+
+struct TestApplication : public ctk::Application {
+  TestApplication(ctk::HierarchyModifier outerModuleModifier,
+      ctk::HierarchyModifier innerGroupModifier = ctk::HierarchyModifier::none)
+  : Application("testApp"), outerModuleGroup1{this, "outerModuleGroup1", "", ctk::HierarchyModifier::none,
+                                innerGroupModifier},
+    outerModule{this, "outerModule", "", outerModuleModifier} {}
+  ~TestApplication() { shutdown(); }
+
+  OuterGroup outerModuleGroup1;
+  TestModule outerModule;
+
+  ctk::ControlSystemModule cs;
+
+  void defineConnections() {
+    findTag(".*").connectTo(cs);
+    //cs.dump();
+  }
+};
+
+// Check if HierarchyModifiers are properly handled in the call to findTag
+// in the constructor of TestApplication
+BOOST_AUTO_TEST_CASE(testIllegalModifiers) {
+  std::cout << "testIllegalModifiers" << std::endl;
+
+  {
+    std::cout << "  Creating TestApplication with outerModuleModifier = none " << std::endl;
+    // Should work
+    TestApplication app(ctk::HierarchyModifier::none);
+    ctk::TestFacility test;
+    std::cout << std::endl;
+  }
+
+  {
+    std::cout << "  Creating TestApplication with outerModuleModifier = oneLevelUp " << std::endl;
+    TestApplication app(ctk::HierarchyModifier::oneLevelUp);
+    // Should detect illegal usage of oneLevelUp on first level below Application and throw
+    BOOST_CHECK_THROW(ctk::TestFacility test, ctk::logic_error)
+    std::cout << std::endl;
+  }
+
+  // Should detect illegal usage of oneUpAndHide on first level below Application and throw
+  // Currently leads to memory access violation, should also throw
+  // Bug is described by issue #166.
+//  {
+//    std::cout << "Creating TestApplication with outerModuleModifier = oneUpAndHide " << std::endl;
+//    TestApplication app(ctk::HierarchyModifier::oneUpAndHide);
+//    ctk::TestFacility test;
+//    std::cout << std::endl;
+//  }
+
+  {
+    std::cout << "  Creating TestApplication with outerModuleModifier = moveToRoot " << std::endl;
+    // Should work
+    TestApplication app(ctk::HierarchyModifier::moveToRoot);
+    ctk::TestFacility test;
+    std::cout << std::endl;
+  }
+}
+
+BOOST_AUTO_TEST_CASE(testGetVirtualQualifiedName) {
+  std::cout << "testGetVirtualQualifiedName" << std::endl;
+
+  {
+    TestApplication app(ctk::HierarchyModifier::none);
+    ctk::TestFacility test;
+
+    //app.cs.dump();
+    BOOST_CHECK_EQUAL(app.outerModule.getVirtualQualifiedName(), "/testApp/outerModule");
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.getVirtualQualifiedName(), "/testApp/outerModuleGroup1");
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.outerModule.getVirtualQualifiedName(), "/testApp/outerModuleInGroup");
+    BOOST_CHECK_EQUAL(
+        app.outerModuleGroup1.innerGroup.getVirtualQualifiedName(), "/testApp/outerModuleGroup1/innerModuleGroup");
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModule.getVirtualQualifiedName(),
+        "/testApp/outerModuleGroup1/innerModuleGroup/innerModule");
+
+    //FIXME" getVirtualQualifiedName fails here
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModuleOneUpAndHide.getVirtualQualifiedName(),
+        "/testApp/outerModuleGroup1");
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModuleMoveToRoot.getVirtualQualifiedName(),
+        "/testApp/innerModuleMoveToRoot");
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModuleSameNameAsGroup.getVirtualQualifiedName(),
+        "/testApp/outerModuleGroup1/innerModuleGroup");
+  }
+
+  {
+    TestApplication app(ctk::HierarchyModifier::hideThis);
+    ctk::TestFacility test;
+
+    //    app.cs.dump();
+    BOOST_CHECK_EQUAL(app.outerModule.getVirtualQualifiedName(), "/testApp");
+  }
+
+  {
+    TestApplication app(ctk::HierarchyModifier::moveToRoot, ctk::HierarchyModifier::moveToRoot);
+    ctk::TestFacility test;
+
+    //    app.cs.dump();
+    BOOST_CHECK_EQUAL(app.outerModule.getVirtualQualifiedName(), "/testApp/outerModule");
+    auto virtualisedApp = app.findTag(".*");
+    BOOST_CHECK_NO_THROW(/*[[maybe_unused]]*/ ctk::Module& outerModuleRef = virtualisedApp["outerModule"];)
+    BOOST_CHECK_NO_THROW(
+        /*[[maybe_unused]]*/ ctk::Module& innerModuleMoveToRootRef = virtualisedApp["innerModuleMoveToRoot"];)
+
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.getVirtualQualifiedName(), "/testApp/innerModuleGroup");
+    BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModule.getVirtualQualifiedName(),
+        "/testApp/innerModuleGroup/innerModule");
+  }
+}
+
+BOOST_AUTO_TEST_CASE(testGetNetworkNodesOnVirtualHierarchy) {
+  std::cout << "testGetNetworkNodesOnVirtualHierarchy" << std::endl;
+
+  TestApplication app(ctk::HierarchyModifier::none);
+  ctk::TestFacility test;
+
+  //app.cs.dump();
+
+  auto virtualisedApplication = app.findTag(".*");
+
+  // Need to trip away "/appName/" in the submodule() calls
+  size_t firstModuleOffsetInPath = ("/" + app.getName() + "/").size();
+
+  auto pathToInnerModuleOneUpAndHide =
+      app.outerModuleGroup1.innerGroup.innerModuleOneUpAndHide.getVirtualQualifiedName();
+
+  // Get submodule by the virtual path
+  ctk::Module& module = virtualisedApplication.submodule(
+      {pathToInnerModuleOneUpAndHide.begin() + firstModuleOffsetInPath, pathToInnerModuleOneUpAndHide.end()});
+  auto node2 = module("input2");
+  BOOST_CHECK_EQUAL(node2.getName(), "input2");
+
+  // As a reference, navigate to the module using operator []
+  auto node2Ref = virtualisedApplication["outerModuleGroup1"]("input2");
+  BOOST_CHECK(node2 == node2Ref);
+
+  // Repeat test for other modules: Module moved to root
+  auto pathToInnerModuleMoveToRoot = app.outerModuleGroup1.innerGroup.innerModuleMoveToRoot.getVirtualQualifiedName();
+
+  ctk::Module& innerModuleMoveToRoot = virtualisedApplication.submodule(
+      {pathToInnerModuleMoveToRoot.begin() + firstModuleOffsetInPath, pathToInnerModuleMoveToRoot.end()});
+  auto node3 = innerModuleMoveToRoot("input3");
+
+  auto node3Ref = virtualisedApplication["innerModuleMoveToRoot"]("input3");
+  BOOST_CHECK(node3 == node3Ref);
+
+  // Repeat test for other modules: Module with same name as its group and modifier oneLevelUp
+  auto pathToInnerModuleSameNameAsGroup =
+      app.outerModuleGroup1.innerGroup.innerModuleSameNameAsGroup.getVirtualQualifiedName();
+
+  ctk::Module& innerModuleSameNameAsGroup = virtualisedApplication.submodule(
+      {pathToInnerModuleSameNameAsGroup.begin() + firstModuleOffsetInPath, pathToInnerModuleSameNameAsGroup.end()});
+  node3 = innerModuleSameNameAsGroup("input3");
+
+  node3Ref = virtualisedApplication["outerModuleGroup1"]["innerModuleGroup"]("input3");
+  BOOST_CHECK(node3 == node3Ref);
+}
diff --git a/tests/executables_src/testVirtualModule.cc b/tests/executables_src/testVirtualModule.cc
deleted file mode 100644
index 1c4e53192e48f49bef88cc42d421dc7299104b90..0000000000000000000000000000000000000000
--- a/tests/executables_src/testVirtualModule.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-
-#define BOOST_TEST_MODULE testVirtualModule
-#include <boost/test/included/unit_test.hpp>
-
-#include "Application.h"
-#include "ApplicationModule.h"
-#include "ModuleGroup.h"
-#include "TestFacility.h"
-
-using namespace boost::unit_test_framework;
-
-namespace ctk = ChimeraTK;
-
-struct TestModule : public ctk::ApplicationModule {
-  using ctk::ApplicationModule::ApplicationModule;
-
-  ctk::ScalarPushInput<int> input{this, "input", "", {"CS"}};
-  ctk::ScalarOutput<int> output{this, "output", "", {"CS"}};
-
-  void mainLoop() override {}
-};
-
-struct OuterGroup : public ctk::ModuleGroup {
-  OuterGroup(
-      EntityOwner* owner, const std::string& name, const std::string& description, ctk::HierarchyModifier modifier)
-  : ModuleGroup(owner, name, description, modifier) {
-    auto allAccessors = getOwner()->findTag(".*").getAccessorListRecursive();
-
-    for(auto acc : allAccessors) {
-      std::cout << "      -- Accessor: " << acc.getName() << " of module: " << acc.getOwningModule()->getName()
-                << std::endl;
-    }
-  }
-  virtual ~OuterGroup() {}
-
-  TestModule outerModule{this, "outerModuleInGroup", "", ctk::HierarchyModifier::oneLevelUp};
-
-  struct InnerGroup : public ctk::ModuleGroup {
-    using ctk::ModuleGroup::ModuleGroup;
-
-    TestModule innerModule{this, "innerModule", "", ctk::HierarchyModifier::hideThis};
-
-  } innerGroup{this, "innerModuleGroup", ""};
-};
-
-struct TestApplication : public ctk::Application {
-  TestApplication(ctk::HierarchyModifier outerModuleModifier)
-  : Application("testApp"), outerModule{this, "outerModule", "", outerModuleModifier} {}
-  ~TestApplication() { shutdown(); }
-
-  OuterGroup outerModuleGroup1{this, "outerModuleGroup", "", ctk::HierarchyModifier::none};
-
-  TestModule outerModule;
-
-  ctk::ControlSystemModule cs;
-
-  void defineConnections() {
-    findTag(".*").connectTo(cs);
-    cs.dump();
-  }
-};
-
-BOOST_AUTO_TEST_CASE(testIllegalModifiers) {
-  // Just test if the app comes up without without
-  std::cout << "testIllegalModifiers" << std::endl;
-
-  {
-    std::cout << "Creating TestApplication with outerModuleModifier = none " << std::endl;
-    // Should work
-    TestApplication app(ctk::HierarchyModifier::none);
-    ctk::TestFacility test;
-    std::cout << std::endl;
-  }
-
-  {
-    std::cout << "Creating TestApplication with outerModuleModifier = oneLevelUp " << std::endl;
-    TestApplication app(ctk::HierarchyModifier::oneLevelUp);
-    // Should detect usage of oneLevelUp and throw
-    BOOST_CHECK_THROW(ctk::TestFacility test, ctk::logic_error);
-    std::cout << std::endl;
-  }
-
-  // Currently leads to memory access violation, should also throw
-//  {
-//    std::cout << "Creating TestApplication with outerModuleModifier = oneUpAndHide " << std::endl;
-//    TestApplication app(ctk::HierarchyModifier::oneUpAndHide);
-//    ctk::TestFacility test;
-//    std::cout << std::endl;
-//  }
-
-    {
-      std::cout << "Creating TestApplication with outerModuleModifier = moveToRoot " << std::endl;
-      // Should work
-      TestApplication app(ctk::HierarchyModifier::moveToRoot);
-      ctk::TestFacility test;
-      std::cout << std::endl;
-    }
-}