diff --git a/src/Command/ControllersCommand.php b/src/Command/ControllersCommand.php
index 79d6882ed3f0a7053499a6be549220edeaf20204..51e95aad86a826f805e0345085a0e40d04d22b62 100644
--- a/src/Command/ControllersCommand.php
+++ b/src/Command/ControllersCommand.php
@@ -355,9 +355,9 @@ class ControllersCommand extends Command
         $controllers = [];
         $plugin = $this->param('plugin');
         $namespace = Configure::read('App.namespace');
-        $appControllerMethods = get_class_methods(
-            $namespace."\\Controller\\AppController"
-        );
+        $appControllerMethods = class_exists($namespace."\\Controller\\AppController")
+            ? get_class_methods($namespace."\\Controller\\AppController")
+            : [];
         if (!$appControllerMethods) {
             $appControllerMethods = get_class_methods(
                 $namespace."\\Controller\\Controller"
diff --git a/src/Command/RolesPermsCommand.php b/src/Command/RolesPermsCommand.php
index d8c6123ba065eebd782b325cd7e8e9a11c870a78..1abfa2bb32cc3f119a8964f54f07523286c39ec6 100644
--- a/src/Command/RolesPermsCommand.php
+++ b/src/Command/RolesPermsCommand.php
@@ -95,7 +95,10 @@ class RolesPermsCommand extends Command
         $controllers = [];
         $apis = [];
         $basePath = Configure::read('App.namespace') . '\\Controller\\';
-        $appControllerMethods = get_class_methods($basePath . "AppController");
+
+        $appControllerMethods = class_exists($basePath . "AppController")
+            ? get_class_methods($basePath . "AppController")
+            : [];
         if (!$appControllerMethods) {
             $appControllerMethods = get_class_methods($basePath . "Controller");
         }
diff --git a/src/Command/XsdExploreCommand.php b/src/Command/XsdExploreCommand.php
index 1d6f2c093519bf542bb1de425b273e6734af7c1b..b78cada715cd4514948f735927fc711a14b9dee5 100644
--- a/src/Command/XsdExploreCommand.php
+++ b/src/Command/XsdExploreCommand.php
@@ -240,7 +240,10 @@ class XsdExploreCommand extends Command
                 // Récupère les enfants spécifiques à cette extension
                 $sequenceOrChoiceNodeList = $xpath->query(".//$prefix:sequence | .//$prefix:choice", $extensionNode);
                 foreach ($sequenceOrChoiceNodeList as $container) {
-                    $children = array_merge($children, $this->parseContainer($container, $xpath, $prefix, $seenElements));
+                    $children = array_merge(
+                        $children,
+                        $this->parseContainer($container, $xpath, $prefix, $seenElements)
+                    );
                 }
             }
 
@@ -356,6 +359,84 @@ class XsdExploreCommand extends Command
         return $index;
     }
 
+    /**
+     * Liste le contenu pour un element
+     * @param DOMElement $child
+     * @param string     $prefix
+     * @param array      $seenElements
+     * @param array      $children
+     * @return void
+     */
+    private function parseContainerElement(
+        DOMElement $child,
+        string $prefix,
+        array &$seenElements,
+        array &$children
+    ): void {
+        $elementName = $child->getAttribute('name');
+        $typeName = $child->getAttribute('type');
+        if ($elementName && !in_array($elementName, $seenElements, true)) {
+            /** @var DOMElement $parent */
+            $parent = $child->parentNode;
+            $beforeCardinality = '';
+            if ($parent->nodeName === "$prefix:choice") {
+                $minOccurs = ($parent->getAttribute('minOccurs') !== '') ? $parent->getAttribute('minOccurs') : '1';
+                $maxOccurs = ($parent->getAttribute('maxOccurs') !== '') ? $parent->getAttribute('maxOccurs') : '1';
+                if ($maxOccurs === 'unbounded') {
+                    $maxOccurs = 'n';
+                }
+                $index = $this->getChoiceIndex($parent);
+                $beforeCardinality = "choice[$index]:$minOccurs..$maxOccurs - ";
+            }
+
+            $minOccurs = ($child->getAttribute('minOccurs') !== '') ? $child->getAttribute('minOccurs') : '1';
+            $maxOccurs = ($child->getAttribute('maxOccurs') !== '') ? $child->getAttribute('maxOccurs') : '1';
+            if ($maxOccurs === 'unbounded') {
+                $maxOccurs = 'n';
+            }
+            $cardinality = "$beforeCardinality$minOccurs..$maxOccurs";
+
+            if (!$typeName) {
+                $typeName = 'Unknown';  // Définit un type inconnu si aucun n'est trouvé
+            }
+
+            // Ajouter le nom de l'élément, la cardinalité et le type
+            $children[] = ['name' => $elementName, 'cardinality' => $cardinality, 'type' => $typeName];
+
+            $seenElements[] = $elementName;
+        }
+    }
+
+    /**
+     * Liste le contenu pour un groupe
+     * @param DOMElement $child
+     * @param string     $prefix
+     * @param DOMXPath   $xpath
+     * @param array      $seenElements
+     * @param array      $children
+     * @return void
+     */
+    private function parseContainerGroup(
+        DOMElement $child,
+        string $prefix,
+        DOMXPath $xpath,
+        array &$seenElements,
+        array &$children
+    ): void {
+        $groupName = $child->getAttribute('ref');
+        if ($groupName && !in_array($groupName, $seenElements, true)) {
+            // Traite les groupes uniquement pour éviter la récursion
+            $groupNodeList = $xpath->query("//$prefix:group[@name='$groupName']");
+            if ($groupNodeList->length > 0) {
+                $groupNode = $groupNodeList->item(0);
+                $children = array_merge(
+                    $children,
+                    $this->parseGroup($groupNode, $xpath, $prefix, $seenElements)
+                );
+            }
+        }
+    }
+
     /**
      * Analyse un conteneur (sequence ou choice) pour extraire les noms des nœuds enfants possibles au premier niveau.
      *
@@ -376,50 +457,9 @@ class XsdExploreCommand extends Command
 
         foreach ($childNodeList as $child) {
             if ($child->nodeName === "$prefix:element") {
-                $elementName = $child->getAttribute('name');
-                $typeName = $child->getAttribute('type');
-                if ($elementName && !in_array($elementName, $seenElements, true)) {
-                    $parent = $child->parentNode;
-                    $beforeCardinality = '';
-                    if ($parent->nodeName === "$prefix:choice") {
-                        $minOccurs = ($parent->getAttribute('minOccurs') !== '') ? $parent->getAttribute('minOccurs') : '1';
-                        $maxOccurs = ($parent->getAttribute('maxOccurs') !== '') ? $parent->getAttribute('maxOccurs') : '1';
-                        if ($maxOccurs === 'unbounded') {
-                            $maxOccurs = 'n';
-                        }
-                        $index = $this->getChoiceIndex($parent);
-                        $beforeCardinality = "choice[$index]:$minOccurs..$maxOccurs - ";
-                    }
-
-                    $minOccurs = ($child->getAttribute('minOccurs') !== '') ? $child->getAttribute('minOccurs') : '1';
-                    $maxOccurs = ($child->getAttribute('maxOccurs') !== '') ? $child->getAttribute('maxOccurs') : '1';
-                    if ($maxOccurs === 'unbounded') {
-                        $maxOccurs = 'n';
-                    }
-                    $cardinality = "$beforeCardinality$minOccurs..$maxOccurs";
-
-                    if (!$typeName) {
-                        $typeName = 'Unknown';  // Définit un type inconnu si aucun n'est trouvé
-                    }
-
-                    // Ajouter le nom de l'élément, la cardinalité et le type
-                    $children[] = ['name' => $elementName, 'cardinality' => $cardinality, 'type' => $typeName];
-
-                    $seenElements[] = $elementName;
-                }
+                $this->parseContainerElement($child, $prefix, $seenElements, $children);
             } elseif ($child->nodeName === "$prefix:group") {
-                $groupName = $child->getAttribute('ref');
-                if ($groupName && !in_array($groupName, $seenElements, true)) {
-                    // Traite les groupes uniquement pour éviter la récursion
-                    $groupNodeList = $xpath->query("//$prefix:group[@name='$groupName']");
-                    if ($groupNodeList->length > 0) {
-                        $groupNode = $groupNodeList->item(0);
-                        $children = array_merge(
-                            $children,
-                            $this->parseGroup($groupNode, $xpath, $prefix, $seenElements)
-                        );
-                    }
-                }
+                $this->parseContainerGroup($child, $prefix, $xpath, $seenElements, $children);
             }
         }
 
diff --git a/src/Error/AppExceptionRenderer.php b/src/Error/AppExceptionRenderer.php
index 2bd64bbc7e0b89f739eab4c33b2423ead9aa623f..6945b4de3e1e173401a0934a6490256489061f48 100644
--- a/src/Error/AppExceptionRenderer.php
+++ b/src/Error/AppExceptionRenderer.php
@@ -104,12 +104,15 @@ class AppExceptionRenderer extends WebExceptionRenderer
         } catch (MissingTemplateException $e) {
             $builder = $this->controller->viewBuilder();
             if ($builder->getTemplatePath() === 'Error') {
-                return $this->_outputMessage(
-                    $this->error instanceof Exception
-                    && ((string)$this->error->getCode())[0] === '4'
-                        ? static::$plugin . 'error400'
-                        : static::$plugin . 'error500'
-                );
+                $nextTemplate = $this->error instanceof Exception
+                && ((string)$this->error->getCode())[0] === '4'
+                    ? static::$plugin . 'error400'
+                    : static::$plugin . 'error500';
+                if ($nextTemplate === $template) {
+                    debug($e); // seul moyen de comprendre pourquoi le render à échoué
+                    return $this->_outputMessageSafe(static::$plugin . 'error500');
+                }
+                return $this->_outputMessage($nextTemplate);
             }
             try {
                 $this->error = $e;
diff --git a/src/MinkSuite/MinkSuite.php b/src/MinkSuite/MinkSuite.php
index 3ac8416d0c30bf25fb5881b760c24417f96e40f0..44a10216fb6ea03a9e915bbb429370303f740cf5 100644
--- a/src/MinkSuite/MinkSuite.php
+++ b/src/MinkSuite/MinkSuite.php
@@ -12,7 +12,6 @@ use Behat\Mink\Mink;
 use Behat\Mink\Session;
 use Cake\Core\Configure;
 use Cake\Error\Debugger;
-use Cake\Utility\Hash;
 use DMore\ChromeDriver\HttpClient;
 use ErrorException;
 use Exception;
diff --git a/src/Utility/Session.php b/src/Utility/Session.php
index 7b3107f0f96fd9143314ffa8319adec3a8a73db0..48f2ff66ccf7b641c92f6ed382725b41ddd745b3 100644
--- a/src/Utility/Session.php
+++ b/src/Utility/Session.php
@@ -46,6 +46,7 @@ class Session
      * session
      * @param int|string $user_id
      * @throws ZMQSocketException
+     * @throws Exception
      */
     public static function emitReset($user_id)
     {
diff --git a/src/View/Helper/AjaxPaginatorHelper.php b/src/View/Helper/AjaxPaginatorHelper.php
index 6c46f9f042ccba7f9f33754a0344146c5bf18d8e..0190603b78ea7b35f6167e62f7676d9c05fceca4 100644
--- a/src/View/Helper/AjaxPaginatorHelper.php
+++ b/src/View/Helper/AjaxPaginatorHelper.php
@@ -110,7 +110,7 @@ class AjaxPaginatorHelper extends PaginatorHelper implements ObjectHelperInterfa
      * @param array  $params
      * @return ObjectInterface|AjaxPaginator
      */
-    public function create(string $id, array $params = []): ObjectInterface
+    public function create(string $id, array $params = []): AjaxPaginator
     {
         return new AjaxPaginator($this, $id);
     }
diff --git a/src/View/Helper/FilterHelper.php b/src/View/Helper/FilterHelper.php
index baa8a7a4ec0e0152741926dade1533dcefcb2d9f..06246f2fbaf8e6ed50b7cd815ad086a257bfe16b 100644
--- a/src/View/Helper/FilterHelper.php
+++ b/src/View/Helper/FilterHelper.php
@@ -50,7 +50,7 @@ class FilterHelper extends Helper implements ObjectHelperInterface
      * @param array  $params
      * @return ObjectInterface|Filter
      */
-    public function create(string $id, array $params = []): ObjectInterface
+    public function create(string $id, array $params = []): Filter
     {
         return new Filter($this, $id);
     }
diff --git a/src/View/Helper/ModalFormHelper.php b/src/View/Helper/ModalFormHelper.php
index 1bc76439bb49a4480aedb1f7fb5731c3f8ca59dd..c12542977d39f8b83c4aee6fc76d0023f83dcec8 100644
--- a/src/View/Helper/ModalFormHelper.php
+++ b/src/View/Helper/ModalFormHelper.php
@@ -46,7 +46,7 @@ class ModalFormHelper extends Helper implements ObjectHelperInterface
      * @param array  $params
      * @return ObjectInterface|ModalForm
      */
-    public function create(string $id, array $params = []): ObjectInterface
+    public function create(string $id, array $params = []): ModalForm
     {
         return new ModalForm($this, $id, $params);
     }
diff --git a/src/View/Helper/ModalViewHelper.php b/src/View/Helper/ModalViewHelper.php
index ad7478fcfb561b8d9ed95a4f4bb359c27e9efce8..2e6f2e1db54df39e35347d82f15e30d20731234d 100644
--- a/src/View/Helper/ModalViewHelper.php
+++ b/src/View/Helper/ModalViewHelper.php
@@ -46,7 +46,7 @@ class ModalViewHelper extends Helper implements ObjectHelperInterface
      * @param array  $params
      * @return ObjectInterface|ModalView
      */
-    public function create(string $id, array $params = []): ObjectInterface
+    public function create(string $id, array $params = []): ModalView
     {
         return new ModalView($this, $id, $params);
     }
diff --git a/src/View/Helper/TableHelper.php b/src/View/Helper/TableHelper.php
index 6927b3b23d6d065ba6184f114e288f1776ffd94c..94967b640686d519435865017fc274cb0f82ccb6 100644
--- a/src/View/Helper/TableHelper.php
+++ b/src/View/Helper/TableHelper.php
@@ -72,7 +72,7 @@ class TableHelper extends Helper implements ObjectHelperInterface
      * @return ObjectInterface|Table
      * @throws Exception
      */
-    public function create(string $id, array $params = []): ObjectInterface
+    public function create(string $id, array $params = []): Table
     {
         return new Table($this, $id, $params);
     }
diff --git a/src/View/Helper/TabsHelper.php b/src/View/Helper/TabsHelper.php
index 52a2a3480157b1d7215826faa813067d90a4faaf..25717f68ba690d1445bc762685cde7a9721d453d 100644
--- a/src/View/Helper/TabsHelper.php
+++ b/src/View/Helper/TabsHelper.php
@@ -37,7 +37,7 @@ class TabsHelper extends Helper implements ObjectHelperInterface
      * @return ObjectInterface|Tabs
      * @throws Exception
      */
-    public function create(string $id, array $params = []): ObjectInterface
+    public function create(string $id, array $params = []): Tabs
     {
         return new Tabs($this, $id, $params);
     }
diff --git a/tests/TestCase/Database/Type/DateTimeTypeTest.php b/tests/TestCase/Database/Type/DateTimeTypeTest.php
index ae5a74ed316304d9e7a1ad12675a05e4b9e06f64..2f1f813fcea110589da000f2393cff2ca042d0d9 100644
--- a/tests/TestCase/Database/Type/DateTimeTypeTest.php
+++ b/tests/TestCase/Database/Type/DateTimeTypeTest.php
@@ -25,18 +25,18 @@ class DateTimeTypeTest extends TestCase
         /** @var Time $result */
         $result = $this->invokeMethod($type, '_parseValue', ['1950-01-01']);
         $this->assertInstanceOf(Time::class, $result);
-        $this->assertEquals('1950-01-01T00:00:00+00:00', $result->format(Time::ATOM));
+        $this->assertStringContainsString('1950-01-01T00:00:00', $result->format(DateTimeInterface::ATOM));
 
         $result = $this->invokeMethod($type, '_parseValue', ['1950-01-01 11:50']);
         $this->assertInstanceOf(Time::class, $result);
-        $this->assertEquals('1950-01-01T11:50:00+00:00', $result->format(Time::ATOM));
+        $this->assertEquals('1950-01-01T11:50:00+00:00', $result->format(DateTimeInterface::ATOM));
 
         $result = $this->invokeMethod($type, '_parseValue', ['1950-01-01T11:50:22+0200']);
         $this->assertInstanceOf(Time::class, $result);
-        $this->assertEquals('1950-01-01T11:50:22+02:00', $result->format(Time::ATOM));
+        $this->assertEquals('1950-01-01T11:50:22+02:00', $result->format(DateTimeInterface::ATOM));
 
         $result = $this->invokeMethod($type, '_parseValue', [new Time('08/07/2013 09:09')]);
         $this->assertInstanceOf(DateTimeInterface::class, $result);
-        $this->assertEquals('2013-08-07T09:09:00+00:00', $result->format(Time::ATOM));
+        $this->assertEquals('2013-08-07T09:09:00+00:00', $result->format(DateTimeInterface::ATOM));
     }
 }
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index c7295f828e2ee8e8fbee1c304357988ccaa4cbbc..56bde1f7665cd8ec3fa33ed228799679e422a6d2 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -34,6 +34,7 @@ if (!is_dir(TMP_TESTDIR)) {
 define('BROWSER_SESSION', 'phpunit');
 
 Configure::write('App.paths.plugins', [TESTS]);
+Configure::write('App.paths.templates', [ROOT . '/templates/', TESTS . 'templates/']);
 
 // create schema
 $migrator = new Migrator();
diff --git a/tests/templates/layout/default.php b/tests/templates/layout/default.php
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391