|
JustAnotherDnDGame 0.1.0
Jeu de rôle tactique au d20, vue de dessus, en C++/Qt
|
1051 cas de test, générés depuis les blocs \castest{...} du code par scripts/generate_cahier_test.py (ne pas éditer directement — modifier le commentaire du test concerné puis relancer le script). Organisés ici selon l'arborescence de Source/Test/ pour rester lisibles page par page.
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EngineTest.VersionNonVide (Majeur) Source/Test/Unit/Core/test_core.cpp:15 | Vérifie que la version du moteur n'est pas vide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que engine.version().empty() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EncounterTest.UnAllerRetourRestitueLEtatDExploration (Critique) Source/Test/Unit/Core/Combat/test_encounter.cpp:52 | Un aller-retour exploration -> combat -> exploration restitue l'etat. | 1. Relever un etat d'exploration. 2. Engager une rencontre. 3. La terminer par une victoire. | Vérifie que apres.captured est vrai. Vérifie que apres.playerPosition.x vaut avant.playerPosition.x (comparaison flottante). Vérifie que apres.playerPosition.y vaut avant.playerPosition.y (comparaison flottante). Vérifie que apres.playerFacing.x vaut avant.playerFacing.x (comparaison flottante). Vérifie que apres.playerFacing.y vaut avant.playerFacing.y (comparaison flottante). Vérifie que apres.cameraPosition.x vaut avant.cameraPosition.x (comparaison flottante). Vérifie que apres.cameraPosition.y vaut avant.cameraPosition.y (comparaison flottante). |
| EncounterTest.UnEnnemiVaincuNeReapparaitPas (Critique) Source/Test/Unit/Core/Combat/test_encounter.cpp:80 | Un ennemi vaincu ne reapparait pas. | 1. Gagner une rencontre portant une cle de drapeau. 2. Interroger les drapeaux. | Vérifie que core::encounterAlreadyCleared(drapeaux, cle) est faux. Vérifie que drapeaux.isSet(cle) est vrai. Vérifie que core::encounterAlreadyCleared(drapeaux, cle) est vrai. |
| EncounterTest.UneFuiteNeMarquePasLEnnemiVaincu (Critique) Source/Test/Unit/Core/Combat/test_encounter.cpp:104 | Une fuite ne marque pas l'ennemi vaincu. | 1. Engager une rencontre portant une cle de drapeau. 2. La terminer par une fuite, puis par une defaite. | Vérifie que drapeaux.isSet(cle) est faux. Vérifie que apresFuite.captured est vrai. Vérifie que drapeaux.isSet(cle) est faux. |
| EncounterTest.UneRencontreSansCleSeRedeclenche (Majeur) Source/Test/Unit/Core/Combat/test_encounter.cpp:129 | Une rencontre sans cle de drapeau se redeclenche. | 1. Gagner une rencontre sans cle de drapeau. | Vérifie que core::encounterAlreadyCleared(drapeaux, "") est faux. |
| EncounterTest.LesCombattantsSePlacentRelativementAuDeclencheur (Critique) Source/Test/Unit/Core/Combat/test_encounter.cpp:149 | Les combattants se placent relativement au declencheur. | 1. Placer la meme rencontre a deux endroits differents. | Vérifie que ici.size() vaut 2U. Vérifie que ici[0].position.column vaut 10. Vérifie que ici[0].position.row vaut 9. Vérifie que ici[1].position.column vaut 12. Vérifie que ici[1].position.row vaut 11. Vérifie que ailleurs.size() vaut 2U. Vérifie que ailleurs[rang].creatureId vaut ici[rang].creatureId. Vérifie que ailleurs[rang].position.column - ici[rang].position.column vaut 30. Vérifie que ailleurs[rang].position.row - ici[rang].position.row vaut -8. |
| EncounterTest.UneRencontreNonFuyableLeDeclare (Majeur) Source/Test/Unit/Core/Combat/test_encounter.cpp:179 | Une rencontre non fuyable le declare. | 1. Engager une rencontre declaree non fuyable. | Vérifie que core::beginEncounter(rencontre(true), exploration(), {}, "").escapable est vrai. Vérifie que core::beginEncounter(rencontre(false), exploration(), {}, "").escapable est faux. |
| EncounterTest.LeCatalogueLivreSeCharge (Majeur) Source/Test/Unit/Core/Combat/test_encounter.cpp:195 | Le catalogue de rencontres livre se charge. | 1. Charger Source/Elements/Rpg/encounters. | Vérifie que catalogue.errors.empty() est vrai. Vérifie que catalogue.encounters.empty() est faux. Vérifie que combat.id.empty() est faux. Vérifie que combat.name.empty() est faux. Vérifie que combat.combatants.empty() est faux. Vérifie que combattant.creatureId.empty() est faux. Vérifie que catalogue.find("nuee-de-rats") diffère de nullptr. Vérifie que catalogue.find("rencontre-qui-n-existe-pas") vaut nullptr. |
| EncounterTest.UnInstantaneNonReleveSeDistingueDeLOrigine (Majeur) Source/Test/Unit/Core/Combat/test_encounter.cpp:223 | Un instantane non releve se distingue de l'origine. | 1. Construire un instantane par defaut. | Vérifie que vide.captured est faux. |
| EncounterTest.UnEnnemiPosePorteUneCleUneZoneNonN (?) Source/Test/Unit/Core/Combat/test_encounter.cpp:239 | Un ennemi pose porte une cle, une zone n'en porte pas. cat Unitaire · Combat crit Critique etapes 1. Lire une entite de rencontre posee. 2. Lire la meme avec respawns. attendu La premiere porte une cle fabriquee, la seconde aucune. | Vérifie que declencheur.has_value() est vrai. Vérifie que declencheur->encounterId vaut "nuee-de-rats". Vérifie que declencheur->position.column vaut 5. Vérifie que declencheur->defeatFlagKey.empty() est faux. Vérifie que declencheurZone.has_value() est vrai. Vérifie que declencheurZone->defeatFlagKey.empty() est vrai. | |
| EncounterTest.DeuxDeclencheursNePartagentJamaisLeurCle (?) Source/Test/Unit/Core/Combat/test_encounter.cpp:270 | Deux declencheurs ne partagent jamais leur cle. cat Unitaire · Combat crit Critique etapes 1. Lire deux entites de rencontre a des cases differentes de la meme carte. 2. Lire la meme case sur deux cartes differentes. attendu Les cles different dans les deux cas. | Vérifie que a && b && ailleurs est vrai. Vérifie que a->defeatFlagKey diffère de b->defeatFlagKey. Vérifie que a->defeatFlagKey diffère de ailleurs->defeatFlagKey. | |
| EncounterTest.CeQuiNEstPasUnDeclencheurNEnDevientPasUn (?) Source/Test/Unit/Core/Combat/test_encounter.cpp:296 | Ce qui n'est pas un declencheur n'en devient pas un. cat Unitaire · Combat crit Majeur etapes 1. Lire une entite d'un autre type. 2. Lire une entite de rencontre sans encounterId. attendu Aucun declencheur dans les deux cas. | Vérifie que core::encounterTriggerFor(coffre, "grotte").has_value() est faux. Vérifie que core::encounterTriggerFor(sansRencontre, "grotte").has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| JsonDocumentPosition.ConvertitUnDecalageEnLigneEtColonne (Majeure) Source/Test/Unit/Core/Data/test_json_document.cpp:35 | Une position d'erreur est exprimee en ligne et colonne. | 1. Convertir le decalage du premier octet de la 3e ligne d'un texte connu. | Vérifie que position.line vaut 3. Vérifie que position.column vaut 1. |
| JsonDocumentPosition.RendUnePositionInconnueHorsDuTexte (Mineure) Source/Test/Unit/Core/Data/test_json_document.cpp:54 | Un decalage aberrant ne produit pas de position fausse. | 1. Convertir un decalage superieur a la taille du texte. | Vérifie que position.line vaut 0. Vérifie que position.column vaut 0. |
| JsonDocument.LitUnObjetBienForme (Critique) Source/Test/Unit/Core/Data/test_json_document.cpp:74 | Un document JSON valide se lit sans erreur. | 1. Lire une chaine JSON contenant une version et un champ. | Vérifie que doc.ok() est vrai. Vérifie que doc.version vaut 1. Vérifie que doc.root.at("a").get<int>() vaut 2. |
| JsonDocument.VersionAbsenteVautUn (Majeure) Source/Test/Unit/Core/Data/test_json_document.cpp:90 | Un champ de version absent vaut 1. | 1. Lire un document sans champ de version, avec une version geree de 3. | Vérifie que doc.ok() est vrai. Vérifie que doc.version vaut 1. |
| JsonDocument.RefuseUneVersionPlusRecenteQueLeLecteur (Critique) Source/Test/Unit/Core/Data/test_json_document.cpp:106 | Une version de format non geree est refusee, pas lue au mieux. | 1. Lire un document de version 4 avec une version geree de 3. | Vérifie que doc.ok() est faux. Vérifie que doc.error vaut core::JsonReadError::UnsupportedVersion. Vérifie que doc.message.find('4') diffère de std::string::npos. Vérifie que doc.message.find('3') diffère de std::string::npos. |
| JsonDocument.RefuseUneRacineQuiNEstPasUnObjet (Majeure) Source/Test/Unit/Core/Data/test_json_document.cpp:126 | Un document dont la racine est un tableau est refuse. | 1. Lire un document dont la racine est un tableau. | Vérifie que doc.ok() est faux. Vérifie que doc.error vaut core::JsonReadError::ParseError. |
| JsonDocument.SitueLErreurDeSyntaxeALaLigne (Critique) Source/Test/Unit/Core/Data/test_json_document.cpp:142 | Une erreur de syntaxe nomme le fichier et la ligne. | 1. Lire un document dont la 3e ligne porte une virgule en trop, en nommant l'origine. | Vérifie que doc.ok() est faux. Vérifie que doc.error vaut core::JsonReadError::ParseError. Vérifie que doc.position.line vaut 3. Vérifie que doc.message.find("essai.json:3") diffère de std::string::npos. |
| JsonDocument.NeLevePasSurUnFichierAbsent (Critique) Source/Test/Unit/Core/Data/test_json_document.cpp:163 | Un fichier absent est un echec decrit, pas une exception. | 1. Lire un fichier qui n'existe pas. | Vérifie que doc.ok() est faux. Vérifie que doc.error vaut core::JsonReadError::FileNotFound. |
| JsonDocument.NommeLeFichierDansSesMessages (Majeure) Source/Test/Unit/Core/Data/test_json_document.cpp:180 | Un echec de lecture de fichier nomme ce fichier. | 1. Lire une fixture JSON tronquee depuis le disque. | Vérifie que doc.ok() est faux. Vérifie que doc.message.find("tronque.json") diffère de std::string::npos. |
| FixtureJson.ProduitLaCategorieAnnoncee (Majeure) Source/Test/Unit/Core/Data/test_json_document.cpp:220 | Chaque fixture JSON produit la categorie d'echec attendue. | 1. Lire chacune des six fixtures de Fixtures/Json. 2. Comparer la categorie d'echec obtenue a celle annoncee par le nom du fichier. | Vérifie que doc.error vaut attente.attendu. Vérifie que doc.message.empty() est faux. |
| FixtureJsonCouverture.AucuneFixtureOrpheline (Mineure) Source/Test/Unit/Core/Data/test_json_document.cpp:262 | Aucune fixture n'est presente sans etre lue par un test. | 1. Parcourir le dossier de fixtures. 2. Verifier que chaque fichier figure dans la liste des cas instancies. | Vérifie que std::filesystem::is_directory(FIXTURES) est vrai. Vérifie que std::find(couvertes.begin(), couvertes.end(), nom) diffère de couvertes.end(). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AssertTest.ConditionVraieNInvoquePasLeHandler (Majeur) Source/Test/Unit/Core/Diagnostics/test_assert.cpp:17 | Une condition vraie n'invoque pas le gestionnaire d'assertion. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que invoked est faux. |
| AssertTest.ConditionFausseInvoqueLeHandler (Majeur) Source/Test/Unit/Core/Diagnostics/test_assert.cpp:40 | Une condition fausse invoque le gestionnaire une fois, avec le message (Debug uniquement). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que count vaut 1. Vérifie que capturedMessage vaut "echec attendu". |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| FileLogSinkTest.EcritureEstPersisteeImmediatement (Majeur) Source/Test/Unit/Core/Diagnostics/test_file_log_sink.cpp:49 | FileLogSink : écriture persistée immédiatement (flush). | 1. Construire un FileLogSink sur un chemin dans un dossier temporaire. 2. Écrire un message. 3. Relire le fichier sans détruire le sink. | Vérifie que sink.isOpen() est vrai. Vérifie que content.find("message de test") diffère de std::string::npos. |
| FileLogSinkTest.MessagesSuccessifsUneLigneChacunOrdrePreserve (Majeur) Source/Test/Unit/Core/Diagnostics/test_file_log_sink.cpp:70 | FileLogSink : plusieurs messages, une ligne chacun, ordre préservé. | 1. Construire un FileLogSink. 2. Écrire trois messages successifs. 3. Relire le fichier. | Vérifie que std::getline(stream, line) est vrai. Vérifie que line vaut "premier". Vérifie que std::getline(stream, line) est vrai. Vérifie que line vaut "deuxieme". Vérifie que std::getline(stream, line) est vrai. Vérifie que line vaut "troisieme". |
| FileLogSinkTest.CreeLesDossiersParentsManquants (Mineur) Source/Test/Unit/Core/Diagnostics/test_file_log_sink.cpp:98 | FileLogSink : crée les dossiers parents manquants. | 1. Construire un FileLogSink sur dir/sous/dossier/session.log (dossiers inexistants). 2. Écrire un message. | Vérifie que sink.isOpen() est vrai. Vérifie que std::filesystem::exists(path) est vrai. Vérifie que readFile(path).find("message") diffère de std::string::npos. |
| FileLogSinkTest.EcraseParDefautCompleteAvecAppend (Mineur) Source/Test/Unit/Core/Diagnostics/test_file_log_sink.cpp:119 | FileLogSink : écrase par défaut, complète avec append = true. | 1. Écrire un fichier avec un premier sink. 2. Rouvrir sur le même chemin sans append, puis avec append = true. | Vérifie que afterTruncate.find("premiere ouverture") vaut std::string::npos. Vérifie que afterTruncate.find("seconde ouverture") diffère de std::string::npos. Vérifie que afterAppend.find("seconde ouverture") diffère de std::string::npos. Vérifie que afterAppend.find("troisieme ouverture") diffère de std::string::npos. |
| FileLogSinkTest.CheminInvalideSinkFermeEtWriteSilencieux (Mineur) Source/Test/Unit/Core/Diagnostics/test_file_log_sink.cpp:155 | FileLogSink : chemin invalide, sink fermé, write() silencieux. | 1. Construire un FileLogSink dont un segment du chemin est en réalité un fichier existant (impossible à traverser comme dossier). 2. Appeler write(). | Vérifie que sink.isOpen() est faux. EXPECT_NO_THROW(sink.write(core::LogLevel::Error, "ne doit rien faire")) |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LogFormatTest.LigneContientTousLesChamps (Majeur) Source/Test/Unit/Core/Diagnostics/test_log_format.cpp:17 | La ligne formatée contient horodatage, niveau, catégorie, position source et message. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que line.find("12:34:56") diffère de std::string::npos. Vérifie que line.find("WARNING") diffère de std::string::npos. Vérifie que line.find("HMI") diffère de std::string::npos. Vérifie que line.find("Foo.cpp:42") diffère de std::string::npos. Vérifie que line.find("message test") diffère de std::string::npos. |
| LogFormatTest.CheminReduitAuNomDeFichier (Majeur) Source/Test/Unit/Core/Diagnostics/test_log_format.cpp:40 | Le chemin source est réduit à son nom de fichier dans la ligne. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que line.find("Foo.cpp:7") diffère de std::string::npos. Vérifie que line.find("JustAnotherDnDGame") vaut std::string::npos. Vérifie que line.find("Source") vaut std::string::npos. |
| LogFormatTest.FileNameIsoleLeNom (Majeur) Source/Test/Unit/Core/Diagnostics/test_log_format.cpp:60 | fileName isole le nom de fichier des chemins Windows et POSIX, ou renvoie l'entrée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::fileName("a/b/c/File.cpp") vaut "File.cpp". Vérifie que core::fileName("a\\\\b\\\\File.cpp") vaut "File.cpp". Vérifie que core::fileName("File.cpp") vaut "File.cpp". |
| LogFormatTest.HorodatageFormatHeure (Majeur) Source/Test/Unit/Core/Diagnostics/test_log_format.cpp:77 | L'horodatage courant respecte le format HH:MM:SS (longueur 8). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que timestamp.size() vaut 8u. Vérifie que timestamp[2] vaut ':'. Vérifie que timestamp[5] vaut ':'. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LogLevelParseTest.NiveauxReconnus (Majeur) Source/Test/Unit/Core/Diagnostics/test_log_level_parse.cpp:15 | Les noms de niveaux reconnus sont convertis (y compris l'alias « warn »). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::parseLogLevel("trace") vaut core::LogLevel::Trace. Vérifie que core::parseLogLevel("info") vaut core::LogLevel::Info. Vérifie que core::parseLogLevel("warning") vaut core::LogLevel::Warning. Vérifie que core::parseLogLevel("warn") vaut core::LogLevel::Warning. Vérifie que core::parseLogLevel("error") vaut core::LogLevel::Error. |
| LogLevelParseTest.InsensibleALaCasse (Majeur) Source/Test/Unit/Core/Diagnostics/test_log_level_parse.cpp:33 | L'analyse est insensible à la casse. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::parseLogLevel("INFO") vaut core::LogLevel::Info. Vérifie que core::parseLogLevel("Warning") vaut core::LogLevel::Warning. Vérifie que core::parseLogLevel("Error") vaut core::LogLevel::Error. |
| LogLevelParseTest.ValeurInconnue (Majeur) Source/Test/Unit/Core/Diagnostics/test_log_level_parse.cpp:49 | Une valeur inconnue ou vide n'est pas convertie. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::parseLogLevel("verbose").has_value() est faux. Vérifie que core::parseLogLevel("").has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LoggerTest.FiltreParNiveauMinimal (Majeur) Source/Test/Unit/Core/Diagnostics/test_logger.cpp:18 | Un message au-dessus du niveau minimal est diffusé ; en dessous, il est filtré. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que observed->entries().size() vaut 1u. Vérifie que observed->entries()[0].level vaut core::LogLevel::Error. Vérifie que observed->entries()[0].message vaut "garde". |
| LoggerTest.DiffuseAPlusieursSinks (Majeur) Source/Test/Unit/Core/Diagnostics/test_logger.cpp:44 | Le même message atteint tous les sinks enregistrés. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que firstObserved->entries().size() vaut 1u. Vérifie que secondObserved->entries().size() vaut 1u. |
| LoggerTest.ClearSinksArreteLaDiffusion (Majeur) Source/Test/Unit/Core/Diagnostics/test_logger.cpp:69 | clearSinks retire les destinations : plus rien n'est diffusé ensuite. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que observedAfterClear->entries().size() vaut 1u. Vérifie que observedAfterClear->entries()[0].message vaut "personne". |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ScopedLogLevelTest.ReleveUnNiveauPermissifPuisLeRestaure (Majeur) Source/Test/Unit/Core/Diagnostics/test_scoped_log_level.cpp:17 | ScopedLogLevel relève un niveau permissif, puis le restaure. | 1. Logger au niveau Trace. 2. Ouvrir une portée ScopedLogLevel(logger, Warning). 3. Fermer la portée. | Vérifie que logger.minimumLevel() vaut core::LogLevel::Warning. Vérifie que logger.isEnabled(core::LogLevel::Info) est faux. Vérifie que logger.minimumLevel() vaut core::LogLevel::Trace. Vérifie que logger.isEnabled(core::LogLevel::Trace) est vrai. |
| ScopedLogLevelTest.NAssouplitJamaisUnNiveauDejaPlusStrict (Majeur) Source/Test/Unit/Core/Diagnostics/test_scoped_log_level.cpp:40 | ScopedLogLevel n'assouplit jamais un niveau déjà plus strict. | 1. Logger au niveau Error. 2. Ouvrir une portée ScopedLogLevel(logger, Warning). | Vérifie que logger.minimumLevel() vaut core::LogLevel::Error. Vérifie que logger.minimumLevel() vaut core::LogLevel::Error. |
| ScopedLogLevelTest.ElevationsImbriqueesNeRestaurentQuALaDerniereSortie (Majeur) Source/Test/Unit/Core/Diagnostics/test_scoped_log_level.cpp:67 | Élévations imbriquées : restauration à la sortie de la dernière seulement. | 1. Journaliseur à Info. 2. Ouvrir une première élévation à Warning, puis une seconde. 3. Fermer la première, vérifier le niveau ; fermer la seconde, vérifier à nouveau. | Vérifie que logger.minimumLevel() vaut core::LogLevel::Warning. Vérifie que logger.minimumLevel() vaut core::LogLevel::Warning. Vérifie que logger.minimumLevel() vaut core::LogLevel::Warning. Vérifie que logger.minimumLevel() vaut core::LogLevel::Info. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MemoryLogSinkTest.ConserveNiveauEtTexteDansLOrdre (Majeur) Source/Test/Unit/Core/Diagnostics/test_sinks.cpp:15 | Le sink mémoire conserve fidèlement niveau et texte, dans l'ordre. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que sink.entries().size() vaut 2u. Vérifie que sink.entries()[0].level vaut core::LogLevel::Info. Vérifie que sink.entries()[0].message vaut "premier". Vérifie que sink.entries()[1].level vaut core::LogLevel::Error. Vérifie que sink.entries()[1].message vaut "second". |
| MemoryLogSinkTest.ClearVideLesMessages (Majeur) Source/Test/Unit/Core/Diagnostics/test_sinks.cpp:37 | clear vide les messages mémorisés. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que sink.entries().empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AnimationClipTest.ClipExistantResoluParNom (Critique) Source/Test/Unit/Core/Ecs/test_animation_clip.cpp:32 | Un clip existant est résolu par son nom. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que clips.clipCount() vaut 2. Vérifie que clips.indexOf("idle") est supérieur ou égal à 0. Vérifie que clips.indexOf("run") est supérieur ou égal à 0. Vérifie que clips.clipAt(clips.indexOf("idle")).name vaut "idle". Vérifie que clips.clipAt(clips.indexOf("run")).name vaut "run". |
| AnimationClipTest.ClipInexistantRepliDeterministe (Critique) Source/Test/Unit/Core/Ecs/test_animation_clip.cpp:55 | Un nom inconnu ou un index hors bornes retombe sur le premier clip, sans plantage. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que clips.indexOf("inconnu") vaut -1. Vérifie que clips.clipAt(-1).name vaut "idle". Vérifie que clips.clipAt(42).name vaut "idle". |
| AnimationClipTest.JeuVideRepliSurUnClipParDefaut (Critique) Source/Test/Unit/Core/Ecs/test_animation_clip.cpp:78 | Un jeu de clips vide se replie sur un clip par défaut portant au moins une image. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que clips.clipCount() vaut 0. Vérifie que fallback.name.empty() est vrai. Vérifie que fallback.frames.empty() est faux. Vérifie que fallback.frameDuration vaut 0.0f. |
| AnimationClipTest.ClipAUneSeuleImage (Majeur) Source/Test/Unit/Core/Ecs/test_animation_clip.cpp:98 | Un clip d'une seule image est un clip valide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que clip.frames.size() vaut 1u. |
| AnimationClipTest.DureesInegalesEntreClips (Majeur) Source/Test/Unit/Core/Ecs/test_animation_clip.cpp:115 | Chaque clip garde sa propre durée d'image. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que clips.clipAt(clips.indexOf("idle")).frameDuration vaut 0.5f (comparaison flottante). Vérifie que clips.clipAt(clips.indexOf("run")).frameDuration vaut 0.1f (comparaison flottante). |
| AnimationClipTest.ClipJoueUneFoisAvecClipSuivant (Critique) Source/Test/Unit/Core/Ecs/test_animation_clip.cpp:135 | Un clip joué une fois désigne un clip suivant, résolu dans le même jeu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que opening.endMode vaut core::ClipEndMode::OneShot. Vérifie que opening.nextClip vaut "open". Vérifie que clips.indexOf(opening.nextClip) est supérieur ou égal à 0. |
| AnimationClipTest.AjouterUnClipDeMemeNomLeRemplace (Critique) Source/Test/Unit/Core/Ecs/test_animation_clip.cpp:157 | Ajouter un clip de même nom remplace l'existant, à index constant. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que clips.clipCount() vaut 1. Vérifie que clips.indexOf("idle") vaut firstIndex. Vérifie que clips.clipAt(firstIndex).frames.size() vaut 3u. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ComponentPoolTest.AjoutPuisAcces (Majeur) Source/Test/Unit/Core/Ecs/test_component_pool.cpp:28 | add puis get renvoie la valeur stockée ; has est cohérent. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que pool.has(entity) est faux. Vérifie que pool.has(entity) est vrai. Vérifie que pool.get(entity).x vaut 3. Vérifie que pool.get(entity).y vaut 4. Vérifie que pool.size() vaut 1u. |
| ComponentPoolTest.GetRenvoieReferenceModifiable (Majeur) Source/Test/Unit/Core/Ecs/test_component_pool.cpp:52 | get renvoie une référence modifiable sur le composant stocké. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que pool.get(entity).x vaut 42. |
| ComponentPoolTest.RemoveAuMilieuSwapAndPop (Majeur) Source/Test/Unit/Core/Ecs/test_component_pool.cpp:74 | remove d'un élément au milieu (swap-and-pop) laisse les autres composants accessibles et corrects, et le stockage dense reste contigu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que pool.has(middle) est faux. Vérifie que pool.has(first) est vrai. Vérifie que pool.has(last) est vrai. Vérifie que pool.get(first) vaut 10. Vérifie que pool.get(last) vaut 30. Vérifie que pool.size() vaut 2u. Vérifie que pool.components().size() vaut 2u. Vérifie que pool.entities().size() vaut 2u. |
| ComponentPoolTest.RemoveDernierElement (Majeur) Source/Test/Unit/Core/Ecs/test_component_pool.cpp:110 | Retirer le dernier élément ne perturbe pas les précédents. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que pool.has(a) est vrai. Vérifie que pool.has(b) est faux. Vérifie que pool.get(a) vaut 1. Vérifie que pool.size() vaut 1u. |
| ComponentPoolTest.HandlePerimeNePossedePasLeComposant (Majeur) Source/Test/Unit/Core/Ecs/test_component_pool.cpp:137 | Un handle périmé (index recyclé, génération différente) ne possède pas le composant de l'ancienne entité. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que pool.has(original) est vrai. Vérifie que pool.has(recycled) est faux. |
| ComponentPoolTest.RemoveIfPresent (Majeur) Source/Test/Unit/Core/Ecs/test_component_pool.cpp:164 | removeIfPresent retire si le composant existe, sinon ne fait rien. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que pool.removeIfPresent(entity) est faux. Vérifie que pool.removeIfPresent(entity) est vrai. Vérifie que pool.has(entity) est faux. |
| ComponentPoolTest.GetSurEntiteAbsenteViolePrecondition (Majeur) Source/Test/Unit/Core/Ecs/test_component_pool.cpp:185 | get sur une entité absente viole une précondition (assertion en Debug). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que l'opération lève bien une exception std::runtime_error. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EntityManagerTest.CreeEntitesVivantesEtDistinctes (Majeur) Source/Test/Unit/Core/Ecs/test_entity_manager.cpp:16 | create renvoie des entités vivantes et distinctes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que manager.isAlive(a) est vrai. Vérifie que manager.isAlive(b) est vrai. Vérifie que a diffère de b. Vérifie que manager.aliveCount() vaut 2u. |
| EntityManagerTest.DestructionInvalideLeHandle (Majeur) Source/Test/Unit/Core/Ecs/test_entity_manager.cpp:37 | Après destruction, l'ancien handle n'est plus vivant. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que manager.isAlive(entity) est faux. Vérifie que manager.aliveCount() vaut 0u. |
| EntityManagerTest.RecyclageChangeLaGeneration (Majeur) Source/Test/Unit/Core/Ecs/test_entity_manager.cpp:58 | Un index recyclé produit une génération différente : l'ancien handle reste invalide, le nouveau est valide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que recycled.index vaut first.index. Vérifie que recycled.generation diffère de first.generation. Vérifie que manager.isAlive(first) est faux. Vérifie que manager.isAlive(recycled) est vrai. |
| EntityManagerTest.DestructionHandlePerimeSansEffet (Majeur) Source/Test/Unit/Core/Ecs/test_entity_manager.cpp:86 | Détruire un handle périmé est sans effet (idempotent) et ne touche pas l'entité vivante qui occupe désormais le même index. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que manager.isAlive(live) est vrai. Vérifie que manager.aliveCount() vaut 1u. |
| EntityManagerTest.EntiteInvalideJamaisVivante (Majeur) Source/Test/Unit/Core/Ecs/test_entity_manager.cpp:110 | L'entité invalide conventionnelle n'est jamais vivante. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que manager.isAlive(core::INVALID_ENTITY) est faux. Vérifie que manager.isAlive(created) est vrai. Vérifie que manager.isAlive(core::INVALID_ENTITY) est faux. |
| EntityManagerTest.EgaliteHandleInvalide (Majeur) Source/Test/Unit/Core/Ecs/test_entity_manager.cpp:128 | Le handle invalide se compare comme tel. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::INVALID_ENTITY vaut core::INVALID_ENTITY. Vérifie que core::INVALID_ENTITY.index vaut core::Entity::INVALID_INDEX. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ParticleSystemTest.DeterminismeMemeSequenceMemesParticules (Critique) Source/Test/Unit/Core/Ecs/test_particle_system.cpp:40 | Déterminisme : même séquence -> mêmes particules. | 1. Deux ParticleSystem/World construits à l'identique (graine par défaut). 2. Rejouer sur chacun la même séquence : émettre un effet dispersé, avancer plusieurs pas, émettre à nouveau, avancer encore. | Vérifie que systemA.aliveCount() vaut systemB.aliveCount(). Vérifie que particlesA.size() vaut particlesB.size(). Vérifie que particlesA[i].position.x vaut particlesB[i].position.x (comparaison flottante). Vérifie que particlesA[i].position.y vaut particlesB[i].position.y (comparaison flottante). Vérifie que particlesA[i].velocity.x vaut particlesB[i].velocity.x (comparaison flottante). Vérifie que particlesA[i].velocity.y vaut particlesB[i].velocity.y (comparaison flottante). Vérifie que particlesA[i].life vaut particlesB[i].life (comparaison flottante). |
| ParticleSystemTest.BudgetJamaisDepasseRecycleLaPlusAncienne (Critique) Source/Test/Unit/Core/Ecs/test_particle_system.cpp:92 | Budget : jamais dépassé, recyclage de la plus ancienne. | 1. Émettre MAX_PARTICLES + 5 particules individuelles, une origine distincte chacune (x = 0, 1, 2...). 2. Lire le nombre de particules vivantes et leurs origines. | Vérifie que system.aliveCount() vaut core::MAX_PARTICLES. Vérifie que particles.size() vaut static_cast<std::size_t>(core::MAX_PARTICLES). Vérifie que particle.position.x est supérieur ou égal à static_cast<float>(EXTRA_EMISSIONS). |
| ParticleSystemTest.DureeDeVieDisparaitAuPasAttendu (Majeur) Source/Test/Unit/Core/Ecs/test_particle_system.cpp:123 | Durée de vie : disparition au pas attendu. | 1. Émettre une particule de durée de vie fixe 1,0 s. 2. Avancer de 0,25 s par pas (fixedDelta, exactement représentable en flottant), trois fois. 3. Avancer un quatrième pas. | Vérifie que system.aliveCount() vaut 1. Vérifie que system.aliveCount() vaut 1. Vérifie que stillAlive.size() vaut 1u. Vérifie que stillAlive.front().life vaut 0.25f (comparaison flottante). Vérifie que system.aliveCount() vaut 0. |
| ParticleSystemTest.AucunEffetSurLesEntitesDeGameplay (Critique) Source/Test/Unit/Core/Ecs/test_particle_system.cpp:158 | Aucun effet sur le gameplay. | 1. Peupler un core::Actor dans le monde. 2. Émettre et simuler des particules plusieurs pas. | Vérifie que after.facing.x vaut original.facing.x (comparaison flottante). Vérifie que after.facing.y vaut original.facing.y (comparaison flottante). Vérifie que after.mass vaut original.mass (comparaison flottante). |
| ParticleSystemTest.ClearVideToutesLesParticulesVivantes (Majeur) Source/Test/Unit/Core/Ecs/test_particle_system.cpp:190 | clear() vide toutes les particules vivantes. | 1. Émettre plusieurs particules. 2. Appeler clear(). | Vérifie que system.aliveCount() vaut 1. Vérifie que system.aliveCount() vaut 0. Vérifie que snapshot(world).empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ParticleTriggersTest.AtterrissageSousLeSeuilAucunEffet (Critique) Source/Test/Unit/Core/Ecs/test_particle_triggers.cpp:20 | Atterrissage sous le seuil : aucun effet. | 1. Appeler emitLanding avec une vitesse d'impact strictement inférieure au seuil. | Vérifie que system.aliveCount() vaut 0. |
| ParticleTriggersTest.IntensiteAtterrissageProportionnelleALaVitesseDImpact (Critique) Source/Test/Unit/Core/Ecs/test_particle_triggers.cpp:40 | Intensité d'atterrissage proportionnelle à la vitesse d'impact. | 1. Émettre au seuil minimal. 2. Émettre à mi-intervalle (mondes séparés). 3. Émettre au-delà du plafond. | Vérifie que systemMin.aliveCount() vaut core::LANDING_DUST_MIN_COUNT. Vérifie que systemMax.aliveCount() vaut core::LANDING_DUST_MAX_COUNT. Vérifie que systemMid.aliveCount() est strictement supérieur à systemMin.aliveCount(). Vérifie que systemMid.aliveCount() est strictement inférieur à systemMax.aliveCount(). Vérifie que systemExtreme.aliveCount() vaut core::LANDING_DUST_MAX_COUNT. |
| ParticleTriggersTest.TraineeDeDashEmissionContinueUnAppelParPas (Critique) Source/Test/Unit/Core/Ecs/test_particle_triggers.cpp:79 | Traînée de dash : émission continue, un appel par pas. | 1. Appeler emitDashTrail puis update quatre fois de suite (simulant quatre pas de dash). | Vérifie que system.aliveCount() est strictement supérieur à previousCount. |
| ParticleTriggersTest.MortProduitUneRafaleDeParticulesDeType (Majeur) Source/Test/Unit/Core/Ecs/test_particle_triggers.cpp:105 | Mort : rafale ponctuelle de particules. | 1. Appeler emitDeath une fois. | Vérifie que system.aliveCount() est strictement supérieur à 1. Vérifie que particle.kind vaut core::ParticleKind::Death. |
| ParticleTriggersTest.RechargementAucuneParticuleResiduelle (Majeur) Source/Test/Unit/Core/Ecs/test_particle_triggers.cpp:127 | Rechargement : aucune particule résiduelle. | 1. Émettre un éclatement de mort. 2. Appeler clear (rechargement). | Vérifie que system.aliveCount() est strictement supérieur à 0. Vérifie que system.aliveCount() vaut 0. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| SpriteTest.ValeursParDefaut (Majeur) Source/Test/Unit/Core/Ecs/test_sprite.cpp:15 | Un sprite par défaut a une teinte blanche opaque, la couche 0 et une région nulle. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que sprite.layer vaut 0. Vérifie que sprite.region.x vaut 0. Vérifie que sprite.region.y vaut 0. Vérifie que sprite.region.width vaut 0. Vérifie que sprite.region.height vaut 0. Vérifie que sprite.tint.r vaut 1.0f (comparaison flottante). Vérifie que sprite.tint.g vaut 1.0f (comparaison flottante). Vérifie que sprite.tint.b vaut 1.0f (comparaison flottante). Vérifie que sprite.tint.a vaut 1.0f (comparaison flottante). |
| SpriteTest.ChampsAssignables (Majeur) Source/Test/Unit/Core/Ecs/test_sprite.cpp:40 | Les champs sont librement assignables (donnée pure). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que sprite.region.x vaut 16. Vérifie que sprite.region.y vaut 32. Vérifie que sprite.region.width vaut 16. Vérifie que sprite.region.height vaut 16. Vérifie que sprite.layer vaut 2. Vérifie que sprite.tint.g vaut 0.5f (comparaison flottante). Vérifie que sprite.tint.a vaut 0.8f (comparaison flottante). |
| SpriteTest.CopieValeur (Majeur) Source/Test/Unit/Core/Ecs/test_sprite.cpp:65 | Le composant est utilisable comme un composant d'ECS (stockage/copie de données pures). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que copy.layer vaut 5. Vérifie que copy.region.width vaut 16. Vérifie que copy.tint.r vaut 0.2f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| DeplacementTopDownTest.LaDiagonaleNEstPasPlusRapide (Critique) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:82 | La diagonale n'est pas plus rapide que la marche cardinale. | 1. Faire marcher un acteur vers la droite pendant 60 pas. 2. Faire marcher un second acteur en diagonale bas-droite pendant 60 pas. | Vérifie que distanceCardinale est strictement supérieur à 0.0f. Vérifie que distanceDiagonale vaut distanceCardinale, à 1e-4f près. |
| DeplacementTopDownTest.LesQuatreDirectionsCardinalesSontEquivalentes (Majeur) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:108 | Aucun axe n'est privilegie : la marche est isotrope. | 1. Faire marcher un acteur vers chacune des quatre directions cardinales, 30 pas. | Vérifie que distances.front() est strictement supérieur à 0.0f. Vérifie que distance vaut distances.front(), à 1e-4f près. |
| DeplacementTopDownTest.AucuneTraverseeDeMurAVitesseAbsurde (Critique) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:134 | Un acteur lance a vitesse absurde ne traverse pas un mur. | 1. Poser un acteur pres du mur de droite, avec une vitesse de 1000 unites/s. 2. Avancer d'un pas. | Vérifie que position.x + ACTOR_SIZE est inférieur ou égal à 9.0f. Vérifie que position.x est strictement supérieur à 2.0f. |
| DeplacementTopDownTest.GlissementLeLongDUnMurPrisEnBiais (Critique) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:160 | Un mur pris en biais laisse glisser le long de sa surface. | 1. Placer un acteur contre le mur du haut. 2. Marcher en diagonale haut-droite pendant 60 pas. | Vérifie que position.y est supérieur ou égal à 1.0f. Vérifie que position.x est strictement supérieur à 2.5f. |
| DeplacementTopDownTest.PousserContreUnMurNAccumuleAucunElan (Majeur) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:183 | Pousser contre un mur n'accumule aucun elan. | 1. Pousser un acteur contre le mur de droite pendant 120 pas. | Vérifie que world.getComponent<core::Velocity>(actor).value.x vaut 0.0f (comparaison flottante). Vérifie que world.getComponent<core::Transform>(actor).position.x + ACTOR_SIZE est inférieur ou égal à 9.0f. |
| DeplacementTopDownTest.OrientationConserveeALArret (Majeur) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:204 | L'orientation suit la marche et survit a l'arret. | 1. Marcher vers le bas, puis relacher l'intention pendant 60 pas. | Vérifie que facingEnMarche.x vaut 0.0f, à 1e-5f près. Vérifie que facingEnMarche.y vaut 1.0f, à 1e-5f près. Vérifie que facingALArret.x vaut 0.0f, à 1e-5f près. Vérifie que facingALArret.y vaut 1.0f, à 1e-5f près. |
| DeplacementTopDownTest.IntentionRelacheeArreteNet (Majeur) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:230 | Intention relachee, l'acteur s'arrete net. | 1. Lancer un acteur a pleine vitesse. 2. Relacher l'intention pendant 60 pas. | Vérifie que world.getComponent<core::Velocity>(actor).value.x vaut 0.0f (comparaison flottante). Vérifie que world.getComponent<core::Velocity>(actor).value.y vaut 0.0f (comparaison flottante). Vérifie que world.getComponent<core::Transform>(actor).position.x vaut arret.x (comparaison flottante). Vérifie que world.getComponent<core::Transform>(actor).position.y vaut arret.y (comparaison flottante). |
| DeplacementTopDownTest.MemesEntreesMemesPositionsSur600Pas (Critique) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:256 | Memes entrees, memes positions sur 600 pas. | 1. Rejouer deux fois la meme sequence de 600 intentions variables. 2. Comparer les trajectoires pas a pas. | Vérifie que premier.size() vaut second.size(). Vérifie que premier[step].x vaut second[step].x (comparaison flottante). Vérifie que premier[step].y vaut second[step].y (comparaison flottante). |
| DeplacementTopDownTest.EntiteSansActeurIgnoree (Mineur) Source/Test/Unit/Core/Ecs/test_top_down_movement.cpp:297 | Une entite sans composant Actor est ignoree sans planter. | 1. Creer une entite portant Transform, Velocity et Collider, mais pas Actor. 2. Lui appliquer un pas de deplacement. | Vérifie que world.getComponent<core::Transform>(entity).position.x vaut 4.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ViewTest.SelectionneUniquementLIntersection (Majeur) Source/Test/Unit/Core/Ecs/test_view.cpp:30 | Une vue <A, B> itère exactement les entités possédant A et B. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que visited.size() vaut 1u. Vérifie que visited.front() vaut both. |
| ViewTest.ComposantsCorrespondentALEntite (Majeur) Source/Test/Unit/Core/Ecs/test_view.cpp:61 | Les composants fournis par la vue correspondent bien à l'entité itérée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que velocity.value vaut position.value * 10. Vérifie que position.value vaut 1. Vérifie que position.value vaut 2. |
| ViewTest.ModificationViaVueEstVisible (Majeur) Source/Test/Unit/Core/Ecs/test_view.cpp:95 | La modification d'un composant via la vue est visible ensuite (référence). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que positions.get(entity).value vaut 8. |
| ViewTest.VueVideNIterePas (Majeur) Source/Test/Unit/Core/Ecs/test_view.cpp:121 | Une vue sans entité correspondante s'itère sans erreur (aucune visite). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que visits vaut 0. |
| ViewTest.IterationForEtEachCoherentes (Majeur) Source/Test/Unit/Core/Ecs/test_view.cpp:148 | L'itération par for visite les mêmes entités que each. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que fromEach.size() vaut 2u. Vérifie que fromFor vaut fromEach. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| WorldTest.CycleComposant (Majeur) Source/Test/Unit/Core/Ecs/test_world.cpp:56 | Le cycle add/has/get/remove d'un composant est cohérent via le World. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que world.hasComponent<Health>(entity) est faux. Vérifie que world.hasComponent<Health>(entity) est vrai. Vérifie que world.getComponent<Health>(entity).value vaut 100. Vérifie que world.getComponent<Health>(entity).value vaut 60. Vérifie que world.hasComponent<Health>(entity) est faux. |
| WorldTest.HasComponentSansPool (Majeur) Source/Test/Unit/Core/Ecs/test_world.cpp:83 | hasComponent est faux quand aucune pool du type n'existe encore. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que world.hasComponent<Health>(entity) est faux. |
| WorldTest.DestroyEntityRetireTousLesComposants (Majeur) Source/Test/Unit/Core/Ecs/test_world.cpp:99 | destroyEntity retire l'entité de toutes les pools et la rend non vivante. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que world.isAlive(entity) est faux. Vérifie que world.hasComponent<Health>(entity) est faux. Vérifie que world.hasComponent<Position>(entity) est faux. |
| WorldTest.SystemesExecutesDansLOrdre (Majeur) Source/Test/Unit/Core/Ecs/test_world.cpp:122 | Les systèmes enregistrés s'exécutent dans l'ordre d'enregistrement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que world.systemCount() vaut 3u. Vérifie que log vaut (std::vector<int>{1, 2, 3}). |
| WorldTest.UpdateNFoisExecuteNFois (Majeur) Source/Test/Unit/Core/Ecs/test_world.cpp:145 | update appelé N fois exécute chaque système N fois (cadencement déterministe). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que log.size() vaut static_cast<std::size_t>(calls). |
| WorldTest.FixedDeltaTransmisAuxSystemes (Majeur) Source/Test/Unit/Core/Ecs/test_world.cpp:169 | Le fixedDelta passé à update est transmis tel quel aux systèmes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que observed vaut 0.25f (comparaison flottante). |
| WorldTest.ViewViaWorld (Majeur) Source/Test/Unit/Core/Ecs/test_world.cpp:189 | La vue exposée par le World itère l'intersection des composants. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que visited.size() vaut 1u. Vérifie que visited.front() vaut both. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| InteractionTest.LaCaseViseeSuitLaDirectionDominante (Majeur) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:69 | La case visee suit la direction dominante de l'orientation. | 1. Viser avec quatre orientations cardinales, puis une orientation a 30 degres. 2. Viser avec une orientation nulle. | Vérifie que core::aimedCell(depart, {1.0F, 0.0F}) vaut (core::GridPosition{3, 2}). Vérifie que core::aimedCell(depart, {-1.0F, 0.0F}) vaut (core::GridPosition{1, 2}). Vérifie que core::aimedCell(depart, {0.0F, 1.0F}) vaut (core::GridPosition{2, 3}). Vérifie que core::aimedCell(depart, {0.0F, -1.0F}) vaut (core::GridPosition{2, 1}). Vérifie que core::aimedCell(depart, {0.866F, 0.5F}) vaut (core::GridPosition{3, 2}). Vérifie que core::aimedCell(depart, {0.5F, 0.866F}) vaut (core::GridPosition{2, 3}). Vérifie que core::aimedCell(depart, {0.0F, 0.0F}) vaut depart. |
| InteractionTest.UnCoffreNeDonneSonButinQuUneFois (Critique) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:97 | Un coffre ne donne son butin qu'a la premiere ouverture. | 1. Interagir deux fois avec le meme coffre. | Vérifie que premiere.found() est vrai. Vérifie que butin.happened est vrai. Vérifie que butin.consumed est vrai. Vérifie que butin.type vaut "chest". Vérifie que seconde.found() est faux. Vérifie que rien.happened est faux. |
| InteractionTest.LEtatDUnCoffreSurvitAUnAllerRetourDeCarte (Critique) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:128 | Un coffre ouvert le reste apres avoir quitte la carte et y etre revenu. | 1. Ouvrir un coffre, puis DETRUIRE les entites de la carte et les recreer depuis la couche objects, comme le fait un changement de carte. | Vérifie que core::spawnMapEntities(monde, niveau, niveau.name()) vaut 1U. Vérifie que objets.size() vaut 1U. Vérifie que cible.found() est vrai. Vérifie que core::interact(cible, drapeaux).consumed est vrai. Vérifie que core::spawnMapEntities(monde, niveau, niveau.name()) vaut 1U. Vérifie que objets.size() vaut 1U. Vérifie que cible.found() est faux. |
| InteractionTest.LInteractionNeTraversePasUnMur (Critique) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:184 | Un objet place sur une case pleine n'est pas atteignable. | 1. Poser un coffre sur une case, puis rendre cette case pleine. | Vérifie que core::findInteractionTarget({2, 2}, {1.0F, 0.0F}, carte, candidats(objets), drapeaux) .found() est vrai. Vérifie que derriereLeMur.found() est faux. Vérifie que derriereLeMur.aimedCell vaut (core::GridPosition{3, 2}). |
| InteractionTest.LaCibleEstDeterministeAEgalite (Critique) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:211 | Deux objets sur la meme case designent toujours le meme. | 1. Poser deux objets sur la case visee et designer la cible dix fois. | Vérifie que cible.found() est vrai. Vérifie que cible.index vaut 0U. Vérifie que cible.interactable->type vaut "chest". |
| InteractionTest.UnPanneauSeRelitIndefiniment (Majeur) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:236 | Une entite non consommable reste une cible apres interaction. | 1. Interagir trois fois avec un panneau. | Vérifie que cible.found() est vrai. Vérifie que lecture.happened est vrai. Vérifie que lecture.consumed est faux. Vérifie que lecture.promptKey vaut "interaction.sign". Vérifie que drapeaux.size() vaut 0U. |
| InteractionTest.DeuxCartesNeSeMarchentPasDessus (Critique) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:262 | Deux coffres de cartes differentes a la meme case ont des drapeaux distincts. | 1. Fabriquer la cle de deux coffres a la case (3, 2), sur deux cartes. 2. Ouvrir le premier. | Vérifie que cleVillage diffère de cleDonjon. Vérifie que cible.found() est vrai. Vérifie que core::interact(cible, drapeaux).consumed est vrai. Vérifie que core::findInteractionTarget({2, 2}, {1.0F, 0.0F}, carte, candidats(auDonjon), drapeaux) .found() est vrai. |
| InteractionTest.UnTypeInconnuProduitUneEntiteNonInteractive (Majeur) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:294 | Un objet de type inconnu apparait sur la carte sans etre interactif. | 1. Peupler un monde depuis une couche objects portant un type inconnu. | Vérifie que core::spawnMapEntities(monde, niveau, niveau.name()) vaut 2U. Vérifie que interactif.type vaut "chest". Vérifie que interactifs vaut 1U. |
| InteractionTest.LesDrapeauxSeRelisentTries (Mineur) Source/Test/Unit/Core/Gameplay/test_interaction.cpp:322 | Les drapeaux acquis se relisent dans un ordre stable. | 1. Lever trois drapeaux dans le desordre, puis les relire. 2. Lever deux fois le meme. | Vérifie que drapeaux.set("village/chest@3,2") est vrai. Vérifie que drapeaux.set("donjon/chest@1,1") est vrai. Vérifie que drapeaux.set("village/chest@0,0") est vrai. Vérifie que drapeaux.set("village/chest@3,2") est faux. Vérifie que drapeaux.size() vaut 3U. Vérifie que tous.size() vaut 3U. Vérifie que std::is_sorted(tous.begin(), tous.end()) est vrai. Vérifie que drapeaux.isSet("donjon/chest@1,1") est faux. Vérifie que drapeaux.size() vaut 2U. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MechanismControllerTest.ContactOuvreLaPorte (Majeur) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:94 | Au départ, la porte est fermée (solide) ; toucher l'interrupteur l'ouvre. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. Vérifie que controller.isDoorOpen(0) est faux. Vérifie que controller.collisionMap().isSolid(4, 1) est faux. Vérifie que controller.isDoorOpen(0) est vrai. |
| MechanismControllerTest.BasculeSurFront (Majeur) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:116 | La bascule est sur front : rester sur l'interrupteur ne re-bascule pas ; revenir bascule. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.isDoorOpen(0) est faux. Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. |
| MechanismControllerTest.SansContactRienNeChange (Majeur) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:143 | Loin de l'interrupteur, rien ne change (la porte reste fermée). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. Vérifie que controller.isDoorOpen(0) est faux. |
| MechanismControllerTest.PlaqueDePressionActivationContinue (Majeur) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:161 | Une plaque de pression ouvre la porte tant que le poids y repose, et la referme dès qu'il en part. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.collisionMap().isSolid(4, 1) est faux. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.isDoorOpen(0) est faux. Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. Vérifie que controller.isDoorOpen(0) est vrai. |
| MechanismControllerTest.PlaqueDePressionPoidsInsuffisant (Majeur) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:192 | Un poids insuffisant sur la plaque de pression n'ouvre pas la porte. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.isDoorOpen(0) est faux. Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. |
| MechanismControllerTest.ContactSeulNOuvrePasLaPorteVerrouillee (Bloquant) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:210 | Le simple contact sur la clé n'ouvre pas la porte verrouillée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.isDoorOpen(0) est faux. Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. |
| MechanismControllerTest.ContactEtInteragirRamasseLaCleEtOuvreDefinitivement (Bloquant) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:227 | Contact + Interagir ramasse la clé et ouvre définitivement la porte verrouillée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.collisionMap().isSolid(4, 1) est faux. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.collisionMap().isSolid(4, 1) est faux. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.collisionMap().isSolid(4, 1) est faux. |
| MechanismControllerTest.InteragirSansContactNeRamassePasLaCle (Majeur) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:257 | Interagir sans contact ne ramasse pas la clé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.isDoorOpen(0) est faux. Vérifie que controller.collisionMap().isSolid(4, 1) est vrai. |
| MechanismControllerTest.DeuxPairesCleEtPorteIndependantes (Bloquant) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:275 | Deux paires clé/porte verrouillée indépendantes ne s'influencent pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.isDoorOpen(1) est faux. Vérifie que controller.collisionMap().isSolid(2, 1) est faux. Vérifie que controller.collisionMap().isSolid(6, 1) est vrai. Vérifie que controller.isDoorOpen(0) est vrai. Vérifie que controller.isDoorOpen(1) est vrai. Vérifie que controller.collisionMap().isSolid(6, 1) est faux. |
| MechanismControllerTest.RechargementReinitialiseCleEtPorte (Majeur) Source/Test/Unit/Core/Gameplay/test_mechanism_controller.cpp:301 | Reconstruire le contrôleur remet la clé et la porte dans leur état initial. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first.isDoorOpen(0) est vrai. Vérifie que reloaded.isDoorOpen(0) est faux. Vérifie que reloaded.collisionMap().isSolid(4, 1) est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CameraFramingTest.NomEtReconnaissanceSontSymetriques (Majeur) Source/Test/Unit/Core/Levels/test_camera_framing.cpp:20 | Le nom JSON d'un mode et sa reconnaissance sont symétriques. | 1. Pour chacun des trois modes, convertir en nom JSON puis reconnaître ce nom. | Vérifie que parsed.has_value() est vrai. Vérifie que *parsed vaut mode. |
| CameraFramingTest.NomInconnuNeProduitAucunMode (Majeur) Source/Test/Unit/Core/Levels/test_camera_framing.cpp:40 | Un nom de mode non reconnu ne produit aucun mode. | 1. Reconnaître un nom de mode arbitraire, non défini. | Vérifie que core::parseCameraFramingMode("zoomInfini").has_value() est faux. Vérifie que core::parseCameraFramingMode("").has_value() est faux. |
| CameraFramingTest.CadrageDeclareEstResoluTelQuel (Critique) Source/Test/Unit/Core/Levels/test_camera_framing.cpp:54 | Un cadrage déclaré est résolu tel quel. | 1. Résoudre un cadrage explicitement déclaré (Follow). | Vérifie que resolved.mode vaut core::CameraFramingMode::Follow. |
| CameraFramingTest.RegleDeRepliReproduitLaRegleHistoriqueAuxBornes (Critique) Source/Test/Unit/Core/Levels/test_camera_framing.cpp:72 | La règle de repli reproduit la règle historique aux bornes. | 1. Résoudre l'absence de cadrage pour un niveau tenant exactement dans une salle par défaut. 2. Résoudre pour un niveau un cran plus large, puis un cran plus haut. | Vérifie que exact.mode vaut core::CameraFramingMode::WholeLevel. Vérifie que tooWide.mode vaut core::CameraFramingMode::PerRoom. Vérifie que tooWide.roomWidthTiles.has_value() est faux. Vérifie que tooTall.mode vaut core::CameraFramingMode::PerRoom. |
| CameraFramingTest.ValidationNommeLeChampFautif (Majeur) Source/Test/Unit/Core/Levels/test_camera_framing.cpp:100 | La validation nomme le champ fautif pour chaque cas invalide. | 1. Valider une taille de salle nulle, puis supérieure au niveau, puis un paramètre de taille de vue sur le mode niveau entier. 2. Valider une taille de vue sur le mode suivi. | Vérifie que core::validateCameraFramingConfig(zeroWidth, 20, 20).has_value() est vrai. Vérifie que core::validateCameraFramingConfig(exceedsLevel, 20, 20).has_value() est vrai. Vérifie que core::validateCameraFramingConfig(foreignParameter, 20, 20).has_value() est vrai. Vérifie que core::validateCameraFramingConfig(valid, 20, 20).has_value() est faux. Vérifie que core::validateCameraFramingConfig(followWithSize, 20, 20).has_value() est faux. |
| CameraFramingTest.ValidationDesZonesNommeLeChampFautif (Majeur) Source/Test/Unit/Core/Levels/test_camera_framing.cpp:137 | La validation des zones de caméra nomme le champ fautif. | 1. Valider une zone sur un mode qui n'est pas par salle. 2. Valider une zone de largeur nulle, une zone à position négative, une zone dépassant le niveau. 3. Valider un cadrage par salle avec des zones valides, y compris chevauchantes. | Vérifie que core::validateCameraFramingConfig(wrongMode, 20, 20).has_value() est vrai. Vérifie que core::validateCameraFramingConfig(zeroWidth, 20, 20).has_value() est vrai. Vérifie que core::validateCameraFramingConfig(negativePosition, 20, 20).has_value() est vrai. Vérifie que core::validateCameraFramingConfig(exceedsLevel, 20, 20).has_value() est vrai. Vérifie que core::validateCameraFramingConfig(overlapping, 20, 20).has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TileMapTest.GrilleNeuveVideAuxBonnesDimensions (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:18 | Une grille neuve a les bonnes dimensions et n'est composée que de cases Empty. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que map.width() vaut 4. Vérifie que map.height() vaut 3. Vérifie que map.tile(column, row) vaut core::TileType::Empty. |
| TileMapTest.EcritureLectureDUneTuile (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:41 | Écrire puis lire une tuile restitue le type posé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que map.tile(2, 1) vaut core::TileType::Solid. Vérifie que map.tile(0, 0) vaut core::TileType::Empty. |
| TileMapTest.Bornes (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:59 | Les bornes de la grille sont correctement détectées. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que map.inBounds(0, 0) est vrai. Vérifie que map.inBounds(3, 2) est vrai. Vérifie que map.inBounds(4, 2) est faux. Vérifie que map.inBounds(3, 3) est faux. Vérifie que map.inBounds(-1, 0) est faux. |
| TileMapTest.Solidite (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:79 | Seules les tuiles solides bloquent statiquement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que map.isSolid(0, 0) est vrai. Vérifie que map.isSolid(1, 0) est faux. Vérifie que map.isSolid(2, 0) est faux. |
| TileMapTest.IsSolidParType (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:100 | isSolid(TileType) : vrai seulement pour Solid. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::isSolid(core::TileType::Solid) est vrai. Vérifie que core::isSolid(core::TileType::Empty) est faux. Vérifie que core::isSolid(core::TileType::Door) est faux. Vérifie que core::isSolid(core::TileType::Danger) est faux. |
| LevelTest.RestitueSesComposantes (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:117 | Un Level restitue ses composantes (nom, grille, entrée/sortie, mécanismes). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que level.name() vaut "Tutoriel". Vérifie que level.tileMap().width() vaut 5. Vérifie que level.entry() vaut (core::GridPosition{1, 1}). Vérifie que level.exit() vaut (core::GridPosition{3, 2}). Vérifie que level.mechanisms().size() vaut 1u. Vérifie que level.mechanisms().front().switchPosition vaut (core::GridPosition{2, 1}). Vérifie que level.mechanisms().front().doorPosition vaut (core::GridPosition{4, 2}). |
| LevelTest.RestitueSonFondEtSonJeuDeSkinsOuLeurAbsence (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:151 | Un Level restitue son fond et son jeu de skins, ou leur absence. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que sansFond.background().has_value() est faux. Vérifie que sansFond.skinSet().has_value() est faux. Vérifie que avecFond.background().has_value() est vrai. Vérifie que *avecFond.background() vaut "forest.png". Vérifie que avecFond.skinSet().has_value() est vrai. Vérifie que *avecFond.skinSet() vaut "foret". |
| LevelTest.RestitueSonCadrageDeCameraOuLeDefaut (Majeur) Source/Test/Unit/Core/Levels/test_level.cpp:186 | Un Level restitue son cadrage de caméra, ou le défaut à défaut d'un cadrage fourni. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que defaut.cameraFraming().mode vaut core::CameraFramingMode::WholeLevel. Vérifie que avecCadrage.cameraFraming().mode vaut core::CameraFramingMode::Follow. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LevelDraftTest.PaintTilePoseLeType (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:30 | paintTile pose le type demandé sur la case visée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Solid. |
| LevelDraftTest.SetEntryDeplaceLEntreeExistante (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:46 | Poser une seconde entrée déplace la première (unicité, EX-EDIT-004). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.entry().has_value() est vrai. Vérifie que *draft.entry() vaut (GridPosition{0, 0}). Vérifie que *draft.entry() vaut (GridPosition{2, 2}). Vérifie que draft.tileMap().tile(0, 0) vaut TileType::Empty. Vérifie que draft.tileMap().tile(2, 2) vaut TileType::Entry. |
| LevelDraftTest.SetExitDeplaceLaSortieExistante (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:68 | Poser une seconde sortie déplace la première (unicité, EX-EDIT-004). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que *draft.exit() vaut (GridPosition{3, 3}). Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Empty. Vérifie que draft.tileMap().tile(3, 3) vaut TileType::Exit. |
| LevelDraftTest.PeindrePardessusLEntreeLInvalide (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:87 | Peindre par-dessus l'entrée invalide la position d'entrée mémorisée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.entry().has_value() est faux. Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Solid. |
| LevelDraftTest.LierPuisDelierUnMecanisme (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:105 | Lier un interrupteur à une porte crée un mécanisme ; le délier le retire. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().size() vaut 1u. Vérifie que draft.mechanisms().front().switchPosition vaut (GridPosition{0, 0}). Vérifie que draft.mechanisms().front().doorPosition vaut (GridPosition{3, 3}). Vérifie que draft.mechanisms().empty() est vrai. |
| LevelDraftTest.LierUneCleAUnePorteVerrouillee (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:130 | Lier une clé à une porte verrouillée crée un mécanisme. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().size() vaut 1u. Vérifie que draft.mechanisms().front().switchPosition vaut (GridPosition{0, 0}). Vérifie que draft.mechanisms().front().doorPosition vaut (GridPosition{3, 3}). |
| LevelDraftTest.RoundTripEditionCleEtPorteVerrouillee (Critique) Source/Test/Unit/Core/Levels/test_level_draft.cpp:152 | Poser, lier, enregistrer et recharger une clé/porte verrouillée donne un modèle identique. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->mechanisms().size() vaut 1u. Vérifie que reloaded.level->mechanisms().front().switchPosition vaut (GridPosition{1, 0}). Vérifie que reloaded.level->mechanisms().front().doorPosition vaut (GridPosition{2, 0}). Vérifie que reloaded.level->tileMap().tile(1, 0) vaut TileType::Key. Vérifie que reloaded.level->tileMap().tile(2, 0) vaut TileType::LockedDoor. |
| LevelDraftTest.LierUnePlaqueDePression (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:181 | Lier une plaque de pression à une porte crée un mécanisme. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().size() vaut 1u. Vérifie que draft.mechanisms().front().switchPosition vaut (GridPosition{0, 0}). Vérifie que draft.mechanisms().front().doorPosition vaut (GridPosition{3, 3}). |
| LevelDraftTest.RelierUnePorteRemplaceLaLiaisonPrecedente (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:202 | Relier une porte déjà liée remplace la liaison précédente (une porte, un interrupteur). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().size() vaut 1u. Vérifie que draft.mechanisms().front().switchPosition vaut (GridPosition{1, 0}). |
| LevelDraftTest.UnInterrupteurPeutOuvrirPlusieursPortes (Mineur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:227 | Un interrupteur peut ouvrir plusieurs portes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().size() vaut 2u. |
| LevelDraftTest.PeindrePardessusUnInterrupteurRetireSesLiaisons (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:249 | Peindre par-dessus un interrupteur retire les liaisons qui le référencent. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().empty() est vrai. |
| LevelDraftTest.AgrandirConserveLeContenu (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:269 | Agrandir la grille conserve le contenu existant et complète en cases vides. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.tileMap().width() vaut 5. Vérifie que draft.tileMap().height() vaut 5. Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Entry. Vérifie que *draft.entry() vaut (GridPosition{1, 1}). Vérifie que draft.tileMap().tile(4, 4) vaut TileType::Empty. |
| LevelDraftTest.ReduireTronqueEtInvalideLEntreePerdue (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:292 | Réduire la grille tronque le contenu hors bornes et invalide l'entrée perdue. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.tileMap().width() vaut 3. Vérifie que draft.tileMap().height() vaut 3. Vérifie que draft.entry().has_value() est faux. Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Solid. |
| LevelDraftTest.ReduireRetireLesMecanismesHorsBornes (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:316 | Réduire la grille retire les mécanismes dont une extrémité sort des bornes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().empty() est vrai. |
| LevelDraftTest.ToLevelSansSortieEchoueProprement (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:337 | toLevel() sur un brouillon sans sortie échoue avec un message récupérable (EX-EDIT-007). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.error.empty() est faux. |
| LevelDraftTest.FromLevelRestitueLeContenu (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:358 | Un brouillon reconstruit depuis un niveau existant restitue son contenu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que draft.name() vaut "Depart". Vérifie que *draft.entry() vaut (GridPosition{0, 0}). Vérifie que *draft.exit() vaut (GridPosition{2, 2}). |
| LevelDraftTest.BrouillonNeufSansHistorique (Mineur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:380 | Un brouillon neuf ne peut ni annuler ni refaire. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.canUndo() est faux. Vérifie que draft.canRedo() est faux. |
| LevelDraftTest.UndoApresPeintureRestitueLEtatPrecedent (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:396 | undo() après une peinture restitue l'état exact précédent. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.canUndo() est vrai. Vérifie que undone est vrai. Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Empty. Vérifie que draft.canUndo() est faux. Vérifie que draft.canRedo() est vrai. |
| LevelDraftTest.RedoApresUndoRestitueLEtatMute (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:419 | redo() après un undo() restitue l'état muté. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que redone est vrai. Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Solid. Vérifie que draft.canUndo() est vrai. Vérifie que draft.canRedo() est faux. |
| LevelDraftTest.SequenceDeMutationsPuisUndoRestitueLEtatInitial (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:442 | Une séquence de N mutations suivie de N undo() restitue l'état initial exact. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.undo() est vrai. Vérifie que draft.undo() est vrai. Vérifie que draft.undo() est vrai. Vérifie que draft.undo() est vrai. Vérifie que draft.canUndo() est faux. Vérifie que draft.tileMap().tile(0, 0) vaut TileType::Empty. Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Empty. Vérifie que draft.tileMap().tile(2, 2) vaut TileType::Empty. Vérifie que draft.tileMap().tile(4, 4) vaut TileType::Empty. Vérifie que draft.entry().has_value() est faux. Vérifie que draft.exit().has_value() est faux. |
| LevelDraftTest.MutationApresUndoInvalideLeRefaire (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:474 | Une nouvelle mutation après un undo() invalide la branche de refaire. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.canRedo() est vrai. Vérifie que draft.canRedo() est faux. Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Danger. |
| LevelDraftTest.UndoRedoSurPileVideSansEffet (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:496 | undo()/redo() sur une pile vide est sans effet (pas de plantage). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.undo() est faux. Vérifie que draft.redo() est faux. Vérifie que draft.tileMap().tile(0, 0) vaut TileType::Empty. |
| LevelDraftTest.UndoApresLiaisonMecanismeRestitueLAbsenceDeLiaison (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:513 | L'annulation d'une liaison de mécanisme restitue la liaison précédente. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().size() vaut 1u. Vérifie que draft.mechanisms().empty() est vrai. |
| LevelDraftTest.SetBackgroundEtSetSkinSetAssignentEtRetirent (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:536 | setBackground/setSkinSet assignent et retirent les champs correspondants. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.background().has_value() est faux. Vérifie que draft.skinSet().has_value() est faux. Vérifie que draft.background().has_value() est vrai. Vérifie que *draft.background() vaut "forest.png". Vérifie que draft.skinSet().has_value() est faux. Vérifie que draft.skinSet().has_value() est vrai. Vérifie que *draft.skinSet() vaut "foret". Vérifie que draft.background().has_value() est faux. Vérifie que draft.skinSet().has_value() est vrai. Vérifie que *draft.skinSet() vaut "foret". |
| LevelDraftTest.UndoRedoApresChangementDeFondEtDeJeuDeSkins (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:567 | L'annulation d'un changement de fond ou de jeu de skins restitue la valeur precedente. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.canUndo() est vrai. Vérifie que draft.undo() est vrai. Vérifie que draft.skinSet().has_value() est faux. Vérifie que draft.background().has_value() est vrai. Vérifie que *draft.background() vaut "forest.png". Vérifie que draft.undo() est vrai. Vérifie que draft.background().has_value() est faux. Vérifie que draft.redo() est vrai. Vérifie que draft.background().has_value() est vrai. Vérifie que *draft.background() vaut "forest.png". |
| LevelDraftTest.SetCameraFramingChangeLeModeEtSAnnule (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:598 | setCameraFraming change le mode de cadrage et s'annule. | 1. Créer un brouillon vierge et vérifier son cadrage par défaut. 2. Appeler setCameraFraming avec le mode suivi. 3. Annuler. | Vérifie que draft.cameraFraming().mode vaut core::CameraFramingMode::WholeLevel. Vérifie que draft.cameraFraming().mode vaut core::CameraFramingMode::Follow. Vérifie que draft.canUndo() est vrai. Vérifie que draft.undo() est vrai. Vérifie que draft.cameraFraming().mode vaut core::CameraFramingMode::WholeLevel. |
| LevelDraftTest.AddEtRemoveCameraZoneSontAnnulables (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:622 | addCameraZone/removeCameraZone ajoutent et retirent une zone, annulables. | 1. Ajouter deux zones sur un brouillon vierge. 2. Retirer la première. 3. Annuler le retrait, puis annuler les deux ajouts. | Vérifie que draft.cameraFraming().zones.empty() est vrai. Vérifie que draft.cameraFraming().zones.size() vaut 2u. Vérifie que draft.cameraFraming().zones[0].x vaut 0. Vérifie que draft.cameraFraming().zones[1].x vaut 10. Vérifie que draft.cameraFraming().zones.size() vaut 1u. Vérifie que draft.cameraFraming().zones[0].x vaut 10. Vérifie que draft.undo() est vrai. Vérifie que draft.cameraFraming().zones.size() vaut 2u. Vérifie que draft.undo() est vrai. Vérifie que draft.undo() est vrai. Vérifie que draft.cameraFraming().zones.empty() est vrai. |
| LevelDraftTest.RemoveCameraZoneHorsBornesSansEffet (Mineur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:655 | removeCameraZone sur un index hors bornes reste sans effet. | 1. Appeler removeCameraZone avec un index hors bornes sur une liste vide. | Vérifie que draft.cameraFraming().zones.empty() est vrai. Vérifie que draft.canUndo() est faux. |
| LevelDraftTest.PaintRegionAppliqueLeBlocEntier (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:671 | paintRegion applique un bloc homogène comme une succession de paintTile équivalente. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.tileMap().tile(1, 1) vaut TileType::Solid. Vérifie que draft.tileMap().tile(2, 1) vaut TileType::Solid. Vérifie que draft.tileMap().tile(1, 2) vaut TileType::Solid. Vérifie que draft.tileMap().tile(2, 2) vaut TileType::Solid. Vérifie que draft.tileMap().tile(0, 0) vaut TileType::Empty. |
| LevelDraftTest.PaintRegionUnSeulSnapshotUndo (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:697 | paintRegion ne pousse qu'un seul snapshot undo pour tout le bloc. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.undo() est vrai. Vérifie que draft.canUndo() est faux. Vérifie que draft.tileMap().tile(0, 0) vaut TileType::Empty. Vérifie que draft.tileMap().tile(1, 0) vaut TileType::Empty. Vérifie que draft.tileMap().tile(2, 0) vaut TileType::Empty. |
| LevelDraftTest.PaintRegionDecoupeAuxBords (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:721 | paintRegion découpe silencieusement le bloc aux bords de la grille. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.tileMap().tile(1, 2) vaut TileType::Solid. Vérifie que draft.tileMap().tile(2, 2) vaut TileType::Solid. |
| LevelDraftTest.PaintRegionDeplaceLEntree (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:744 | paintRegion qui inclut une position d'entrée déplace l'entrée existante. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.tileMap().tile(0, 0) vaut TileType::Empty. Vérifie que *draft.entry() vaut (GridPosition{2, 2}). |
| LevelDraftTest.PaintRegionRetireLesLiaisonsRecouvertes (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:764 | paintRegion qui recouvre un interrupteur retire les liaisons qui le référencent. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.mechanisms().empty() est vrai. |
| LevelDraftTest.PaintRegionBlocVideSansEffet (Mineur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:787 | paintRegion avec un bloc vide est sans effet. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.canUndo() est faux. |
| LevelDraftTest.WouldResizeDropContentDetecteLaPerte (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:803 | wouldResizeDropContent détecte la perte de l'entrée, de la sortie ou d'une liaison. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.wouldResizeDropContent(3, 3) est vrai. Vérifie que draft.wouldResizeDropContent(2, 5) est vrai. Vérifie que draft.wouldResizeDropContent(10, 10) est faux. Vérifie que draft.wouldResizeDropContent(5, 5) est faux. |
| LevelDraftTest.WouldResizeDropContentFauxSurBrouillonVierge (Mineur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:832 | wouldResizeDropContent est faux sur un brouillon vierge, quelle que soit la taille visee. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.wouldResizeDropContent(1, 1) est faux. |
| LevelDraftTest.UndoApresRedimensionnementRestitueLesDimensions (Majeur) Source/Test/Unit/Core/Levels/test_level_draft.cpp:849 | L'annulation d'un redimensionnement restitue les dimensions et le contenu précédents. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.entry().has_value() est faux. Vérifie que draft.tileMap().width() vaut 5. Vérifie que draft.tileMap().height() vaut 5. Vérifie que draft.entry().has_value() est vrai. Vérifie que *draft.entry() vaut (GridPosition{4, 4}). |
| LevelDraftTest.FromLevelRestitueLesPlansEtLaParallaxe (Critique) Source/Test/Unit/Core/Levels/test_level_draft.cpp:882 | fromLevel restitue les plans picturaux et le drapeau de parallaxe. | 1. Charger un niveau declarant deux plans et la parallaxe desactivee. 2. En construire un brouillon par fromLevel. | Vérifie que loaded.ok() est vrai. Vérifie que draft.planes().size() vaut 2u. Vérifie que draft.planes()[0].fileName vaut "fond.png". Vérifie que draft.planes()[0].pixelsPerUnit vaut 8. Vérifie que draft.planes()[0].parallaxX vaut 0.5F (comparaison flottante). Vérifie que draft.planes()[0].opacity vaut 0.75F (comparaison flottante). Vérifie que draft.planes()[0].depth vaut core::PlaneDepth::Behind. Vérifie que draft.planes()[1].fileName vaut "devant.png". Vérifie que draft.planes()[1].depth vaut core::PlaneDepth::Front. Vérifie que draft.parallaxEnabled() est faux. |
| LevelDraftTest.AllerRetourBrouillonConserveLesPlans (Critique) Source/Test/Unit/Core/Levels/test_level_draft.cpp:927 | Un aller-retour niveau -> brouillon -> niveau conserve les plans. | 1. Charger un niveau declarant deux plans. 2. En faire un brouillon, puis le reconvertir en niveau sans aucune mutation. | Vérifie que loaded.ok() est vrai. Vérifie que rewritten.ok() est vrai. Vérifie que rewritten.level->planes().size() vaut 2u. Vérifie que rewritten.level->planes()[0].fileName vaut "fond.png". Vérifie que rewritten.level->planes()[0].pixelsPerUnit vaut 4. Vérifie que rewritten.level->planes()[1].fileName vaut "devant.png". Vérifie que rewritten.level->planes()[1].depth vaut core::PlaneDepth::Front. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LevelLoaderTest.ChargeUnNiveauValide (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:39 | Un niveau valide est chargé avec ses dimensions, tuiles, entrée/sortie et mécanismes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que result.errorCode vaut core::LevelValidationError::None. Vérifie que level.name() vaut "Tutoriel". Vérifie que level.tileMap().width() vaut 4. Vérifie que level.tileMap().height() vaut 3. Vérifie que level.tileMap().tile(0, 0) vaut core::TileType::Solid. Vérifie que level.tileMap().tile(1, 1) vaut core::TileType::Entry. Vérifie que level.entry() vaut (core::GridPosition{1, 1}). Vérifie que level.exit() vaut (core::GridPosition{3, 2}). Vérifie que level.mechanisms().size() vaut 1u. Vérifie que level.mechanisms().front().switchPosition vaut (core::GridPosition{2, 0}). Vérifie que level.mechanisms().front().doorPosition vaut (core::GridPosition{3, 0}). |
| LevelLoaderTest.NiveauSansVersionSeChargeSansErreur (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:71 | Un niveau sans champ version se charge sans erreur. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que result.errorCode vaut core::LevelValidationError::None. |
| LevelLoaderTest.VersionSuperieureALaVersionGereeEchoueProprement (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:88 | Un niveau dont la version depasse celle geree echoue proprement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut core::LevelValidationError::UnsupportedFormatVersion. |
| LevelLoaderTest.ChargeLeFondEtLeJeuDeSkins (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:114 | Un niveau designant un fond et un jeu de skins restitue les deux champs. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que result.level->background().has_value() est vrai. Vérifie que *result.level->background() vaut "forest.png". Vérifie que result.level->skinSet().has_value() est vrai. Vérifie que *result.level->skinSet() vaut "foret". |
| LevelLoaderTest.SansFondNiJeuDeSkinsLesDeuxChampsSontAbsents (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:144 | Un niveau sans fond ni jeu de skins n'en restitue aucun. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que result.level->background().has_value() est faux. Vérifie que result.level->skinSet().has_value() est faux. |
| LevelLoaderTest.ModeDeCadrageDeclareExplicitementEstRestitue (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:162 | Un mode de cadrage déclaré explicitement est restitué tel quel. | 1. Charger un niveau déclarant le mode par salle avec une taille personnalisée. 2. Vérifier le cadrage résolu. | Vérifie que result.ok() est vrai. Vérifie que result.level->cameraFraming().mode vaut core::CameraFramingMode::PerRoom. Vérifie que result.level->cameraFraming().roomWidthTiles.has_value() est vrai. Vérifie que *result.level->cameraFraming().roomWidthTiles vaut 10. Vérifie que result.level->cameraFraming().roomHeightTiles.has_value() est vrai. Vérifie que *result.level->cameraFraming().roomHeightTiles vaut 8. |
| LevelLoaderTest.ZonesDeCameraDeclareesSontRestitueesDansLOrdre (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:191 | Les zones de caméra dessinées à la main sont restituées dans l'ordre du fichier. | 1. Charger un niveau déclarant deux zones de caméra. 2. Vérifier leur nombre, leur ordre et leurs bornes. | Vérifie que result.ok() est vrai. Vérifie que result.level->cameraFraming().zones.size() vaut 2u. Vérifie que result.level->cameraFraming().zones[0] vaut (core::CameraZone{.x = 0, .y = 0, .width = 24, .height = 14}). Vérifie que result.level->cameraFraming().zones[1] vaut (core::CameraZone{.x = 24, .y = 0, .width = 6, .height = 20}). |
| LevelLoaderTest.AbsenceDeCameraFramingReproduitLaRegleHistorique (Critique) Source/Test/Unit/Core/Levels/test_level_loader.cpp:226 | L'absence de cameraFraming reproduit la règle historique. | 1. Charger un petit niveau (tient dans une salle) sans champ cameraFraming. 2. Charger un grand niveau (dépasse une salle) sans champ cameraFraming. | Vérifie que small.ok() est vrai. Vérifie que small.level->cameraFraming().mode vaut core::CameraFramingMode::WholeLevel. Vérifie que large.ok() est vrai. Vérifie que large.level->cameraFraming().mode vaut core::CameraFramingMode::PerRoom. Vérifie que large.level->cameraFraming().roomWidthTiles.has_value() est faux. Vérifie que large.level->cameraFraming().roomHeightTiles.has_value() est faux. |
| LevelLoaderTest.CadrageInvalideEchoueAvecErreurExploitable (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:264 | Un cadrage invalide échoue avec une erreur exploitable. | 1. Charger successivement un niveau par variante d'erreur (mode inconnu, taille nulle, taille supérieure au niveau, paramètre étranger au mode). | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut core::LevelValidationError::InvalidCameraFraming. |
| LevelLoaderTest.ChargeUnePlaqueDePression (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:305 | Une plaque de pression se charge comme un interrupteur. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que level.tileMap().tile(2, 0) vaut core::TileType::PressurePlate. Vérifie que level.mechanisms().size() vaut 1u. Vérifie que level.mechanisms().front().switchPosition vaut (core::GridPosition{2, 0}). Vérifie que level.mechanisms().front().doorPosition vaut (core::GridPosition{3, 0}). |
| LevelLoaderTest.ChargeUnBlocPoussable (Majeur) Source/Test/Unit/Core/Levels/test_level_loader.cpp:339 | Un bloc poussable se charge comme une simple tuile, sans identifiant ni liaison. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que level.tileMap().tile(2, 0) vaut core::TileType::Block. Vérifie que level.mechanisms().empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LevelOutcomeTest.ZoneLibreEstEnCours (Majeur) Source/Test/Unit/Core/Levels/test_level_outcome.cpp:42 | En zone libre (ni sortie, ni danger, dans les limites) : partie en cours. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::evaluateOutcome(unitBox(1.0f, 1.0f), level) vaut core::LevelOutcome::Playing. |
| LevelOutcomeTest.SurLaSortieEstGagne (Majeur) Source/Test/Unit/Core/Levels/test_level_outcome.cpp:57 | La boîte recouvrant la case de sortie : niveau gagné. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::evaluateOutcome(unitBox(8.0f, 8.0f), level) vaut core::LevelOutcome::Won. |
| LevelOutcomeTest.SurUnDangerEstPerdu (Majeur) Source/Test/Unit/Core/Levels/test_level_outcome.cpp:72 | La boîte recouvrant une tuile Danger : niveau perdu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::evaluateOutcome(unitBox(5.0f, 5.0f), level) vaut core::LevelOutcome::Lost. |
| LevelOutcomeTest.SousLaLimiteBasseEstPerdu (Majeur) Source/Test/Unit/Core/Levels/test_level_outcome.cpp:87 | La boîte sous la limite basse (chute dans le vide) : niveau perdu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::evaluateOutcome(unitBox(2.0f, 10.0f), level) vaut core::LevelOutcome::Lost. |
| LevelOutcomeTest.EchecPrioritaireSurSucces (Majeur) Source/Test/Unit/Core/Levels/test_level_outcome.cpp:102 | Recouvrement simultané sortie + danger : l'échec est prioritaire (déterminisme). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::evaluateOutcome(unitBox(5.0f, 5.0f), level) vaut core::LevelOutcome::Lost. |
| LevelOutcomeTest.BoiteSupplementaireProvoqueLEchec (Majeur) Source/Test/Unit/Core/Levels/test_level_outcome.cpp:120 | Une boîte supplémentaire fournie par l'appelant provoque l'échec. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::evaluateOutcome(unitBox(1.0f, 1.0f), level, extraDangerBoxes) vaut core::LevelOutcome::Playing. Vérifie que core::evaluateOutcome(unitBox(3.0f, 3.0f), level, extraDangerBoxes) vaut core::LevelOutcome::Lost. |
| LevelOutcomeTest.SansBoiteSupplementaireComportementInchange (Majeur) Source/Test/Unit/Core/Levels/test_level_outcome.cpp:141 | Sans boîte supplémentaire, le comportement est inchangé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::evaluateOutcome(unitBox(5.0f, 5.0f), level) vaut core::LevelOutcome::Lost. Vérifie que core::evaluateOutcome(unitBox(5.0f, 5.0f), level, {}) vaut core::LevelOutcome::Lost. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LevelWriterTest.PlaqueDePressionSurvitAuRoundTrip (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:41 | Une plaque de pression survit au round-trip. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->tileMap().tile(2, 0) vaut core::TileType::PressurePlate. Vérifie que reloaded.level->mechanisms().size() vaut 1u. Vérifie que reloaded.level->mechanisms().front().switchPosition vaut (core::GridPosition{2, 0}). Vérifie que reloaded.level->mechanisms().front().doorPosition vaut (core::GridPosition{3, 0}). |
| LevelWriterTest.CleEtPorteVerrouilleeSurvitAuRoundTrip (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:77 | Une clé et une porte verrouillée survivent au round-trip. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->tileMap().tile(2, 0) vaut core::TileType::Key. Vérifie que reloaded.level->tileMap().tile(3, 0) vaut core::TileType::LockedDoor. Vérifie que reloaded.level->mechanisms().size() vaut 1u. Vérifie que reloaded.level->mechanisms().front().switchPosition vaut (core::GridPosition{2, 0}). Vérifie que reloaded.level->mechanisms().front().doorPosition vaut (core::GridPosition{3, 0}). |
| LevelWriterTest.BlocPoussableSurvitAuRoundTrip (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:115 | Un bloc poussable survit au round-trip. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->tileMap().tile(2, 0) vaut core::TileType::Block. Vérifie que reloaded.level->mechanisms().empty() est vrai. |
| LevelWriterTest.FondEtJeuDeSkinsSurviventAuRoundTrip (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:148 | Le fond et le jeu de skins survivent au round-trip. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->background().has_value() est vrai. Vérifie que *reloaded.level->background() vaut "forest.png". Vérifie que reloaded.level->skinSet().has_value() est vrai. Vérifie que *reloaded.level->skinSet() vaut "foret". |
| LevelWriterTest.SansFondNiJeuDeSkinsLesClesSontOmisesDuJson (Mineur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:178 | Sans fond ni jeu de skins, les cles sont absentes du JSON produit. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que json.find("\\"background\\\\"\")</tt> vaut <tt>std::string::npos</tt>.<br/>Vérifie que <tt>json.find(\"\\\\"skinSet\\\\"\")</tt> vaut <tt>std::string::npos</tt>.<br/>Vérifie que <tt>json.find(\"\\\\"version\\\\"\") diffère de std::string::npos. |
| LevelWriterTest.InterrupteurNonRelieRegenereUnIdentifiant (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:200 | Un interrupteur non relié à une porte est tout de même sérialisé, avec un identifiant. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->tileMap().tile(1, 1) vaut core::TileType::Switch. Vérifie que reloaded.level->mechanisms().empty() est vrai. |
| LevelWriterTest.SaveToFileEcritUnFichierRechargeable (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:226 | saveToFile écrit un fichier qui se recharge à l'identique (round-trip disque). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que core::LevelWriter::saveToFile(*loaded.level, path) est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->name() vaut loaded.level->name(). Vérifie que reloaded.level->entry() vaut loaded.level->entry(). |
| LevelWriterTest.SaveToFileVersDossierInexistantEchoueProprement (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:253 | saveToFile vers un dossier inexistant échoue proprement (récupérable, EX-NFR-040). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que core::LevelWriter::saveToFile(*loaded.level, path) est faux. |
| LevelWriterTest.ChacunDesTroisModesDeCadrageSurvitAuRoundTrip (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:273 | Chacun des trois modes de cadrage survit au round-trip. | 1. Charger un niveau déclarant chacun des trois modes de cadrage. 2. Sérialiser puis recharger. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->cameraFraming().mode vaut loaded.level->cameraFraming().mode. Vérifie que reloaded.level->cameraFraming().roomWidthTiles vaut loaded.level->cameraFraming().roomWidthTiles. Vérifie que reloaded.level->cameraFraming().roomHeightTiles vaut loaded.level->cameraFraming().roomHeightTiles. |
| LevelWriterTest.ZonesDeCameraSurviventAuRoundTrip (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:329 | Les zones de caméra dessinées à la main survivent au round-trip. | 1. Charger un niveau déclarant deux zones de caméra. 2. Sérialiser puis recharger. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->cameraFraming().zones vaut loaded.level->cameraFraming().zones. |
| LevelWriterTest.CadrageIdentiqueAuRepliResteOmisDuJson (Majeur) Source/Test/Unit/Core/Levels/test_level_writer.cpp:363 | Un cadrage identique au repli reste omis du JSON écrit. | 1. Charger un petit niveau sans champ cameraFraming (repli : niveau entier). 2. Sérialiser. | Vérifie que loaded.ok() est vrai. Vérifie que json.find("cameraFraming") vaut std::string::npos. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CouchesDeCarteTest.CarteVersion2PromueEnCoucheLegacyUnique (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:104 | Une carte version 2 est promue en couche unique. | 1. Charger une carte au format version 2, sans tableau 'layers'. 2. Inspecter les couches du niveau obtenu. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->layers().size() vaut 1u. Vérifie que layer.kind vaut core::LayerKind::Legacy. Vérifie que layer.tiles.width() vaut loaded.level->tileMap().width(). Vérifie que layer.tiles.height() vaut loaded.level->tileMap().height(). Vérifie que layer.tiles.tile(0, 0) vaut core::TileType::Solid. Vérifie que loaded.level->entities().empty() est vrai. |
| CouchesDeCarteTest.CarteVersion2ReecriteSansTableauDeCouches (Mineur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:129 | Une carte version 2 reecrite ne gagne pas de tableau 'layers'. | 1. Charger une carte version 2. 2. La reserialiser. | Vérifie que loaded.ok() est vrai. Vérifie que json.find("\\"layers\\\\"\")</tt> vaut <tt>std::string::npos</tt>.<br/>Vérifie que <tt>json.find(\"\\\\"entities\\\\"\") vaut std::string::npos. |
| CouchesDeCarteTest.AllerRetourSurTroisCouchesEtDeuxEntites (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:148 | Une carte a trois couches et deux entites survit a l'aller-retour. | 1. Charger une carte version 3 a trois couches et deux entites. 2. La reserialiser puis la recharger. 3. Comparer couches et entites au niveau d'origine. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->layers().size() vaut loaded.level->layers().size(). Vérifie que after.name vaut before.name. Vérifie que after.kind vaut before.kind. Vérifie que after.tiles.width() vaut before.tiles.width(). Vérifie que after.tiles.height() vaut before.tiles.height(). Vérifie que after.tiles.tile(column, row) vaut before.tiles.tile(column, row). Vérifie que reloaded.level->entities().size() vaut 2u. Vérifie que reloaded.level->entities()[0].type vaut "npc". Vérifie que reloaded.level->entities()[0].position vaut (core::GridPosition{2, 2}). Vérifie que reloaded.level->entities()[1].type vaut "chest". Vérifie que reloaded.level->entities()[1].position vaut (core::GridPosition{0, 2}). |
| CouchesDeCarteTest.ChampsInconnusDUneCouchePreservesALaReecriture (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:190 | Les champs inconnus d'une couche sont preserves a la reecriture. | 1. Charger une couche portant quatre cles inconnues (booleen, entier, reel, chaine). 2. Reserialiser puis recharger. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que decor diffère de nullptr. Vérifie que decor->properties.size() vaut 4u. Vérifie que std::get<bool>(decor->properties.at("difficultTerrain")) vaut true. Vérifie que std::get<std::int64_t>(decor->properties.at("coverBonus")) vaut 2. Vérifie que std::get<double>(decor->properties.at("heightMeters")) vaut 1.5 (comparaison flottante). Vérifie que std::get<std::string>(decor->properties.at("note")) vaut "tapis". |
| CouchesDeCarteTest.ChampsInconnusDUneEntitePreservesALaReecriture (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:218 | Les champs inconnus d'une entite sont preserves a la reecriture. | 1. Charger une entite portant un dialogue, un niveau et un drapeau. 2. Reserialiser puis recharger. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->entities().size() vaut 2u. Vérifie que npc.properties.size() vaut 3u. Vérifie que std::get<std::string>(npc.properties.at("dialogue")) vaut "bonjour". Vérifie que std::get<std::int64_t>(npc.properties.at("level")) vaut 3. Vérifie que std::get<bool>(npc.properties.at("hostile")) vaut false. Vérifie que reloaded.level->entities().back().properties.empty() est vrai. |
| CouchesDeCarteTest.LaCoucheDeCollisionEstLaGrilleDuGameplay (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:246 | La couche de collision est la grille du gameplay. | 1. Charger une carte dont le decor pose un danger en (2, 1), absent de la collision. 2. Lire la grille du niveau. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->tileMap().tile(0, 0) vaut core::TileType::Solid. Vérifie que loaded.level->tileMap().tile(2, 1) vaut core::TileType::Empty. Vérifie que decor diffère de nullptr. Vérifie que decor->tiles.tile(2, 1) vaut core::TileType::Danger. Vérifie que collision diffère de nullptr. Vérifie que &loaded.level->layers().front() vaut collision. Vérifie que collision->tiles.tile(1, 1) vaut core::TileType::Entry. |
| CouchesDeCarteTest.ProjectionEcsIgnoreLaCoucheDeCollision (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:274 | La projection ECS ignore la couche de collision. | 1. Charger une carte a trois couches (2 tuiles de sol, 1 de decor, 1 de collision). 2. Projeter le niveau en entites ECS. | Vérifie que loaded.ok() est vrai. Vérifie que spriteCount vaut 3u. Vérifie que std::count(orders.begin(), orders.end(), 0) vaut 2. Vérifie que std::count(orders.begin(), orders.end(), 1) vaut 1. |
| CouchesDeCarteTest.CarteVersion4RefuseeAvecUnMessageExplicite (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:304 | Une carte version 4 est refusee explicitement. | 1. Charger une carte declarant version 4. | Vérifie que loaded.ok() est faux. Vérifie que loaded.errorCode vaut core::LevelValidationError::UnsupportedFormatVersion. Vérifie que loaded.error.find('4') diffère de std::string::npos. |
| CouchesDeCarteTest.TuileHorsBornesDansUneCoucheRefusee (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:332 | Une tuile hors bornes dans une couche est refusee. | 1. Charger une carte dont une couche pose une tuile en dehors de la grille. | Vérifie que loaded.ok() est faux. Vérifie que loaded.errorCode vaut core::LevelValidationError::OutOfBounds. Vérifie que loaded.error.find("sol") diffère de std::string::npos. |
| CouchesDeCarteTest.EntiteHorsBornesRefusee (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:361 | Une entite hors bornes est refusee. | 1. Charger une carte dont une entite est posee en dehors de la grille. | Vérifie que loaded.ok() est faux. Vérifie que loaded.errorCode vaut core::LevelValidationError::OutOfBounds. |
| CouchesDeCarteTest.RoleDeCoucheInconnuRetombeSurLeSol (Mineur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:388 | Un role de couche inconnu ne fait pas echouer la carte. | 1. Charger une carte dont une couche declare un role inconnu. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->layers().size() vaut 2u. Vérifie que loaded.level->layers().back().kind vaut core::LayerKind::Ground. Vérifie que loaded.level->layers().back().name vaut "brouillard". |
| CouchesDeCarteTest.BrouillonDEditionPreserveCouchesEtEntites (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:418 | Le brouillon d'edition preserve couches et entites. | 1. Charger une carte version 3 et en faire un brouillon d'edition. 2. Reconvertir le brouillon en niveau, sans rien modifier. | Vérifie que loaded.ok() est vrai. Vérifie que draft.layers().size() vaut 3u. Vérifie que draft.entities().size() vaut 2u. Vérifie que rebuilt.ok() est vrai. Vérifie que rebuilt.level->layers().size() vaut 3u. Vérifie que rebuilt.level->entities().size() vaut 2u. |
| CouchesDeCarteTest.TuilePeinteAtteintLaCoucheDeCollision (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:443 | Une tuile peinte dans l'editeur atteint la couche de collision. | 1. Ouvrir une carte version 3 en brouillon. 2. Peindre un solide en (2, 0). 3. Reconvertir le brouillon en niveau. | Vérifie que loaded.ok() est vrai. Vérifie que rebuilt.ok() est vrai. Vérifie que collision diffère de nullptr. Vérifie que collision->tiles.tile(2, 0) vaut core::TileType::Solid. Vérifie que ground diffère de nullptr. Vérifie que ground->tiles.tile(2, 0) vaut core::TileType::Empty. Vérifie que ground->tiles.tile(1, 0) vaut core::TileType::Solid. |
| CouchesDeCarteTest.RedimensionnementEmporteCouchesEtEntites (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:474 | Un redimensionnement emporte couches et entites. | 1. Ouvrir une carte version 3 de 4x3 en brouillon. 2. La redimensionner en 2x2. | Vérifie que loaded.ok() est vrai. Vérifie que draft.wouldResizeDropContent(2, 2) est vrai. Vérifie que layer.tiles.width() vaut 2. Vérifie que layer.tiles.height() vaut 2. Vérifie que draft.entities().empty() est vrai. |
| CouchesDeCarteTest.CoucheDeCollisionDeclareeRefusee (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:501 | Une couche 'collision' declaree est refusee. | 1. Charger une carte declarant une couche de role 'collision'. | Vérifie que loaded.ok() est faux. Vérifie que loaded.errorCode vaut core::LevelValidationError::ParseError. Vérifie que loaded.error.find("tiles") diffère de std::string::npos. |
| CouchesDeCarteTest.ProjectionEcsAnnonceLeRoleDeChaqueCouche (Majeur) Source/Test/Unit/Core/Levels/test_map_layers.cpp:531 | La projection ECS annonce le role de la couche de chaque tuile. | 1. Projeter une carte version 3 en entites ECS en relevant le role annonce. | Vérifie que loaded.ok() est vrai. Vérifie que parRole[core::LayerKind::Ground] vaut 2. Vérifie que parRole[core::LayerKind::Decor] vaut 1. Vérifie que parRole.count(core::LayerKind::Collision) vaut 0u. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PlaneTest.ValeursParDefaut (Majeur) Source/Test/Unit/Core/Levels/test_plane.cpp:86 | Un plan par défaut est natif, solidaire, opaque et derrière. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que plane.fileName.empty() est vrai. Vérifie que plane.pixelsPerUnit vaut core::PLANE_NATIVE_PIXELS_PER_UNIT. Vérifie que plane.parallaxX vaut 1.0f (comparaison flottante). Vérifie que plane.parallaxY vaut 1.0f (comparaison flottante). Vérifie que plane.opacity vaut 1.0f (comparaison flottante). Vérifie que plane.depth vaut PlaneDepth::Behind. |
| PlaneTest.DensitesValides (Majeur) Source/Test/Unit/Core/Levels/test_plane.cpp:107 | Seules les densités 4, 8 et 16 sont acceptées. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que core::isValidPlaneDensity(4) est vrai. Vérifie que core::isValidPlaneDensity(8) est vrai. Vérifie que core::isValidPlaneDensity(16) est vrai. Vérifie que core::isValidPlaneDensity(0) est faux. Vérifie que core::isValidPlaneDensity(12) est faux. Vérifie que core::isValidPlaneDensity(32) est faux. Vérifie que core::isValidPlaneDensity(-16) est faux. |
| PlaneTest.AddPlaneAjouteEnFinDeListe (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:128 | addPlane ajoute en fin de liste, préservant l'ordre. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.planes().size() vaut 3u. Vérifie que draft.planes()[0].fileName vaut "p0.png". Vérifie que draft.planes()[2].fileName vaut "p2.png". |
| PlaneTest.RemovePlaneRetireAuRangDonne (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:146 | removePlane retire au rang donné, sans effet hors bornes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.planes().size() vaut 2u. Vérifie que draft.planes()[0].fileName vaut "p0.png". Vérifie que draft.planes()[1].fileName vaut "p2.png". Vérifie que draft.planes().size() vaut 2u. |
| PlaneTest.ChaqueMutateurEstAnnulableEtRefaisable (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:169 | Chaque mutateur de plan est annulable et refaisable en un pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.planes()[0].pixelsPerUnit vaut 8. Vérifie que draft.canUndo() est vrai. Vérifie que draft.planes()[0].pixelsPerUnit vaut 16. Vérifie que draft.planes()[0].pixelsPerUnit vaut 8. Vérifie que draft.planes()[0].parallaxX vaut 1.0f (comparaison flottante). Vérifie que draft.planes()[0].parallaxY vaut 0.75f (comparaison flottante). Vérifie que draft.planes()[1].opacity vaut 1.0f (comparaison flottante). Vérifie que draft.planes()[1].opacity vaut 0.25f (comparaison flottante). Vérifie que draft.planes()[1].depth vaut PlaneDepth::Behind. Vérifie que draft.planes()[1].depth vaut PlaneDepth::Front. Vérifie que draft.parallaxEnabled() est faux. Vérifie que draft.parallaxEnabled() est vrai. Vérifie que draft.planes().size() vaut 1u. Vérifie que draft.planes().size() vaut 2u. |
| PlaneTest.MutateurRefuseNEmpileRien (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:222 | Un mutateur refusé n'empile aucun pas d'annulation. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.setPlaneDensity(0, 12) est faux. Vérifie que draft.setPlaneDensity(9, 8) est faux. Vérifie que draft.setPlaneOpacity(0, 1.5f) est faux. Vérifie que draft.setPlaneOpacity(0, -0.1f) est faux. Vérifie que draft.setPlaneOpacity(0, std::numeric_limits<float>::quiet_NaN()) est faux. Vérifie que draft.setPlaneParallax(0, std::numeric_limits<float>::infinity(), 1.0f) est faux. Vérifie que draft.setPlaneDepth(9, PlaneDepth::Front) est faux. Vérifie que draft.movePlaneForward(9).has_value() est faux. Vérifie que draft.movePlaneToBack(9).has_value() est faux. Vérifie que draft.canUndo() vaut hadUndo. Vérifie que draft.planes()[0].pixelsPerUnit vaut 16. Vérifie que draft.planes()[0].opacity vaut 1.0f (comparaison flottante). |
| PlaneTest.ReordonnancementDesPlans (Majeur) Source/Test/Unit/Core/Levels/test_plane.cpp:257 | Le réordonnancement déplace le plan et renvoie son nouveau rang. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.movePlaneForward(0) vaut 1u. Vérifie que draft.planes()[1].fileName vaut "p0.png". Vérifie que draft.movePlaneBackward(1) vaut 0u. Vérifie que draft.planes()[0].fileName vaut "p0.png". Vérifie que draft.movePlaneToFront(0) vaut 3u. Vérifie que draft.planes()[3].fileName vaut "p0.png". Vérifie que draft.movePlaneToBack(3) vaut 0u. Vérifie que draft.planes()[0].fileName vaut "p0.png". Vérifie que draft.movePlaneBackward(0) vaut 0u. Vérifie que draft.movePlaneForward(3) vaut 3u. Vérifie que draft.planes()[3].fileName vaut "p3.png". |
| PlaneTest.ChargementDesPlans (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:288 | Les plans sont lus dans l'ordre déclaré, avec leurs défauts. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que planes.size() vaut 3u. Vérifie que planes[0].fileName vaut "ciel.png". Vérifie que planes[0].pixelsPerUnit vaut 4. Vérifie que planes[0].parallaxX vaut 0.25f (comparaison flottante). Vérifie que planes[0].parallaxY vaut 0.25f (comparaison flottante). Vérifie que planes[0].depth vaut PlaneDepth::Behind. Vérifie que planes[1].fileName vaut "mur.png". Vérifie que planes[1].pixelsPerUnit vaut 16. Vérifie que planes[1].parallaxX vaut 1.0f (comparaison flottante). Vérifie que planes[2].fileName vaut "grille.png". Vérifie que planes[2].parallaxY vaut 1.0f (comparaison flottante). Vérifie que planes[2].opacity vaut 0.5f (comparaison flottante). Vérifie que planes[2].depth vaut PlaneDepth::Front. Vérifie que loaded.level->parallaxEnabled() est vrai. |
| PlaneTest.ChampObsoleteDecorsIgnoreEtNonReecrit (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:326 | Le champ obsolete decors est ignore, et disparait a la reecriture. | 1. Charger un niveau portant encore le champ racine decors. 2. Reecrire le niveau charge. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->planes().empty() est vrai. Vérifie que json.find("\\"decors\\\\"\") vaut std::string::npos. |
| PlaneTest.NiveauSansPlanNEcritPasLeChamp (Majeur) Source/Test/Unit/Core/Levels/test_plane.cpp:350 | Un niveau sans plan n'écrit pas le champ planes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->planes().empty() est vrai. Vérifie que json.find("\\"planes\\\\"\")</tt> vaut <tt>std::string::npos</tt>.<br/>Vérifie que <tt>json.find(\"\\\\"parallax\\\\"\") vaut std::string::npos. |
| PlaneTest.RoundTripDesPlans (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:371 | Le round-trip préserve les plans et omet les défauts. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->planes().size() vaut 3u. Vérifie que after.fileName vaut before.fileName. Vérifie que after.pixelsPerUnit vaut before.pixelsPerUnit. Vérifie que after.parallaxX vaut before.parallaxX (comparaison flottante). Vérifie que after.parallaxY vaut before.parallaxY (comparaison flottante). Vérifie que after.opacity vaut before.opacity (comparaison flottante). Vérifie que after.depth vaut before.depth. Vérifie que defaultPlane diffère de nullptr. Vérifie que defaultPlane->size() vaut 1u. |
| PlaneTest.DrapeauDeParallaxeDesactive (Majeur) Source/Test/Unit/Core/Levels/test_plane.cpp:415 | Le drapeau de parallaxe n'est écrit que désactivé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->parallaxEnabled() est faux. Vérifie que nlohmann::json::parse(json).at("parallax").get<bool>() est faux. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->parallaxEnabled() est faux. |
| PlaneTest.DensiteInvalideRejetee (Critique) Source/Test/Unit/Core/Levels/test_plane.cpp:445 | Une densité de plan invalide fait échouer le chargement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est faux. Vérifie que loaded.errorCode vaut core::LevelValidationError::ParseError. |
| PlaneTest.TropDePlansRejete (Majeur) Source/Test/Unit/Core/Levels/test_plane.cpp:468 | Le nombre de plans est plafonné au chargement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est faux. Vérifie que loaded.errorCode vaut core::LevelValidationError::ParseError. |
| PlaneTest.PlanTropGrandRejete (Majeur) Source/Test/Unit/Core/Levels/test_plane.cpp:494 | Un plan dépassant la limite de texture est refusé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est faux. Vérifie que loaded.errorCode vaut core::LevelValidationError::ParseError. Vérifie que core::LevelLoader::loadFromString(smaller).ok() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TerrainRpgTest.AllerRetourSurChaqueTypeDeTerrain (Critique) Source/Test/Unit/Core/Levels/test_rpg_terrain.cpp:50 | Chaque type de terrain survit a l'aller-retour de format. | 1. Pour chacun des neuf types, charger une carte qui le porte. 2. La reserialiser puis la recharger. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->tileMap().tile(2, 0) vaut type. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->tileMap().tile(2, 0) vaut type. |
| TerrainRpgTest.FranchissabiliteDeChaqueTerrain (Critique) Source/Test/Unit/Core/Levels/test_rpg_terrain.cpp:77 | La franchissabilite de chaque terrain est celle que son nom promet. | 1. Interroger isSolid sur les neuf types. | Vérifie que core::isSolid(core::TileType::Wall) est vrai. Vérifie que core::isSolid(core::TileType::Cliff) est vrai. Vérifie que core::isSolid(core::TileType::DeepWater) est vrai. Vérifie que core::isSolid(core::TileType::Grass) est faux. Vérifie que core::isSolid(core::TileType::Dirt) est faux. Vérifie que core::isSolid(core::TileType::Sand) est faux. Vérifie que core::isSolid(core::TileType::Water) est faux. Vérifie que core::isSolid(core::TileType::Bridge) est faux. Vérifie que core::isSolid(core::TileType::Stairs) est faux. |
| TerrainRpgTest.LaRiveDistingueLesDeuxEaux (Majeur) Source/Test/Unit/Core/Levels/test_rpg_terrain.cpp:101 | L'eau peu profonde se traverse, l'eau profonde non. | 1. Comparer la franchissabilite de Water et DeepWater. | Vérifie que core::isSolid(core::TileType::Water) diffère de core::isSolid(core::TileType::DeepWater). |
| TerrainRpgTest.BorneDeLEnumerationDerivee (Majeur) Source/Test/Unit/Core/Levels/test_rpg_terrain.cpp:115 | La borne de l'enumeration reste derivee du dernier type. | 1. Comparer TILE_TYPE_COUNT au dernier enumerateur. 2. Verifier que chaque valeur jusqu'a cette borne porte un nom. | Vérifie que core::TILE_TYPE_COUNT vaut static_cast<int>(core::TileType::Stairs) + 1. Vérifie que core::TILE_TYPE_COUNT vaut 20. Vérifie que name.empty() est faux. Vérifie que std::adjacent_find(sorted.begin(), sorted.end()) vaut sorted.end(). |
test_tile_texture_override.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TileTextureOverrideTest.SetTextureOverrideAssigneLaTexture (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:32 | setTextureOverride assigne une texture à une case précise. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.textureOverrides().front().position vaut (GridPosition{1, 1}). Vérifie que draft.textureOverrides().front().assetName vaut "door_red.png". |
| TileTextureOverrideTest.ReassignerRemplaceLOverrideExistant (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:54 | Réassigner une texture remplace l'override existant. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.textureOverrides().front().assetName vaut "door_blue.png". |
| TileTextureOverrideTest.RemoveTextureOverrideRetireLOverride (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:75 | removeTextureOverride retire l'override d'une case. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().empty() est vrai. Vérifie que draft.textureOverrides().empty() est vrai. |
| TileTextureOverrideTest.PeindreUnAutreTypeRetireLOverride (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:98 | Repeindre un autre type retire l'override. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().empty() est vrai. |
| TileTextureOverrideTest.PeindreLeMemeTypeConserveLOverride (Critique) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:119 | Repeindre le même type conserve l'override. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.textureOverrides().front().assetName vaut "door_red.png". |
| TileTextureOverrideTest.PaintRegionRetireLOverrideDUneCaseDontLeTypeChange (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:141 | paintRegion retire l'override d'une case dont le type change. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().empty() est vrai. |
| TileTextureOverrideTest.CollerUneRegionNeCopiePasLesOverridesDeLaSource (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:163 | Coller une région ne copie pas les overrides de la source. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.textureOverrides().front().position vaut (GridPosition{0, 0}). |
| TileTextureOverrideTest.ReduireLaGrilleTronqueLesOverridesHorsBornes (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:188 | Réduire la grille tronque les overrides hors bornes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().empty() est vrai. |
| TileTextureOverrideTest.WouldResizeDropContentSignaleLaPerteDUnOverride (Mineur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:208 | wouldResizeDropContent signale la perte d'un override. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.wouldResizeDropContent(2, 2) est vrai. Vérifie que draft.wouldResizeDropContent(5, 5) est faux. |
| TileTextureOverrideTest.UndoRedoCouvrentUneAssignation (Critique) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:227 | undo/redo couvrent une assignation de texture. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.undo() est vrai. Vérifie que draft.textureOverrides().empty() est vrai. Vérifie que draft.redo() est vrai. Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.textureOverrides().front().assetName vaut "door_red.png". |
| TileTextureOverrideTest.UndoRestitueUnOverrideRetire (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:252 | undo restitue un override retiré. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que draft.textureOverrides().empty() est vrai. Vérifie que draft.undo() est vrai. Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.textureOverrides().front().assetName vaut "door_red.png". |
| TileTextureOverrideTest.FromLevelRestitueLesOverrides (Majeur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:275 | fromLevel restitue les overrides de texture. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que draft.textureOverrides().size() vaut 1u. Vérifie que draft.textureOverrides().front().position vaut (GridPosition{2, 2}). Vérifie que draft.textureOverrides().front().assetName vaut "door_red.png". |
| TileTextureOverrideTest.LeChampTextureSurvitAuRoundTripJson (Critique) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:303 | Le champ texture survit au round-trip JSON. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que reloaded.level->textureOverrides().size() vaut 2u. Vérifie que hasCrate est vrai. Vérifie que hasDoor est vrai. |
| TileTextureOverrideTest.SansOverrideLeChampTextureEstAbsentDuJson (Mineur) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:341 | Sans override, le champ texture est absent du JSON produit. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que json.find("\\"texture\\\\"\") vaut std::string::npos. |
| TileTextureOverrideTest.NiveauSansChampTextureSeChargeSansOverride (Critique) Source/Test/Unit/Core/Levels/test_tile_texture_override.cpp:362 | Un niveau sans champ texture se charge sans override. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaded.ok() est vrai. Vérifie que loaded.level->textureOverrides().empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TileTypeNameTest.AllerRetourSurTousLesTypes (Critique) Source/Test/Unit/Core/Levels/test_tile_type_name.cpp:28 | Chaque type de tuile fait l'aller-retour par son nom textuel sans perte. | 1. Pour tous les types, convertir le type en nom, puis le nom en type. | Vérifie que parsed.has_value() est vrai. Vérifie que *parsed vaut type. |
| TileTypeNameTest.LesNomsSontUniques (Critique) Source/Test/Unit/Core/Levels/test_tile_type_name.cpp:48 | Deux types de tuiles distincts ne portent jamais le meme nom. | 1. Collecter les noms de tous les types dans un ensemble. | Vérifie que names.size() vaut static_cast<std::size_t>(LAST_TILE_TYPE + 1). |
| TileTypeNameTest.NomInconnuRefuse (Majeur) Source/Test/Unit/Core/Levels/test_tile_type_name.cpp:66 | Un nom de type inconnu est refuse au lieu d'etre devine. | 1. Convertir une chaine vide, un nom inexistant et un nom de casse differente. | Vérifie que core::parseTileType("").has_value() est faux. Vérifie que core::parseTileType("mur").has_value() est faux. Vérifie que core::parseTileType("Solid").has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| DeterministicRandomTest.SplitMix64VecteursDeReference (Bloquant) Source/Test/Unit/Core/Math/test_deterministic_random.cpp:25 | splitMix64 : vecteurs de référence. | 1. splitMix64 sur 0, 1 et 0x0123456789ABCDEF. | Vérifie que core::splitMix64(0x0000000000000000ULL) vaut 0x0000000000000000ULL. Vérifie que core::splitMix64(0x0000000000000001ULL) vaut 0x5692161D100B05E5ULL. Vérifie que core::splitMix64(0x0123456789ABCDEFULL) vaut 0xB2C058E4EBB5112CULL. |
| DeterministicRandomTest.DeriveSeedVecteursDeReference (Bloquant) Source/Test/Unit/Core/Math/test_deterministic_random.cpp:44 | deriveSeed : vecteurs de référence et séparation du triplet. | 1. deriveSeed sur (1,0,0), (1,0,1) et (1,1,0). 2. Comparer les trois entre eux. | Vérifie que core::deriveSeed(1, 0, 0) vaut 0x71CAC37448049CE4ULL. Vérifie que core::deriveSeed(1, 0, 1) vaut 0xC14BF009DE212E89ULL. Vérifie que core::deriveSeed(1, 1, 0) vaut 0x98DCCAA31A8BAF69ULL. Vérifie que core::deriveSeed(1, 0, 1) diffère de core::deriveSeed(1, 1, 0). |
| DeterministicRandomTest.SuiteDeReferenceDepuisUneGraineFixee (Bloquant) Source/Test/Unit/Core/Math/test_deterministic_random.cpp:64 | DeterministicRandom : suite de référence depuis une graine fixée. | 1. DeterministicRandom(42). 2. Cinq appels à nextUInt32(). | Vérifie que random.nextUInt32() vaut 0xBDD73226U. Vérifie que random.nextUInt32() vaut 0x28EFE333U. Vérifie que random.nextUInt32() vaut 0x47526757U. Vérifie que random.nextUInt32() vaut 0x581CE1FFU. Vérifie que random.nextUInt32() vaut 0x09BC585AU. |
| DeterministicRandomTest.MemeGraineMemeSuite (Bloquant) Source/Test/Unit/Core/Math/test_deterministic_random.cpp:82 | DeterministicRandom : même graine, même suite ; graines différentes, suites différentes. | 1. Deux instances de graine 7, 16 tirages chacune. 2. Une instance de graine 8, premier tirage. | Vérifie que first.nextUInt32() vaut second.nextUInt32(). Vérifie que other.nextUInt32() diffère de reference.nextUInt32(). |
| DeterministicRandomTest.NextFloat01ExclutLaBorneHaute (Majeur) Source/Test/Unit/Core/Math/test_deterministic_random.cpp:105 | nextFloat01 : borne haute exclue. | 1. 10 000 tirages depuis une graine fixée. | Vérifie que value est supérieur ou égal à 0.0f. Vérifie que value est strictement inférieur à 1.0f. |
| DeterministicRandomTest.NextRangeRespecteLesBornes (Majeur) Source/Test/Unit/Core/Math/test_deterministic_random.cpp:123 | nextRange : bornes respectées, intervalle dégénéré rendu exactement. | 1. 1 000 tirages dans [-2, 5]. 2. Un tirage dans [3, 3]. | Vérifie que value est supérieur ou égal à -2.0f. Vérifie que value est inférieur ou égal à 5.0f. Vérifie que random.nextRange(3.0f, 3.0f) vaut 3.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MathUtilsTest.EgaliteExacte (Mineur) Source/Test/Unit/Core/Math/test_math_utils.cpp:15 | approximatelyEqual : égalité exacte | 1. Comparer des valeurs identiques (1, 0, -2,5). | Vérifie que core::approximatelyEqual(1.0f, 1.0f) est vrai. Vérifie que core::approximatelyEqual(0.0f, 0.0f) est vrai. Vérifie que core::approximatelyEqual(-2.5f, -2.5f) est vrai. |
| MathUtilsTest.ToleranceParDefaut (Majeur) Source/Test/Unit/Core/Math/test_math_utils.cpp:29 | approximatelyEqual : tolérance par défaut | 1. Comparer 1 et 1+1e-6. 2. Comparer 1 et 1,1. | Vérifie que core::approximatelyEqual(1.0f, 1.0f + 1e-6f) est vrai. Vérifie que core::approximatelyEqual(1.0f, 1.1f) est faux. |
| MathUtilsTest.MiseALEchelleGrandesMagnitudes (Majeur) Source/Test/Unit/Core/Math/test_math_utils.cpp:42 | approximatelyEqual : mise à l'échelle des grandes magnitudes | 1. Comparer 1e6 et 1e6+1. 2. Comparer 1e6 et 1e6+1000. | Vérifie que core::approximatelyEqual(1.0e6f, 1.0e6f + 1.0f) est vrai. Vérifie que core::approximatelyEqual(1.0e6f, 1.0e6f + 1000.0f) est faux. |
| MathUtilsTest.SignesOpposes (Mineur) Source/Test/Unit/Core/Math/test_math_utils.cpp:55 | approximatelyEqual : signes opposés | 1. Comparer 2 et -2. | Vérifie que core::approximatelyEqual(2.0f, -2.0f) est faux. |
| MathUtilsTest.ToleranceExplicite (Mineur) Source/Test/Unit/Core/Math/test_math_utils.cpp:67 | approximatelyEqual : tolérance explicite | 1. Comparer 1 et 1,5 sans tolérance. 2. Recomparer avec une tolérance de 1. | Vérifie que core::approximatelyEqual(1.0f, 1.5f) est faux. Vérifie que core::approximatelyEqual(1.0f, 1.5f, 1.0f) est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RectTest.Bords (Majeur) Source/Test/Unit/Core/Math/test_rect.cpp:20 | Les bords exposés découlent de la position et de la taille. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que rect.left() vaut 10.0f, à TOLERANCE près. Vérifie que rect.top() vaut 20.0f, à TOLERANCE près. Vérifie que rect.right() vaut 40.0f, à TOLERANCE près. Vérifie que rect.bottom() vaut 60.0f, à TOLERANCE près. |
| RectTest.ContientPointInterieur (Majeur) Source/Test/Unit/Core/Math/test_rect.cpp:38 | Un point strictement intérieur est contenu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que rect.contains(core::Vector2{5.0f, 5.0f}) est vrai. |
| RectTest.ContientBords (Majeur) Source/Test/Unit/Core/Math/test_rect.cpp:53 | Contenance inclusive haut/gauche, exclusive bas/droit. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que rect.contains(core::Vector2{0.0f, 0.0f}) est vrai. Vérifie que rect.contains(core::Vector2{10.0f, 5.0f}) est faux. Vérifie que rect.contains(core::Vector2{5.0f, 10.0f}) est faux. |
| RectTest.NeContientPasExterieur (Majeur) Source/Test/Unit/Core/Math/test_rect.cpp:70 | Un point extérieur n'est pas contenu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que rect.contains(core::Vector2{-1.0f, 5.0f}) est faux. Vérifie que rect.contains(core::Vector2{5.0f, 100.0f}) est faux. |
| RectTest.IntersectionRecouvrement (Majeur) Source/Test/Unit/Core/Math/test_rect.cpp:86 | Deux rectangles qui se recouvrent s'intersectent (relation symétrique). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que a.intersects(b) est vrai. Vérifie que b.intersects(a) est vrai. |
| RectTest.ContactBordSansIntersection (Majeur) Source/Test/Unit/Core/Math/test_rect.cpp:103 | Un simple contact par un bord ne compte pas comme intersection. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que a.intersects(b) est faux. |
| RectTest.Disjonction (Majeur) Source/Test/Unit/Core/Math/test_rect.cpp:119 | Deux rectangles disjoints ne s'intersectent pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que a.intersects(b) est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| Vector2Test.AdditionSoustraction (Majeur) Source/Test/Unit/Core/Math/test_vector2.cpp:19 | Vector2 : addition et soustraction | 1. Poser deux vecteurs. 2. Calculer a+b et a-b. | Vérifie que a + b vaut core::Vector2(4.0f, -2.0f). Vérifie que a - b vaut core::Vector2(-2.0f, 6.0f). |
| Vector2Test.EchelleScalaire (Majeur) Source/Test/Unit/Core/Math/test_vector2.cpp:34 | Vector2 : échelle par un scalaire | 1. Poser un vecteur. 2. Multiplier/diviser par un scalaire, prendre l'opposé. | Vérifie que v * 2.0f vaut core::Vector2(4.0f, -6.0f). Vérifie que 2.0f * v vaut core::Vector2(4.0f, -6.0f). Vérifie que v / 2.0f vaut core::Vector2(1.0f, -1.5f). Vérifie que -v vaut core::Vector2(-2.0f, 3.0f). |
| Vector2Test.OperateursComposes (Mineur) Source/Test/Unit/Core/Math/test_vector2.cpp:50 | Vector2 : opérateurs composés | 1. Appliquer +=, -=, *=, /= à un vecteur. | Vérifie que v vaut core::Vector2(3.0f, 4.0f). Vérifie que v vaut core::Vector2(2.0f, 3.0f). Vérifie que v vaut core::Vector2(4.0f, 6.0f). Vérifie que v vaut core::Vector2(2.0f, 3.0f). |
| Vector2Test.ProduitScalaire (Majeur) Source/Test/Unit/Core/Math/test_vector2.cpp:70 | Vector2 : produit scalaire | 1. Calculer a·b. 2. Calculer le produit de deux vecteurs orthogonaux. | Vérifie que a.dot(b) vaut 11.0f, à TOLERANCE près. Vérifie que core::Vector2(1.0f, 0.0f).dot(core::Vector2(0.0f, 1.0f)) vaut 0.0f, à TOLERANCE près. |
| Vector2Test.Longueur (Majeur) Source/Test/Unit/Core/Math/test_vector2.cpp:86 | Vector2 : longueur | 1. Calculer lengthSquared et length de (3, 4). | Vérifie que v.lengthSquared() vaut 25.0f, à TOLERANCE près. Vérifie que v.length() vaut 5.0f, à TOLERANCE près. |
| Vector2Test.NormalisationNonNulle (Majeur) Source/Test/Unit/Core/Math/test_vector2.cpp:100 | Vector2 : normalisation (non nul) | 1. Normaliser (3, 4). | Vérifie que normalized.length() vaut 1.0f, à TOLERANCE près. Vérifie que normalized vaut core::Vector2(0.6f, 0.8f). |
| Vector2Test.NormalisationVecteurNul (Majeur) Source/Test/Unit/Core/Math/test_vector2.cpp:114 | Vector2 : normalisation (vecteur nul) | 1. Normaliser le vecteur nul. | Vérifie que core::Vector2{}.normalized() vaut core::Vector2(0.0f, 0.0f). |
| Vector2Test.EgaliteApprochee (Majeur) Source/Test/Unit/Core/Math/test_vector2.cpp:126 | Vector2 : égalité approchée | 1. Comparer (0,1+0,2 ; 1) à (0,3 ; 1). 2. Comparer deux vecteurs distincts. | Vérifie que a vaut core::Vector2(0.3f, 1.0f). Vérifie que core::Vector2(0.0f, 0.0f) diffère de core::Vector2(1.0f, 0.0f). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AabbVsAabbTest.TrajetLibreLoinDeLObstacle (Majeur) Source/Test/Unit/Core/Physics/test_aabb_vs_aabb.cpp:32 | Balayage boîte-boîte : trajet libre, loin de l'obstacle | 1. Placer un obstacle réduit en (2, 1). 2. Balayer une boîte 1×1 partie de loin, dont le trajet ne le croise pas. | Vérifie que r.hit est faux. Vérifie que r.position.x vaut 11.0f (comparaison flottante). Vérifie que r.position.y vaut 11.0f (comparaison flottante). |
| AabbVsAabbTest.ButeeHorizontaleContreUnObstacleReduit (Bloquant) Source/Test/Unit/Core/Physics/test_aabb_vs_aabb.cpp:51 | Balayage boîte-boîte : butée horizontale contre un obstacle réduit | 1. Placer un obstacle réduit (0,5×0,5) centré en (2, 1). 2. Balayer une boîte 1×1 vers la droite, alignée verticalement avec l'obstacle. | Vérifie que r.hit est vrai. Vérifie que r.position.x vaut 1.25f (comparaison flottante). Vérifie que r.position.y vaut 1.0f (comparaison flottante). Vérifie que r.normal.x vaut -1.0f (comparaison flottante). |
| AabbVsAabbTest.ButeeVerticaleSurUnObstacleReduit (Bloquant) Source/Test/Unit/Core/Physics/test_aabb_vs_aabb.cpp:74 | Balayage boîte-boîte : butée verticale (dessus d'un obstacle réduit) | 1. Placer un obstacle réduit centré en (2, 1). 2. Balayer une boîte 1×1 en chute verticale au-dessus. | Vérifie que r.hit est vrai. Vérifie que r.position.y vaut 0.25f (comparaison flottante). Vérifie que r.normal.y vaut -1.0f (comparaison flottante). |
| AabbVsAabbTest.EspaceAutourDeLObstacleReduitEstFranchissable (Majeur) Source/Test/Unit/Core/Physics/test_aabb_vs_aabb.cpp:96 | Balayage boîte-boîte : le vide autour d'un obstacle réduit reste franchissable | 1. Placer un obstacle réduit centré en (2, 1) (marge de 0,25 de chaque côté). 2. Balayer une boîte étroite qui passe dans cette marge, sans jamais chevaucher l'obstacle. | Vérifie que r.hit est faux. Vérifie que r.position.x vaut 3.5f (comparaison flottante). |
| AabbVsAabbTest.GlissementDiagonalLeLongDUnObstacleReduit (Majeur) Source/Test/Unit/Core/Physics/test_aabb_vs_aabb.cpp:119 | Balayage boîte-boîte : glissement diagonal contre un obstacle réduit | 1. Placer un obstacle réduit centré en (2, 1). 2. Balayer une boîte en diagonale (droite + bas), bloquée en X par l'obstacle mais pas en Y. | Vérifie que r.normal.x vaut -1.0f (comparaison flottante). Vérifie que r.position.x vaut 1.25f (comparaison flottante). Vérifie que r.normal.y vaut 0.0f (comparaison flottante). Vérifie que r.position.y vaut 4.3f (comparaison flottante). |
| AabbVsAabbTest.DeplacementNulNeBougeRien (Mineur) Source/Test/Unit/Core/Physics/test_aabb_vs_aabb.cpp:144 | Balayage boîte-boîte : déplacement nul sur un axe le laisse inchangé | 1. Placer un obstacle réduit. 2. Balayer avec un déplacement nul sur les deux axes. | Vérifie que r.hit est faux. Vérifie que r.position.x vaut 0.0f (comparaison flottante). Vérifie que r.position.y vaut 0.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| SweptCollisionTest.TrajetLibre (Majeur) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:33 | Balayage : trajet libre | 1. Grille sans tuile solide. 2. Balayer une boîte 1×1 d'un déplacement (3, 2). | Vérifie que r.hit est faux. Vérifie que r.position.x vaut 3.0f (comparaison flottante). Vérifie que r.position.y vaut 2.0f (comparaison flottante). Vérifie que r.normal.x vaut 0.0f (comparaison flottante). Vérifie que r.normal.y vaut 0.0f (comparaison flottante). |
| SweptCollisionTest.ButeeHorizontale (Bloquant) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:53 | Balayage : butée horizontale (mur à droite) | 1. Placer un mur solide à droite. 2. Balayer la boîte vers la droite. | Vérifie que r.hit est vrai. Vérifie que r.position.x vaut 2.0f (comparaison flottante). Vérifie que r.position.y vaut 1.0f (comparaison flottante). Vérifie que r.normal.x vaut -1.0f (comparaison flottante). |
| SweptCollisionTest.ButeeVerticale (Bloquant) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:73 | Balayage : butée verticale (sol) | 1. Placer un sol solide en dessous. 2. Balayer la boîte vers le bas. | Vérifie que r.hit est vrai. Vérifie que r.position.y vaut 4.0f (comparaison flottante). Vérifie que r.position.x vaut 1.0f (comparaison flottante). Vérifie que r.normal.y vaut -1.0f (comparaison flottante). |
| SweptCollisionTest.NonTunneling (Bloquant) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:93 | Balayage : non-tunneling à vitesse élevée | 1. Mur à 5 tuiles. 2. Balayer d'un déplacement de 10 (≫ une tuile) vers le mur. | Vérifie que r.hit est vrai. Vérifie que r.position.x vaut 4.0f (comparaison flottante). Vérifie que r.normal.x vaut -1.0f (comparaison flottante). |
| SweptCollisionTest.GlissementLeLongDuMur (Bloquant) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:113 | Balayage : glissement le long d'un mur | 1. Mur vertical à droite. 2. Balayer d'un déplacement diagonal (droite + bas). | Vérifie que r.hit est vrai. Vérifie que r.position.x vaut 2.0f (comparaison flottante). Vérifie que r.position.y vaut 2.0f (comparaison flottante). Vérifie que r.normal.x vaut -1.0f (comparaison flottante). |
| SweptCollisionTest.ButeeGauche (Majeur) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:135 | Balayage : butée horizontale (mur à gauche) | 1. Mur solide à gauche. 2. Balayer la boîte vers la gauche. | Vérifie que r.hit est vrai. Vérifie que r.position.x vaut 3.0f (comparaison flottante). Vérifie que r.normal.x vaut 1.0f (comparaison flottante). |
| SweptCollisionTest.ButeePlafond (Majeur) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:154 | Balayage : butée verticale (plafond) | 1. Plafond solide au-dessus. 2. Balayer la boîte vers le haut. | Vérifie que r.hit est vrai. Vérifie que r.position.y vaut 3.0f (comparaison flottante). Vérifie que r.normal.y vaut 1.0f (comparaison flottante). |
| SweptCollisionTest.MarcheSurLeSolSansBlocageHorizontal (Majeur) Source/Test/Unit/Core/Physics/test_swept_collision.cpp:174 | Balayage : marcher sur un sol sans blocage horizontal | 1. Sol continu ; boîte posée dessus. 2. Balayer horizontalement le long du sol. | Vérifie que r.hit est faux. Vérifie que r.position.x vaut 3.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AssetKeyTest.UneCleNEstJamaisUnCheminDeFichier (Critique) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:40 | Une cle d'asset n'est jamais un chemin de fichier. | 1. Valider des cles bien formees. 2. Valider des chemins et des cles malformees. | Vérifie que core::isValidAssetKey("beast/wolf") est vrai. Vérifie que core::isValidAssetKey("item/corde-en-chanvre-15-m") est vrai. Vérifie que core::isValidAssetKey("weapon/epee-longue") est vrai. Vérifie que core::isValidAssetKey("Assets/Entities/wolf.png") est faux. Vérifie que core::isValidAssetKey("beast/wolf/token") est faux. Vérifie que core::isValidAssetKey("beast/wolf.png") est faux. Vérifie que core::isValidAssetKey("../beast/wolf") est faux. Vérifie que core::isValidAssetKey("wolf") est faux. Vérifie que core::isValidAssetKey("Beast/wolf") est faux. Vérifie que core::isValidAssetKey("beast/") est faux. Vérifie que core::isValidAssetKey("beast/-wolf") est faux. Vérifie que core::isValidAssetKey("beast/wolf-") est faux. Vérifie que core::isValidAssetKey("beast/gris--loup") est faux. Vérifie que core::isValidAssetKey("") est faux. |
| AssetKeyTest.UneCleSeDecomposeEtSeRecompose (Majeur) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:72 | Une cle se decompose et se recompose sans perte. | 1. Decomposer une cle valide. 2. La reformer depuis ses deux morceaux. | Vérifie que decomposee.has_value() est vrai. Vérifie que decomposee->family vaut "beast". Vérifie que decomposee->id vaut "giant-rat". Vérifie que core::defaultAssetKeyFor(decomposee->family, decomposee->id) vaut "beast/giant-rat". Vérifie que core::parseAssetKey("pas une cle").has_value() est faux. Vérifie que core::defaultAssetKeyFor("beast", "Loup").empty() est vrai. |
| AssetKeyTest.LaTableDesFamillesLivreeSeCharge (Critique) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:92 | La table des familles livree se charge. | 1. Charger Assets/Entities/families.json. | Vérifie que familles().ok() est vrai. Vérifie que famille.name.empty() est faux. Vérifie que famille.width est strictement supérieur à 0. Vérifie que famille.height est strictement supérieur à 0. Vérifie que famille.catalogues.empty() est faux. Vérifie que core::isValidAssetKey(famille.name + "/essai") est vrai. Vérifie que familles().find("beast") diffère de nullptr. Vérifie que familles().find("famille-inexistante") vaut nullptr. |
| AssetKeyTest.AucuneCleOrphelineDansLesCataloguesLivres (Critique) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:116 | Aucune cle d'asset orpheline dans les catalogues livres. | 1. Deriver le manifeste des catalogues reels. 2. Relever les erreurs. | Vérifie que erreurs.empty() est vrai. Vérifie que attendues.size() est strictement supérieur à 300U. |
| AssetKeyTest.LeManifesteDeriveNAPasDeDoublon (Critique) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:135 | Le manifeste derive n'a aucun doublon et chaque cle est bien formee. | 1. Deriver le manifeste. 2. Verifier l'unicite et la syntaxe de chaque cle. | Vérifie que attendues.empty() est faux. Vérifie que core::isValidAssetKey(attendue.key) est vrai. Vérifie que familles().find(attendue.family) diffère de nullptr. Vérifie que vues.insert(attendue.key).second est vrai. |
| AssetMarkerTest.UnMarqueurEstDeterministe (Critique) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:163 | Un marqueur est deterministe. | 1. Peindre deux fois le marqueur d'une meme cle. 2. Peindre celui d'une autre cle. | Vérifie que premier.isEmpty() est faux. Vérifie que premier.pixels vaut second.pixels. Vérifie que autre.isEmpty() est faux. Vérifie que premier.pixels diffère de autre.pixels. Vérifie que core::stableAssetHash("beast/wolf") vaut core::stableAssetHash("beast/wolf"). Vérifie que core::stableAssetHash("beast/wolf") diffère de core::stableAssetHash("beast/wolt"). |
| AssetMarkerTest.UnMarqueurRespecteSesDimensionsEtSeVoit (Majeur) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:191 | Un marqueur respecte ses dimensions et se voit comme un marqueur. | 1. Peindre un marqueur aux dimensions d'une famille. 2. Comparer un pixel de la diagonale a un pixel de coin. | Vérifie que marqueur.isEmpty() est faux. Vérifie que marqueur.width vaut 128. Vérifie que marqueur.height vaut 128. Vérifie que marqueur.pixels.size() vaut 128U * 128U. Vérifie que centre diffère de bord. Vérifie que centre.a vaut 255. |
| AssetMarkerTest.UneCleMalformeeNeRecoitPasDeMarqueur (Majeur) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:215 | Une cle malformee ne recoit pas de marqueur. | 1. Demander le marqueur d'une cle malformee, puis de dimensions nulles. | Vérifie que core::assetMarker("Assets/wolf.png", 96, 96).isEmpty() est vrai. Vérifie que core::assetMarker("beast/wolf", 0, 96).isEmpty() est vrai. Vérifie que core::assetMarker("beast/wolf", 96, -1).isEmpty() est vrai. |
| AssetMarkerTest.TouteCleAttendueObtientUnMarqueur (Critique) Source/Test/Unit/Core/Resources/test_asset_keys.cpp:231 | Toute cle attendue obtient un marqueur. | 1. Deriver le manifeste des catalogues reels. 2. Peindre le marqueur de chaque cle aux dimensions de sa famille. | Vérifie que attendues.empty() est faux. Vérifie que famille diffère de nullptr. Vérifie que marqueur.isEmpty() est faux. Vérifie que marqueur.width vaut famille->width. Vérifie que peints vaut static_cast<int>(attendues.size()). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| BestiaryTest.LesQuatreVingtQuatorzeProfilsChargent (Critique) Source/Test/Unit/Core/Rpg/test_bestiary.cpp:96 | Les 94 creatures du bestiaire de base se chargent toutes. | 1. Charger Source/Elements/Rpg/creatures. 2. Compter les creatures chargees et les erreurs rapportees. | Vérifie que catalogue.creatures.size() vaut BETES_DU_SRD. Vérifie que identifiants.insert(creature.id).second est vrai. Vérifie que creature.name.empty() est faux. Vérifie que creature.source vaut "srd". |
| BestiaryTest.DixProfilsConcordentAvecLeLivre (Critique) Source/Test/Unit/Core/Rpg/test_bestiary.cpp:123 | Dix blocs de statistiques du bestiaire concordent avec le livre. | 1. Pour douze creatures, comparer classe d'armure, points de vie, vitesse de marche, facteur de puissance et degats de l'attaque principale aux valeurs lues sur Animaux.pdf. | Vérifie que creature diffère de nullptr. Vérifie que creature->armorClass vaut attendu.armorClass. Vérifie que creature->hitPoints vaut attendu.hitPoints. Vérifie que creature->speed.walk vaut attendu.walk (comparaison flottante). Vérifie que creature->challengeRating vaut attendu.challengeRating (comparaison flottante). Vérifie que action diffère de nullptr. Vérifie que action->damage.has_value() est vrai. Vérifie que des.has_value() est vrai. Vérifie que *action->damage vaut *des. Vérifie que action->damageType.has_value() est vrai. Vérifie que *action->damageType vaut attendu.damageType. |
| BestiaryTest.ChaqueProfilEstComplet (Critique) Source/Test/Unit/Core/Rpg/test_bestiary.cpp:163 | Aucun profil du bestiaire n'a de caracteristique ni de vitesse manquante. | 1. Pour chaque creature, verifier que les six caracteristiques sont dans [1, 30]. 2. Verifier que la vitesse de marche est renseignee, meme nulle. | Vérifie que valeur est supérieur ou égal à 1. Vérifie que valeur est inférieur ou égal à 30. Vérifie que creature.speed.walk est supérieur ou égal à 0.0F. Vérifie que creature.hitPoints est strictement supérieur à 0. Vérifie que creature.armorClass est strictement supérieur à 0. |
| BestiaryTest.UneVitesseNulleSignifieUnAutreDeplacement (Majeur) Source/Test/Unit/Core/Rpg/test_bestiary.cpp:187 | Une creature sans vitesse de marche possede un autre mode de deplacement. | 1. Relever les creatures dont walk vaut 0. | Vérifie que autrement est vrai. Vérifie que immobiles est strictement supérieur à 0U. |
| BestiaryTest.LesMecanismesExigesSontAnnonces (Majeur) Source/Test/Unit/Core/Rpg/test_bestiary.cpp:215 | Le bestiaire annonce les mecanismes que les creatures exigent du moteur. | 1. Collecter les mecanismesRequis de toutes les creatures chargees. | Vérifie que std::ranges::find(mecanismes, "resistance-conditionnelle") diffère de mecanismes.end(). Vérifie que std::ranges::find(mecanismes, "langue-comprise-non-parlee") diffère de mecanismes.end(). |
| BestiaryTest.UnDossierAbsentEstSignale (Majeur) Source/Test/Unit/Core/Rpg/test_bestiary.cpp:236 | Charger un dossier de creatures inexistant produit une erreur nommee. | 1. Charger un chemin qui n'existe pas. | Vérifie que vide.creatures.empty() est vrai. Vérifie que vide.errors.size() vaut 1U. Vérifie que vide.errors.front().find("dossier-inexistant") diffère de std::string::npos. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CharacterOptionsTest.LesTroisCataloguesChargent (Critique) Source/Test/Unit/Core/Rpg/test_character_options.cpp:89 | Les especes, historiques et classes livres se chargent tous. | 1. Charger species/, backgrounds/ et classes/. | Vérifie que lues.species.empty() est faux. Vérifie que lues.backgrounds.empty() est faux. Vérifie que lues.classes.size() vaut CLASSES.size(). Vérifie que identifiants.insert(espece.id).second est vrai. Vérifie que espece.name.empty() est faux. Vérifie que espece.speed est strictement supérieur à 0.0F. |
| CharacterOptionsTest.LesEspecesConcordentAvecLesLivres (Critique) Source/Test/Unit/Core/Rpg/test_character_options.cpp:115 | Les especes livrees portent les valeurs des livres dont elles sont tirees. | 1. Pour sept especes des trois livres, comparer provenance, taille, vitesse et augmentation de caracteristique aux valeurs lues sur les documents. | Vérifie que espece diffère de nullptr. Vérifie que espece->source vaut attendue.source. Vérifie que espece->size vaut attendue.size. Vérifie que espece->speed vaut attendue.speed (comparaison flottante). Vérifie que espece->increase(attendue.augmentee) vaut attendue.augmentation. |
| CharacterOptionsTest.LAugmentationSAppliqueEtResteBornee (Majeur) Source/Test/Unit/Core/Rpg/test_character_options.cpp:138 | L'augmentation d'une espece s'applique et reste bornee a 20. | 1. Appliquer l'augmentation du nain a une Constitution de 14, puis de 19. | Vérifie que nain diffère de nullptr. Vérifie que regles.ok() est vrai. Vérifie que core::abilityScoreWith(*nain, core::Ability::Constitution, 14, plafond) vaut 16. Vérifie que core::abilityScoreWith(*nain, core::Ability::Constitution, plafond - 1, plafond) vaut plafond. Vérifie que core::abilityScoreWith(*nain, core::Ability::Charisma, 14, plafond) vaut 14. |
| CharacterOptionsTest.LesClassesConcordentAvecLeLivre (Critique) Source/Test/Unit/Core/Rpg/test_character_options.cpp:164 | Les classes simplifiees portent le de de vie et les sauvegardes du livre. | 1. Pour les quatre classes, comparer de de vie, caracteristique principale et jets de sauvegarde a la table << New Simplified Classes >> de la page 57. | Vérifie que classe diffère de nullptr. Vérifie que classe->hitDie vaut attendue.hitDie. Vérifie que classe->primaryAbility.empty() est faux. Vérifie que classe->primaryAbility.front() vaut attendue.primaire. Vérifie que classe->savingThrowProficiencies.size() vaut 2U. Vérifie que classe->savingThrowProficiencies[0] vaut attendue.sauvegarde1. Vérifie que classe->savingThrowProficiencies[1] vaut attendue.sauvegarde2. |
| CharacterOptionsTest.LaProgressionVientDeLaDonnee (Critique) Source/Test/Unit/Core/Rpg/test_character_options.cpp:189 | Le bonus de maitrise des niveaux 1 a 5 est lu dans la table livree. | 1. Lire le bonus de maitrise des niveaux 1 a 5 de chaque classe dans sa table. 2. Le comparer aux valeurs de la table du livre. | Vérifie que classe diffère de nullptr. Vérifie que classe->progression.size() vaut 20U. Vérifie que ligne diffère de nullptr. Vérifie que ligne->proficiencyBonus vaut BONUS_ATTENDUS[static_cast<std::size_t>(niveau - 1)]. Vérifie que ligne->features.empty() est faux. Vérifie que classe->progression[i].level vaut static_cast<int>(i) + 1. |
| CharacterOptionsTest.LesMecanismesExigesSontAnnonces (Majeur) Source/Test/Unit/Core/Rpg/test_character_options.cpp:225 | Une espece qui exige un mecanisme absent le declare au chargement. | 1. Collecter les mecanismesRequis des especes chargees. | Vérifie que std::ranges::find(mecanismes, "augmentation-de-caracteristique-au-choix") diffère de mecanismes.end(). |
| CharacterOptionsTest.LesClassesProvisoiresNeSontReferenceesParRien (Critique) Source/Test/Unit/Core/Rpg/test_character_options.cpp:243 | Les classes provisoires portent leur marque et ne sont referencees par aucune donnee definitive. | 1. Verifier que les quatre classes portent status.provisoire et un critere de retrait. 2. Balayer tous les fichiers de Source/Elements/Rpg/ et chercher leur identifiant. | Vérifie que provisoires.size() vaut CLASSES.size(). Vérifie que classe.status.provisional est vrai. Vérifie que classe.status.removalCriterion.empty() est faux. Vérifie que contenu.find('"' + identifiant + '"') vaut std::string::npos. |
| CharacterOptionsTest.UnDossierAbsentEstSignale (Majeur) Source/Test/Unit/Core/Rpg/test_character_options.cpp:299 | Charger un dossier d'options inexistant produit une erreur nommee. | 1. Charger trois chemins qui n'existent pas. | Vérifie que vides.species.empty() est vrai. Vérifie que vides.backgrounds.empty() est vrai. Vérifie que vides.classes.empty() est vrai. Vérifie que vides.errors.size() vaut 3U. |
| CharacterOptionsTest.LesHistoriquesCitentDesCompetencesQuiExistent (Majeur) Source/Test/Unit/Core/Rpg/test_character_options.cpp:317 | Les competences citees par un historique existent au catalogue. | 1. Pour chaque historique, verifier que le fichier de chaque competence citee existe dans Source/Elements/Rpg/skills/. | Vérifie que historique.skillProficiencies.empty() est faux. Vérifie que std::filesystem::exists(chemin) est vrai. Vérifie que historique.languageCount est supérieur ou égal à 0. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CharacterSheetTest.LesTablesDeReglesSeChargent (Critique) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:67 | La table d'experience et les constantes de creation se chargent depuis la donnee. | 1. Charger rules/experience.json et rules/character-creation.json. | Vérifie que lus.experience.levels.size() vaut 20U. Vérifie que lus.experience.maximumLevel() vaut 20. Vérifie que lus.experience.levels[i].experience est strictement supérieur à lus.experience.levels[i - 1].experience. Vérifie que lus.experience.levels[i].proficiencyBonus est supérieur ou égal à lus.experience.levels[i - 1].proficiencyBonus. Vérifie que lus.rules.ok() est vrai. Vérifie que lus.skills.skills.empty() est faux. |
| CharacterSheetTest.QuatreFichesIndependantes (Critique) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:98 | Quatre fiches de personnage coexistent, chacune avec ses propres valeurs. | 1. Construire quatre fiches d'especes et de classes differentes. 2. Modifier les points de vie de la premiere et faire monter la deuxieme de niveau. | Vérifie que groupe.size() vaut 4U. Vérifie que personnage.speciesId.empty() est faux. Vérifie que personnage.classId.empty() est faux. Vérifie que personnage.backgroundId.empty() est faux. Vérifie que personnage.maximumHitPoints est strictement supérieur à 0. Vérifie que personnage.speedMeters est strictement supérieur à 0.0F. Vérifie que groupe[0].maximumHitPoints vaut pvAvant. Vérifie que groupe[0].level vaut niveauAvant. Vérifie que groupe[1].level vaut 3. Vérifie que groupe[2].level vaut 1. Vérifie que groupe[3].level vaut 1. Vérifie que groupe[0].currentHitPoints diffère de groupe[0].maximumHitPoints. Vérifie que groupe[2].currentHitPoints vaut groupe[2].maximumHitPoints. |
| CharacterSheetTest.TroisClassesDonnentLesBonsModificateurs (Critique) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:143 | Trois classes chargees depuis JSON produisent les bons points de vie et jets de sauvegarde. | 1. Construire une fiche pour le brawler (d12), le mage (d6) et le priest (d8). 2. Comparer points de vie et modificateurs de sauvegarde au calcul du livre. | Vérifie que classe diffère de nullptr. Vérifie que personnage.modifier(core::Ability::Constitution) vaut modificateurAttendu. Vérifie que personnage.maximumHitPoints vaut classe->hitDie + modificateurAttendu. Vérifie que personnage.currentHitPoints vaut personnage.maximumHitPoints. Vérifie que maitrise vaut lus.experience.proficiencyBonusAt(1). Vérifie que core::savingThrowModifier(personnage, lus.experience, caracteristique) vaut personnage.modifier(caracteristique) + maitrise. Vérifie que core::savingThrowModifier(personnage, lus.experience, caracteristique) vaut personnage.modifier(caracteristique). |
| CharacterSheetTest.LaMonteeDeNiveauEstTesteeAuxBornes (Critique) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:194 | La montee de niveau franchit le seuil exact, le depassement et plusieurs niveaux d'un coup. | 1. Donner exactement le seuil du niveau 2, puis un point de moins, puis le seuil du niveau 5 d'un coup. | Vérifie que classe diffère de nullptr. Vérifie que seuil2 est strictement supérieur à 0. Vérifie que seuil5 est strictement supérieur à seuil2. Vérifie que montee.gainedLevel() est vrai. Vérifie que montee.previousLevel vaut 1. Vérifie que montee.newLevel vaut 2. Vérifie que montee.hitPointsGained est strictement supérieur à 0. Vérifie que sansMontee.gainedLevel() est faux. Vérifie que presque.level vaut 1. Vérifie que sansMontee.hitPointsGained vaut 0. Vérifie que saut.newLevel vaut 5. Vérifie que bond.level vaut 5. Vérifie que saut.newProficiencyBonus est strictement supérieur à saut.previousProficiencyBonus. Vérifie que bond.maximumHitPoints vaut core::maximumHitPointsFor(classe->hitDie, 5, bond.modifier(core::Ability::Constitution)). Vérifie que rien.gainedLevel() est faux. Vérifie que stable.experiencePoints vaut seuil5. |
| CharacterSheetTest.LaMonteeDeNiveauEstReproductible (Majeur) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:253 | La montee de niveau est reproductible : le chemin ne change pas le resultat. | 1. Donner le seuil du niveau 5 en une fois a une fiche, en deux fois a une autre. | Vérifie que classe diffère de nullptr. Vérifie que enUneFois.level vaut enDeuxFois.level. Vérifie que enUneFois.maximumHitPoints vaut enDeuxFois.maximumHitPoints. Vérifie que enUneFois.experiencePoints vaut enDeuxFois.experiencePoints. |
| CharacterSheetTest.LeModificateurDeCompetenceVientDuCatalogue (Majeur) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:280 | Un jet de competence emploie la caracteristique que le catalogue lui donne. | 1. Calculer le modificateur d'une competence maitrisee et d'une autre non maitrisee. 2. Demander une competence inconnue du catalogue. | Vérifie que moine.skillProficiencies.empty() est faux. Vérifie que competence diffère de nullptr. Vérifie que calcul.found est vrai. Vérifie que calcul.proficient est vrai. Vérifie que calcul.value vaut moine.modifier(competence->ability) + core::proficiencyBonus(moine, lus.experience). Vérifie que inconnue.found est faux. |
| CharacterSheetTest.LaVitesseSeLitEnCases (Majeur) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:315 | La vitesse d'un personnage se lit en cases via l'echelle unique du projet. | 1. Convertir la vitesse d'un nain (7,50 m) et d'un humain (9 m) en cases. | Vérifie que nain.speedInTiles() vaut core::tilesFromMeters(nain.speedMeters) (comparaison flottante). Vérifie que humain.speedInTiles() vaut core::tilesFromMeters(humain.speedMeters) (comparaison flottante). Vérifie que nain.speedInTiles() vaut 5.0F (comparaison flottante). Vérifie que humain.speedInTiles() vaut 6.0F (comparaison flottante). |
| CharacterSheetTest.LeComposantDistingueLAbsenceDeFiche (Majeur) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:334 | Une entite sans fiche ne se confond pas avec une entite liee a la fiche zero. | 1. Construire un RpgActor par defaut, puis un lie a l'indice 0. | Vérifie que sansFiche.hasSheet() est faux. Vérifie que premiere.hasSheet() est vrai. Vérifie que premiere.sheetIndex vaut 0U. |
| CharacterSheetTest.AucuneValeurDeRegleNEstEcriteDansLeCpp (Critique) Source/Test/Unit/Core/Rpg/test_character_sheet.cpp:354 | La classe d'armure sans armure et le plafond de caracteristique viennent de la donnee. | 1. Lire les deux constantes dans rules/character-creation.json. 2. Verifier que la CA d'une fiche sans armure vaut la constante lue plus le modificateur de Dexterite. | Vérifie que lus.rules.ok() est vrai. Vérifie que personnage.armorClass vaut lus.rules.unarmoredArmorClass + personnage.modifier(core::Ability::Dexterity). Vérifie que personnage.ability(caracteristique) est inférieur ou égal à lus.rules.maximumAbilityScore. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CheckTest.AvantageEtDesavantageGardentLeBonDe (Critique) Source/Test/Unit/Core/Rpg/test_check.cpp:47 | L'avantage garde le meilleur de deux des, le desavantage le pire. | 1. Lancer mille jets avec avantage, puis mille avec desavantage. | Vérifie que avantage.dice.size() vaut 2U. Vérifie que avantage.keptDie vaut std::max(avantage.dice[0], avantage.dice[1]). Vérifie que desavantage.dice.size() vaut 2U. Vérifie que desavantage.keptDie vaut std::min(desavantage.dice[0], desavantage.dice[1]). |
| CheckTest.AvantageEtDesavantageSAnnulent (Critique) Source/Test/Unit/Core/Rpg/test_check.cpp:72 | Avantage et desavantage s'annulent entierement, et ne se cumulent jamais. | 1. Determiner la posture pour 0/0, 1/0, 0/1, 1/1 et 2/1 sources. | Vérifie que core::rollStance(0, 0) vaut core::RollStance::Normal. Vérifie que core::rollStance(1, 0) vaut core::RollStance::Advantage. Vérifie que core::rollStance(0, 1) vaut core::RollStance::Disadvantage. Vérifie que core::rollStance(1, 1) vaut core::RollStance::Normal. Vérifie que core::rollStance(2, 1) vaut core::RollStance::Normal. Vérifie que core::rollStance(1, 3) vaut core::RollStance::Normal. Vérifie que core::rollStance(3, 0) vaut core::RollStance::Advantage. Vérifie que resultat.dice.size() vaut 1U. |
| CheckTest.NaturelsDistinguesDuTotal (Critique) Source/Test/Unit/Core/Rpg/test_check.cpp:99 | Un 1 ou 20 naturel se distingue d'un total de 1 ou 20. | 1. Lancer jusqu'a obtenir un 20 naturel et un 1 naturel. 2. Construire un resultat de total 20 obtenu avec un de de 8. | Vérifie que resultat.isNaturalTwenty() est vrai. Vérifie que resultat.isNaturalOne() est faux. Vérifie que resultat.isNaturalOne() est vrai. Vérifie que resultat.isNaturalTwenty() est faux. Vérifie que vingtVu est vrai. Vérifie que unVu est vrai. Vérifie que total20.isNaturalTwenty() est faux. |
| CheckTest.ModificateursEtRestitution (Critique) Source/Test/Unit/Core/Rpg/test_check.cpp:139 | Les modificateurs d'un jet s'appliquent et conservent leur origine. | 1. Lancer un jet avec +3 de Dexterite et +2 de maitrise. 2. Lire la restitution. | Vérifie que cible vaut 15. Vérifie que resultat.total vaut resultat.keptDie + 5. Vérifie que resultat.target vaut cible. Vérifie que resultat.succeeded() vaut resultat.total >= cible. Vérifie que restitution.find("Dexterite") diffère de std::string::npos. Vérifie que restitution.find("maitrise") diffère de std::string::npos. Vérifie que restitution.find(std::to_string(cible)) diffère de std::string::npos. Vérifie que restitution.find(std::to_string(resultat.total)) diffère de std::string::npos. |
| CheckTest.EchelleDeDifficulteEnDonnee (Majeur) Source/Test/Unit/Core/Rpg/test_check.cpp:173 | L'echelle de difficulte est une donnee complete et croissante. | 1. Lire les paliers de difficulty.json. | Vérifie que document.ok() est vrai. Vérifie que paliers.size() vaut 6U. Vérifie que dc est strictement supérieur à precedent. Vérifie que seuil("tres-facile") vaut 5. Vérifie que seuil("quasi-impossible") vaut 30. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| DiceTest.AnalyseDesTroisFormes (Critique) Source/Test/Unit/Core/Rpg/test_dice.cpp:30 | La notation de des est analysee sous ses trois formes. | 1. Analyser << 2d6+3 >>, << 1d8 >>, << 4 >> et << 1d4-1 >>. | Vérifie que avecModificateur.has_value() est vrai. Vérifie que avecModificateur->count vaut 2. Vérifie que avecModificateur->faces vaut 6. Vérifie que avecModificateur->modifier vaut 3. Vérifie que simple.has_value() est vrai. Vérifie que *simple vaut (core::Dice{1, 8, 0}). Vérifie que fixe.has_value() est vrai. Vérifie que *fixe vaut (core::Dice{0, 0, 4}). Vérifie que negatif.has_value() est vrai. Vérifie que negatif->modifier vaut -1. Vérifie que core::formatDice(*avecModificateur) vaut "2d6+3". Vérifie que core::formatDice(*negatif) vaut "1d4-1". Vérifie que core::formatDice(*fixe) vaut "4". |
| DiceTest.UneNotationMalFormeeEstRefusee (Critique) Source/Test/Unit/Core/Rpg/test_dice.cpp:63 | Une notation de des mal formee est refusee au lieu d'etre devinee. | 1. Analyser << ld8 >> (faute d'OCR), une chaine vide, << 1d >>, << d6 >> et << 1d6+2x >>. | Vérifie que core::parseDice("ld8").has_value() est faux. Vérifie que core::parseDice("").has_value() est faux. Vérifie que core::parseDice("1d").has_value() est faux. Vérifie que core::parseDice("d6").has_value() est faux. Vérifie que core::parseDice("1d6+2x").has_value() est faux. Vérifie que core::parseDice("0d6").has_value() est faux. Vérifie que core::parseDice("1d0").has_value() est faux. |
| DiceTest.UnLancerResteDansSesBornes (Critique) Source/Test/Unit/Core/Rpg/test_dice.cpp:85 | Un lancer de des reste dans ses bornes et conserve le detail de chaque de. | 1. Lancer 2d6+3 mille fois a graine fixe. | Vérifie que roll.faces.size() vaut 2U. Vérifie que face est supérieur ou égal à 1. Vérifie que face est inférieur ou égal à 6. Vérifie que roll.total est supérieur ou égal à dice.minimum(). Vérifie que roll.total est inférieur ou égal à dice.maximum(). |
| DiceTest.RejouabiliteStricte (Critique) Source/Test/Unit/Core/Rpg/test_dice.cpp:109 | Deux generateurs de meme graine produisent exactement la meme suite de des. | 1. Lancer cent fois 3d8 avec deux generateurs de meme graine. 2. Recommencer avec une graine differente. | Vérifie que suiteA vaut suiteB. Vérifie que suiteA diffère de suiteAutre. |
| DiceTest.DistributionUniformeSurCentMilleTirages (Majeur) Source/Test/Unit/Core/Rpg/test_dice.cpp:139 | La distribution d'un d20 est uniforme sur cent mille tirages a graine fixe. | 1. Tirer cent mille d20 a graine fixe et compter chaque face. | Vérifie que effectifs.size() vaut static_cast<std::size_t>(FACES). Vérifie que face est supérieur ou égal à 1. Vérifie que face est inférieur ou égal à FACES. Vérifie que static_cast<double>(compte) vaut attendu, à attendu * 0.10 près. |
| DiceTest.BornesDuTirageEntier (Majeur) Source/Test/Unit/Core/Rpg/test_dice.cpp:171 | Le tirage entier respecte ses bornes, y compris quand elles sont egales. | 1. Tirer dix mille fois dans [3, 3], puis dans [-5, 5]. | Vérifie que random.nextInt(3, 3) vaut 3. Vérifie que valeur est supérieur ou égal à -5. Vérifie que valeur est inférieur ou égal à 5. Vérifie que minAtteint est vrai. Vérifie que maxAtteint est vrai. |
| DiceTest.ModificateurArrondiVersLeBas (Critique) Source/Test/Unit/Core/Rpg/test_dice.cpp:200 | Le modificateur de caracteristique s'arrondit vers le bas, y compris en negatif. | 1. Calculer le modificateur pour 1, 7, 8, 9, 10, 11, 15 et 20. | Vérifie que core::abilityModifier(1) vaut -5. Vérifie que core::abilityModifier(3) vaut -4. Vérifie que core::abilityModifier(7) vaut -2. Vérifie que core::abilityModifier(8) vaut -1. Vérifie que core::abilityModifier(9) vaut -1. Vérifie que core::abilityModifier(10) vaut 0. Vérifie que core::abilityModifier(11) vaut 0. Vérifie que core::abilityModifier(15) vaut 2. Vérifie que core::abilityModifier(20) vaut 5. Vérifie que core::abilityModifier(30) vaut 10. |
| DiceTest.AllerRetourDesCaracteristiques (Majeur) Source/Test/Unit/Core/Rpg/test_dice.cpp:225 | Les six caracteristiques font l'aller-retour par leur nom sans perte. | 1. Convertir chaque caracteristique en nom, puis le nom en caracteristique. 2. Analyser un nom francais. | Vérifie que core::allAbilities().size() vaut 6U. Vérifie que nom.empty() est faux. Vérifie que relu.has_value() est vrai. Vérifie que *relu vaut ability. Vérifie que core::parseAbility("force").has_value() est faux. |
| DiceTest.EchelleDuMonde (Majeur) Source/Test/Unit/Core/Rpg/test_dice.cpp:248 | L'echelle du monde convertit metres et cases dans les deux sens. | 1. Convertir 9 metres en cases, puis 6 cases en metres. | Vérifie que core::METERS_PER_TILE vaut 1.5f (comparaison flottante). Vérifie que core::tilesFromMeters(9.0f) vaut 6.0f (comparaison flottante). Vérifie que core::metersFromTiles(6.0f) vaut 9.0f (comparaison flottante). Vérifie que core::tilesFromMeters(core::metersFromTiles(4.0f)) vaut 4.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EquipmentTest.LesDeuxCataloguesSeChargent (Critique) Source/Test/Unit/Core/Rpg/test_equipment.cpp:87 | Les armes et les armures livrees se chargent toutes. | 1. Charger weapons/ et armors/. | Vérifie que lus.weapons.size() vaut 37U. Vérifie que lus.armors.size() vaut ARMURES.size(). Vérifie que regles().ok() est vrai. |
| EquipmentTest.LesTreizeArmuresPortentLesValeursDuLivre (Critique) Source/Test/Unit/Core/Rpg/test_equipment.cpp:107 | Chaque armure du catalogue porte la CA, le poids et le prix du livre. | 1. Pour les 13 rangees de la table p. 50, comparer categorie, CA de base, plafond de Dexterite, Force exigee, discretion, poids et prix aux valeurs recopiees a la main. | Vérifie que armure diffère de nullptr. Vérifie que core::armorCategoryName(armure->category) vaut attendue.categorie. Vérifie que armure->baseArmorClass vaut attendue.base. Vérifie que armure->weightGrams vaut attendue.poidsGrammes. Vérifie que armure->price vaut attendue.prixCuivre. Vérifie que armure->stealthDisadvantage vaut attendue.discretion. Vérifie que armure->dexterityBonus est faux. Vérifie que armure->dexterityBonus est vrai. Vérifie que armure->dexterityBonusMax.has_value() est faux. Vérifie que armure->dexterityBonusMax.has_value() est vrai. Vérifie que *armure->dexterityBonusMax vaut attendue.dexMax. Vérifie que armure->strengthRequired.has_value() est faux. Vérifie que armure->strengthRequired.has_value() est vrai. Vérifie que *armure->strengthRequired vaut attendue.forceExigee. |
| EquipmentTest.LaCaCalculeeEgaleLaColonneDuLivre (Critique) Source/Test/Unit/Core/Rpg/test_equipment.cpp:149 | La classe d'armure calculee pour chaque armure egale la colonne CA du livre. | 1. Avec une Dexterite de 18 (modificateur +4), calculer la CA de chaque armure. 2. La comparer a la formule de la colonne CA, appliquee a la main. | Vérifie que dexterite vaut 4. Vérifie que armure diffère de nullptr. Vérifie que core::armorClassFor(fiche, regles(), armure, nullptr) vaut attendu. |
| EquipmentTest.LeBouclierAjouteIlNeRemplacePas (Critique) Source/Test/Unit/Core/Rpg/test_equipment.cpp:188 | Un bouclier ajoute son bonus a la classe d'armure, seul ou avec une armure. | 1. Calculer la CA d'un personnage en bouclier seul, puis en harnois et bouclier. | Vérifie que bouclier diffère de nullptr. Vérifie que harnois diffère de nullptr. Vérifie que core::armorClassFor(fiche, regles(), bouclier, nullptr) vaut regles().unarmoredArmorClass + fiche.modifier(core::Ability::Dexterity). Vérifie que core::armorClassFor(fiche, regles(), nullptr, bouclier) vaut regles().unarmoredArmorClass + fiche.modifier(core::Ability::Dexterity) + bouclier->baseArmorClass. Vérifie que core::armorClassFor(fiche, regles(), harnois, bouclier) vaut harnois->baseArmorClass + bouclier->baseArmorClass. |
| EquipmentTest.LePoidsDUnInventaireDeDepartCorrespondAuCalculManuel (Critique) Source/Test/Unit/Core/Rpg/test_equipment.cpp:216 | Le poids total d'un inventaire de depart egale la somme calculee a la main. | 1. Composer l'inventaire d'un guerrier : cotte de mailles, epee longue, bouclier et deux javelines. 2. Comparer le total au calcul fait a la main depuis les poids du livre. | Vérifie que cotte diffère de nullptr. Vérifie que bouclier diffère de nullptr. Vérifie que epee diffère de nullptr. Vérifie que javeline diffère de nullptr. Vérifie que core::totalWeightGrams(sac) vaut TOTAL_ATTENDU_GRAMMES. Vérifie que core::totalWeightGrams(avecVides) vaut cotte->weightGrams. Vérifie que core::totalWeightGrams({}) vaut 0. |
| EquipmentTest.LeFiletNInfligeAucunDegat (Majeur) Source/Test/Unit/Core/Rpg/test_equipment.cpp:255 | Une arme sans degats est chargee sans que des lui soient inventes. | 1. Charger le filet et une arme ordinaire. | Vérifie que filet diffère de nullptr. Vérifie que filet->damage.has_value() est faux. Vérifie que filet->damageType.has_value() est faux. Vérifie que filet->text.empty() est faux. Vérifie que dague diffère de nullptr. Vérifie que dague->damage.has_value() est vrai. Vérifie que dague->damage->count vaut 1. Vérifie que dague->damage->faces vaut 4. Vérifie que dague->damageType.has_value() est vrai. Vérifie que *dague->damageType vaut core::DamageType::Piercing. |
| EquipmentTest.LesArmesPortentLeurCategorieEtLeurPortee (Critique) Source/Test/Unit/Core/Rpg/test_equipment.cpp:282 | Chaque arme porte la categorie et la portee de son intertitre. | 1. Verifier la categorie et la portee de quatre armes, une par groupe du livre. | Vérifie que arme diffère de nullptr. Vérifie que arme->category vaut cas.categorie. Vérifie que arme->ranged vaut cas.distance. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| InventoryTest.LaClasseDArmureNeDerivePasAvecLOrdre (Critique) Source/Test/Unit/Core/Rpg/test_inventory.cpp:119 | La classe d'armure ne derive pas avec l'ordre des equipements. | 1. Relever la CA sans equipement. 2. Jouer six ordres d'equipement et de retrait d'une armure et d'un bouclier. 3. Relever la CA apres chaque sequence complete. | Vérifie que depart vaut 12. Vérifie que core::derivedStatsFor(personnage, sac, catalogues, regles(), charge()).armorClass vaut depart. |
| InventoryTest.ChaqueCategorieDArmureAppliqueSaRegle (Critique) Source/Test/Unit/Core/Rpg/test_inventory.cpp:185 | Chaque categorie d'armure applique sa propre regle de Dexterite. | 1. Equiper une armure legere, puis une intermediaire, avec une Dexterite de 18. 2. Ajouter un bouclier. | Vérifie que core::derivedStatsFor(personnage, sac, catalogues, regles(), charge()).armorClass vaut 15. Vérifie que core::derivedStatsFor(personnage, sac, catalogues, regles(), charge()).armorClass vaut 17. Vérifie que core::derivedStatsFor(personnage, sac, catalogues, regles(), charge()).armorClass vaut 19. |
| InventoryTest.UnEmplacementRendCeQuIlPortait (Majeur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:214 | Un emplacement ne porte jamais deux pieces, et ce qui en sort est rendu. | 1. Equiper une armure, puis une autre au meme emplacement. | Vérifie que core::equip(sac, EquipmentSlot::Torso, "cuir") vaut "". Vérifie que core::equip(sac, EquipmentSlot::Torso, "demi-plate") vaut "cuir". Vérifie que sac.at(EquipmentSlot::Torso) vaut "demi-plate". Vérifie que core::unequip(sac, EquipmentSlot::Torso) vaut "demi-plate". Vérifie que sac.isEquipped(EquipmentSlot::Torso) est faux. |
| InventoryTest.LeSacEmpileEtSeVide (Majeur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:232 | Le sac empile, et une ligne videe disparait. | 1. Ajouter deux fois le meme objet. 2. En retirer plus qu'il n'y en a. | Vérifie que sac.backpack.size() vaut 1U. Vérifie que sac.backpack.front().quantity vaut 5. Vérifie que core::removeFromBackpack(sac, "torche", 10) vaut 5. Vérifie que sac.backpack.empty() est vrai. Vérifie que core::removeFromBackpack(sac, "torche", 1) vaut 0. |
| InventoryTest.LePoidsPorteCompteLeSacEtLEquipement (Majeur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:254 | Le poids porte compte le sac et l'equipement. | 1. Equiper une armure et une arme. 2. Ajouter des objets au sac. | Vérifie que core::carriedWeightGrams(sac, catalogues) vaut 5000 + 1500 + 2000 + 5000. |
| InventoryTest.UnIdentifiantInconnuEstSignale (Majeur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:278 | Un identifiant inconnu des catalogues est signale. | 1. Mettre au sac un identifiant absent des catalogues. | Vérifie que inconnus vaut (std::vector<std::string>{"bidule-inexistant", "heaume-fantome"}). Vérifie que core::carriedWeightGrams(sac, catalogues) vaut 0. |
| InventoryTest.LaChargeFranchitSesSeuils (Critique) Source/Test/Unit/Core/Rpg/test_inventory.cpp:301 | La charge franchit ses trois seuils et definit le depassement. | 1. Charger un personnage de Force 10 en dessous du premier seuil, puis entre les deux, puis au-dela du second, puis au-dela de la capacite. | Vérifie que leger.encumbrance vaut core::EncumbranceLevel::Unencumbered. Vérifie que leger.speedMeters vaut 9.0F (comparaison flottante). Vérifie que leger.carryingCapacityGrams vaut 75000. Vérifie que encombre.encumbrance vaut core::EncumbranceLevel::Encumbered. Vérifie que encombre.speedMeters vaut 6.0F (comparaison flottante). Vérifie que lourd.encumbrance vaut core::EncumbranceLevel::HeavilyEncumbered. Vérifie que lourd.speedMeters vaut 3.0F (comparaison flottante). Vérifie que trop.encumbrance vaut core::EncumbranceLevel::OverCapacity. Vérifie que trop.speedMeters vaut 0.0F (comparaison flottante). |
| InventoryTest.SansRegleDeChargeAucunEncombrementNEstAffirme (Majeur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:342 | Sans regle de charge, aucun encombrement n'est affirme. | 1. Deriver les statistiques avec des bornes de charge non chargees. | Vérifie que derivees.encumbrance vaut core::EncumbranceLevel::Unencumbered. Vérifie que derivees.carryingCapacityGrams vaut 0. Vérifie que derivees.speedMeters vaut 9.0F (comparaison flottante). |
| InventoryTest.LaCaracteristiqueDAttaqueSuitLArme (Critique) Source/Test/Unit/Core/Rpg/test_inventory.cpp:366 | La caracteristique d'attaque suit l'arme portee. | 1. Equiper une arme de melee, puis une arme a distance, puis une arme de finesse, avec une Dexterite superieure a la Force. | Vérifie que derivees.attackAbility vaut Ability::Strength. Vérifie que derivees.damage.has_value() est vrai. Vérifie que derivees.damage->faces vaut 8. Vérifie que derivees.attackAbility vaut Ability::Dexterity. Vérifie que derivees.attackAbility vaut Ability::Dexterity. Vérifie que derivees.damage.has_value() est faux. |
| InventoryTest.LaCategorieDecideAvantLEmplacement (Majeur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:402 | C'est la categorie qui dit comment une piece compte, pas l'emplacement. | 1. Ranger un bouclier a l'emplacement du torse. | Vérifie que core::derivedStatsFor(personnage, sac, catalogues, regles(), charge()).armorClass vaut 14. |
| InventoryTest.LesEmplacementsSeNommentEtSeRelisent (Mineur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:422 | Les seize emplacements se nomment et se relisent. | 1. Convertir chaque emplacement en nom, puis le nom en emplacement. | Vérifie que nom.empty() est faux. Vérifie que core::parseEquipmentSlot(nom) vaut emplacement. Vérifie que core::parseEquipmentSlot("chapeau-de-paille").has_value() est faux. |
| InventoryTest.LeCatalogueLivreSeCharge (Majeur) Source/Test/Unit/Core/Rpg/test_inventory.cpp:441 | Le catalogue d'objets livre se charge. | 1. Charger Source/Elements/Rpg/items. | Vérifie que catalogue.errors.empty() est vrai. Vérifie que catalogue.items.size() est strictement supérieur à 100U. Vérifie que objet.id.empty() est faux. Vérifie que objet.name.empty() est faux. Vérifie que objet.weightGrams est supérieur ou égal à 0. |
| InventoryTest.LesBornesDeChargeLivreesSontCellesDuLivre (Critique) Source/Test/Unit/Core/Rpg/test_inventory.cpp:463 | Les bornes de charge livrees portent les valeurs du livre. | 1. Charger Source/Elements/Rpg/rules/encumbrance.json. | Vérifie que regles.isLoaded() est vrai. Vérifie que regles.carryingCapacityGramsPerStrength vaut 7500. Vérifie que regles.encumberedGramsPerStrength vaut 2500. Vérifie que regles.heavilyEncumberedGramsPerStrength vaut 5000. Vérifie que regles.encumberedSpeedPenaltyMeters vaut 3.0F (comparaison flottante). Vérifie que regles.heavilyEncumberedSpeedPenaltyMeters vaut 6.0F (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MulticlassingTest.ExempleTravailleDuManuelDesJoueurs (Critique) Source/Test/Unit/Core/Rpg/test_multiclassing.cpp:59 | L'exemple de multiclassage du Manuel des Joueurs est reproduit a l'identique. | 1. Calculer le niveau de lanceur d'un rodeur 4 / magicien 3. 2. Lire les emplacements correspondants dans la table livree. | Vérifie que niveau vaut 5. Vérifie que table.size() est strictement supérieur à static_cast<std::size_t>(niveau). Vérifie que table[static_cast<std::size_t>(niveau)][0] vaut 4. Vérifie que table[static_cast<std::size_t>(niveau)][1] vaut 3. Vérifie que table[static_cast<std::size_t>(niveau)][2] vaut 2. |
| MulticlassingTest.LArrondiSeFaitParClasse (Critique) Source/Test/Unit/Core/Rpg/test_multiclassing.cpp:89 | L'arrondi du niveau de lanceur se fait par classe, jamais sur le total. | 1. Calculer le niveau de lanceur d'un paladin 3 / rodeur 3. 2. Calculer celui d'un guerrier 5 / roublard 5 sous archetype. | Vérifie que core::multiclassCasterLevel(paladinRodeur) vaut 2. Vérifie que core::multiclassCasterLevel(guerrierRoublard) vaut 2. |
| MulticlassingTest.LaMagieDePacteEstCompteeAPart (Critique) Source/Test/Unit/Core/Rpg/test_multiclassing.cpp:110 | Les emplacements de magie de pacte n'entrent pas dans le cumul multiclasse. | 1. Calculer le niveau de lanceur d'un sorcier 5 / magicien 3. | Vérifie que core::multiclassCasterLevel(sorcierMagicien) vaut 3. |
| MulticlassingTest.ClassesSansIncantationEtBorneSuperieure (Majeur) Source/Test/Unit/Core/Rpg/test_multiclassing.cpp:128 | Une classe sans incantation n'apporte rien au niveau de lanceur, borne a 20. | 1. Calculer le niveau d'un barbare 10 seul, puis d'un magicien 20 / clerc 20. | Vérifie que core::multiclassCasterLevel(barbare) vaut 0. Vérifie que core::multiclassCasterLevel(impossible) vaut 20. |
| MulticlassingTest.AllerRetourDesNomsDeProgression (Majeur) Source/Test/Unit/Core/Rpg/test_multiclassing.cpp:145 | Les noms de progression de lanceur font l'aller-retour sans perte. | 1. Convertir chaque progression en nom, puis le nom en progression. 2. Analyser un nom inconnu. | Vérifie que nom.empty() est faux. Vérifie que relu.has_value() est vrai. Vérifie que *relu vaut progression. Vérifie que core::parseCasterProgression("plein").has_value() est faux. Vérifie que core::parseCasterProgression("").has_value() est faux. |
| MulticlassingTest.LesProgressionsDeLaDonneeSontConnuesDuMoteur (Critique) Source/Test/Unit/Core/Rpg/test_multiclassing.cpp:171 | Les progressions de lanceur de la donnee sont toutes connues du moteur. | 1. Lire casterProgression de multiclassing.json. 2. Analyser chaque valeur avec parseCasterProgression. | Vérifie que document.ok() est vrai. Vérifie que progressions.size() vaut 12U. Vérifie que core::parseCasterProgression(nom).has_value() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RpgEnumsTest.AllerRetourSurToutesLesValeurs (Critique) Source/Test/Unit/Core/Rpg/test_rpg_enums.cpp:67 | Chaque valeur des enumerations RPG fait l'aller-retour par son nom sans perte. | 1. Pour chaque type de degats, condition et ecole de magie, convertir en nom puis reconvertir en valeur. | Vérifie que nom.empty() est faux. Vérifie que relu.has_value() est vrai. Vérifie que *relu vaut type. Vérifie que nom.empty() est faux. Vérifie que relu.has_value() est vrai. Vérifie que *relu vaut condition. Vérifie que nom.empty() est faux. Vérifie que relu.has_value() est vrai. Vérifie que *relu vaut school. Vérifie que nom.empty() est faux. Vérifie que relu.has_value() est vrai. Vérifie que *relu vaut size. |
| RpgEnumsTest.LesNomsSontUniques (Critique) Source/Test/Unit/Core/Rpg/test_rpg_enums.cpp:109 | Deux valeurs distinctes d'une enumeration RPG ne portent jamais le meme nom. | 1. Collecter les noms de chaque enumeration dans un ensemble. | Vérifie que nomsDuMoteur(core::allDamageTypes(), core::damageTypeName).size() vaut core::allDamageTypes().size(). Vérifie que nomsDuMoteur(core::allConditions(), core::conditionName).size() vaut core::allConditions().size(). Vérifie que nomsDuMoteur(core::allMagicSchools(), core::magicSchoolName).size() vaut core::allMagicSchools().size(). Vérifie que nomsDuMoteur(core::allCreatureSizes(), core::creatureSizeName).size() vaut core::allCreatureSizes().size(). |
| RpgEnumsTest.UnNomInconnuEstRefuse (Majeur) Source/Test/Unit/Core/Rpg/test_rpg_enums.cpp:129 | Un nom d'enumeration RPG inconnu est refuse au lieu d'etre devine. | 1. Analyser une chaine vide, un terme francais, et un nom de casse differente. | Vérifie que core::parseDamageType("").has_value() est faux. Vérifie que core::parseDamageType("psychique").has_value() est faux. Vérifie que core::parseDamageType("Psychic").has_value() est faux. Vérifie que core::parseCondition("empoisonne").has_value() est faux. Vérifie que core::parseMagicSchool("invocation").has_value() est faux. Vérifie que core::parseCreatureSize("P").has_value() est faux. Vérifie que core::parseCreatureSize("moyenne").has_value() est faux. |
| RpgEnumsTest.LesEnumerationsCoincidentAvecLesSchemas (Critique) Source/Test/Unit/Core/Rpg/test_rpg_enums.cpp:152 | Les enumerations partagees entre le C++ et les schemas JSON sont identiques. | 1. Lire les enumerations damageType, conditionRef et magicSchool de common.schema.json. 2. Les comparer aux noms produits par core::DamageType, core::Condition et core::MagicSchool. | Vérifie que nomsDuMoteur(core::allDamageTypes(), core::damageTypeName) vaut enumDuSchema("damageType"). Vérifie que nomsDuMoteur(core::allConditions(), core::conditionName) vaut enumDuSchema("conditionRef"). Vérifie que nomsDuMoteur(core::allMagicSchools(), core::magicSchoolName) vaut enumDuSchema("magicSchool"). Vérifie que nomsDuMoteur(core::allCreatureSizes(), core::creatureSizeName) vaut enumDuSchema("size"). |
| RpgEnumsTest.LesEnsemblesFermesOntLeurCardinal (Majeur) Source/Test/Unit/Core/Rpg/test_rpg_enums.cpp:185 | Les enumerations fermees du RPG ont le nombre de valeurs fixe par les regles. | 1. Compter les types de degats, les conditions et les ecoles de magie. | Vérifie que core::allDamageTypes().size() vaut 13U. Vérifie que core::allConditions().size() vaut 15U. Vérifie que core::allMagicSchools().size() vaut 8U. Vérifie que core::allCreatureSizes().size() vaut 6U. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| FixedTimestepTest.UnPasExact (Majeur) Source/Test/Unit/Core/Time/test_fixed_timestep.cpp:19 | Un temps écoulé égal au pas fixe produit exactement un pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que timestep.advance(STEP) vaut 1. |
| FixedTimestepTest.TempsInsuffisant (Majeur) Source/Test/Unit/Core/Time/test_fixed_timestep.cpp:34 | Un temps écoulé inférieur au pas ne produit aucun pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que timestep.advance(STEP * 0.5f) vaut 0. |
| FixedTimestepTest.TempsNulOuNegatif (Majeur) Source/Test/Unit/Core/Time/test_fixed_timestep.cpp:49 | Un temps écoulé nul ou négatif ne produit aucun pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que timestep.advance(0.0f) vaut 0. Vérifie que timestep.advance(-1.0f) vaut 0. |
| FixedTimestepTest.ResteConserve (Majeur) Source/Test/Unit/Core/Time/test_fixed_timestep.cpp:65 | 2,5 pas donnent 2 pas, et le reste (0,5 pas) est conservé puis complété. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que timestep.advance(STEP * 2.5f) vaut 2. Vérifie que timestep.interpolationAlpha() vaut 0.5f, à 1e-4f près. Vérifie que timestep.advance(STEP * 0.6f) vaut 1. |
| FixedTimestepTest.PlafondAntiSpirale (Majeur) Source/Test/Unit/Core/Time/test_fixed_timestep.cpp:85 | Un temps écoulé énorme est plafonné (anti-spirale de la mort). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que timestep.advance(STEP * 1000.0f) vaut maximum. Vérifie que timestep.advance(0.0f) vaut 0. |
| FixedTimestepTest.PasFixeExpose (Majeur) Source/Test/Unit/Core/Time/test_fixed_timestep.cpp:103 | Le pas fixe exposé correspond à la configuration. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que timestep.fixedDeltaSeconds() vaut STEP, à 1e-6f près. |
| FixedTimestepTest.PauseSansAppelNAccumuleAucunPas (Critique) Source/Test/Unit/Core/Time/test_fixed_timestep.cpp:122 | Une pause simulée (aucun appel à advance()) n'accumule aucun pas. | 1. Avancer normalement de quelques pas. 2. Simuler une pause de longue durée en n'appelant PAS advance() (aucun appel, pas un appel à zéro). 3. Reprendre avec un petit delta, comme après réarmement de l'horloge de référence. | Vérifie que timestep.advance(STEP * 3.0f) vaut 3. Vérifie que timestep.advance(STEP) vaut 1. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AtlasTest.LesTreizeRegionsEtLeursLieuxChargentSansErreur (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:56 | Les treize regions et leurs quatre-vingt-quatorze lieux se chargent tous. | 1. Charger Source/Elements/World. 2. Compter les regions, les lieux et les erreurs rapportees. | Vérifie que atlas().errors.empty() est vrai. Vérifie que atlas().regions.size() vaut REGIONS_DU_LIVRE. Vérifie que atlas().locations.size() vaut LIEUX_DU_LIVRE. |
| AtlasTest.ChaqueRegionPorteSesSeptAxes (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:73 | Chaque region porte les sept statistiques regionales. | 1. Pour chaque region, lire les sept axes de l'encart. | Vérifie que axe.appraisals.empty() est faux. |
| AtlasTest.LEncartDeLEmpireCentralEstRejoueDepuisLeLivre (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:95 | L'encart de l'Empire central concorde avec le Sourcebook. | 1. Comparer les sept notes de l'Empire central aux valeurs lues sur la page imprimee 90. 2. Comparer l'effectif et la part de la premiere espece au bloc d'introduction. | Vérifie que empire diffère de nullptr. Vérifie que empire->statistic(note.axis).grade() vaut note.grade. Vérifie que empire->statistic(note.axis).varies() est faux. Vérifie que empire->population.total.has_value() est vrai. Vérifie que *empire->population.total vaut 2300000. Vérifie que empire->population.species.empty() est faux. Vérifie que empire->population.species.front().species vaut "human". Vérifie que empire->population.species.front().percent vaut 84. |
| AtlasTest.UneRegionNonUniformePorteSesDeuxAppreciations (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:135 | Une region non uniforme porte ses deux appreciations avec leur portee. | 1. Lire la liberte civique du Benenet imperial et la criminalite des Domaines straviens. 2. Verifier les deux notes et les deux portees de chacune. | Vérifie que benenet diffère de nullptr. Vérifie que liberte.appraisals.size() vaut 2U. Vérifie que liberte.varies() est vrai. Vérifie que liberte.appraisals[0].grade vaut core::RegionGrade::Low. Vérifie que liberte.appraisals[0].scope vaut "south". Vérifie que liberte.appraisals[1].grade vaut core::RegionGrade::High. Vérifie que liberte.appraisals[1].scope vaut "north". Vérifie que stravian diffère de nullptr. Vérifie que crime.appraisals.size() vaut 2U. Vérifie que crime.appraisals[0].grade vaut core::RegionGrade::Low. Vérifie que crime.appraisals[0].scope vaut "underground". Vérifie que crime.appraisals[1].grade vaut core::RegionGrade::High. Vérifie que crime.appraisals[1].scope vaut "surface". |
| AtlasTest.UneRegionUniformeNePorteAucunePortee (Mineur) Source/Test/Unit/Core/World/test_atlas.cpp:172 | Une region uniforme ne nomme aucune portee. | 1. Pour chaque axe ne portant qu'une appreciation, lire sa portee. | Vérifie que axe.appraisals.front().scope.empty() est vrai. |
| AtlasTest.AucunLieuSansRegion (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:194 | Aucun lieu n'est orphelin de region. | 1. Pour chaque lieu, resoudre la region qu'il declare. 2. Verifier que cette region le cite en retour. | Vérifie que region diffère de nullptr. Vérifie que std::ranges::find(region->locations, lieu.id) diffère de region->locations.end(). |
| AtlasTest.ToutLieuCiteParUneRegionExiste (Majeur) Source/Test/Unit/Core/World/test_atlas.cpp:213 | Toute region ne cite que des lieux existants. | 1. Pour chaque region, resoudre chacun des lieux qu'elle cite. | Vérifie que atlas().findLocation(identifiant) diffère de nullptr. |
| AtlasTest.LeVoisinageEstSymetriqueEtLeGrapheConnexe (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:231 | Le voisinage des regions est symetrique et le graphe connexe. | 1. Pour chaque arete, verifier que la region voisine declare la reciproque. 2. Parcourir le graphe depuis la premiere region. | Vérifie que autre diffère de nullptr. Vérifie que std::ranges::find(autre->neighbors, region.id) diffère de autre->neighbors.end(). Vérifie que atlas().regions.empty() est faux. Vérifie que atlas().unreachableFrom(atlas().regions.front().id).empty() est vrai. |
| AtlasTest.UneRegionCoupeeDuGrapheEstSignalee (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:256 | Le controle de connexite sait echouer. | 1. Retirer les aretes de Yama, dans une copie de l'atlas. 2. Relancer le parcours depuis une autre region. | Vérifie que ampute.regions.size() est supérieur ou égal à 2U. Vérifie que cible diffère de nullptr. Vérifie que depart diffère de isolee. Vérifie que std::ranges::find(perdues, isolee) diffère de perdues.end(). |
| AtlasTest.LesNotesDuMoteurCoincidentAvecCellesDuSchema (Critique) Source/Test/Unit/Core/World/test_atlas.cpp:295 | Les notes et les axes du moteur coincident avec region.schema.json. | 1. Lire le schema LIVRE. 2. Y chercher les cinq notes et les sept axes que le moteur nomme. 3. Verifier qu'une note hors des cinq est refusee. | Vérifie que flux.is_open() est vrai. Vérifie que schema.find('"' + std::string{nom} + '"') diffère de std::string::npos. Vérifie que core::regionGradeFromName(nom) vaut std::optional<core::RegionGrade>{static_cast<core::RegionGrade>(rang)}. Vérifie que core::regionGradeFromName("average").has_value() est faux. Vérifie que schema.find('"' + std::string{nom} + '"') diffère de std::string::npos. |
| AtlasTest.UnDossierAbsentEstUneErreurPasUnMondeVide (Majeur) Source/Test/Unit/Core/World/test_atlas.cpp:333 | Un dossier d'atlas absent produit une erreur, pas un monde vide. | 1. Charger un dossier qui n'existe pas. | Vérifie que absent.regions.empty() est vrai. Vérifie que absent.errors.empty() est faux. |
| AtlasTest.LesPartsDePopulationRestentPlausibles (Majeur) Source/Test/Unit/Core/World/test_atlas.cpp:349 | Les parts de population de chaque region somment a 100 % a l'arrondi pres. | 1. Pour chaque region, sommer les parts d'espece et la part << others >>. | Vérifie que part.percent est strictement supérieur à 0. Vérifie que part.species.empty() est faux. Vérifie que somme est supérieur ou égal à 97. Vérifie que somme est inférieur ou égal à 103. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| GridDistanceFieldTest.DistanceDeLaCibleAElleMemeEstNulle (Majeur) Source/Test/Unit/Core/World/test_grid_distance_field.cpp:18 | La distance de la cible à elle-même est nulle. | 1. Grille ouverte, GridDistanceField construit avec une cible. | Vérifie que field.distance(target) vaut 0. |
| GridDistanceFieldTest.GrilleOuverteEgaleDistanceDeManhattan (Bloquant) Source/Test/Unit/Core/World/test_grid_distance_field.cpp:34 | Grille sans mur : distance de grille égale à la distance de Manhattan. | 1. Grille 10x10 vide, cible en (0,0). 2. Lit la distance de plusieurs cases. | Vérifie que field.distance(core::GridPosition{3, 0}) vaut 3. Vérifie que field.distance(core::GridPosition{0, 4}) vaut 4. Vérifie que field.distance(core::GridPosition{3, 4}) vaut 7. Vérifie que field.distance(core::GridPosition{9, 9}) vaut 18. |
| GridDistanceFieldTest.MurSeparateurCompletRendInatteignable (Bloquant) Source/Test/Unit/Core/World/test_grid_distance_field.cpp:54 | Mur séparateur complet : cases isolées à la distance sentinelle. | 1. Grille 5x5, colonne 2 entièrement solide (mur de bord en bord). 2. Cible en (0,0), lit la distance d'une case de l'autre côté du mur ((4,0)). | Vérifie que field.distance(core::GridPosition{4, 0}) vaut map.width() * map.height(). |
| GridDistanceFieldTest.MurPartielForceUnDetourPlusLongQueLaLigneDirecte (Bloquant) Source/Test/Unit/Core/World/test_grid_distance_field.cpp:75 | Mur partiel (détour) : la distance de grille suit le chemin réel, pas la ligne droite. | 1. Grille 3x3, case (1,1) solide (mur direct entre (1,2) et la cible (1,0)). | Vérifie que field.distance(core::GridPosition{1, 2}) vaut 4. |
| GridDistanceFieldTest.CaseHorsGrilleRenvoieLaSentinelle (Mineur) Source/Test/Unit/Core/World/test_grid_distance_field.cpp:94 | Case hors-grille : distance sentinelle, pas de plantage. | 1. Grille 5x5, cible valide. 2. Lit la distance d'une case negative et d'une case au-delà des bornes. | Vérifie que field.distance(core::GridPosition{-1, 0}) vaut sentinel. Vérifie que field.distance(core::GridPosition{5, 5}) vaut sentinel. |
| GridDistanceFieldTest.MultiCiblesDistanceALaPlusProche (Bloquant) Source/Test/Unit/Core/World/test_grid_distance_field.cpp:114 | Multi-cibles : distance à la plus proche des cibles fournies. | 1. Grille ouverte 10x10, deux cibles (0,0) et (9,9). 2. Lit la distance d'une case proche de chaque cible. | Vérifie que field.distance(core::GridPosition{1, 0}) vaut 1. Vérifie que field.distance(core::GridPosition{8, 9}) vaut 1. Vérifie que field.distance(core::GridPosition{0, 0}) vaut 0. Vérifie que field.distance(core::GridPosition{9, 9}) vaut 0. |
| GridDistanceFieldTest.MultiCiblesIgnoreUneCibleSolideOuHorsGrille (Bloquant) Source/Test/Unit/Core/World/test_grid_distance_field.cpp:136 | Multi-cibles : une cible invalide n'empêche pas les autres de fonctionner. | 1. Grille 5x5, case (1,1) solide utilisée comme première cible, (4,4) valide comme seconde. | Vérifie que field.distance(core::GridPosition{4, 4}) vaut 0. Vérifie que field.distance(core::GridPosition{3, 4}) vaut 1. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AudioEngine.MutedEngineAcceptsPreloadAndPlayWithoutError (Critique) Source/Test/Unit/HMI/Audio/test_audio_engine.cpp:15 | Un moteur audio muet accepte precharge et lecture sans erreur. | 1. Construire un AudioEngine force en etat muet (ForceMuted::Yes). 2. Precharger un echantillon sur un chemin inexistant. 3. Jouer cet echantillon, puis un identifiant jamais precharge. | Vérifie que engine.muted() est vrai. |
| AudioEngine.VolumeIsClampedToUnitRange (Majeur) Source/Test/Unit/HMI/Audio/test_audio_engine.cpp:37 | Le volume du moteur audio est borne a [0, 1]. | 1. Regler un volume negatif, puis un volume superieur a 1, puis une valeur intermediaire. | Vérifie que engine.volume() vaut 0.0f (comparaison flottante). Vérifie que engine.volume() vaut 1.0f (comparaison flottante). Vérifie que engine.volume() vaut 0.42f (comparaison flottante). |
| AudioEngine.DefaultVolumeIsFull (Mineur) Source/Test/Unit/HMI/Audio/test_audio_engine.cpp:61 | Le volume par defaut du moteur audio est au maximum. | 1. Construire un AudioEngine sans regler de volume. | Vérifie que engine.volume() vaut 1.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| SoundCatalogTest.CatalogueValideSeCharge (Critique) Source/Test/Unit/HMI/Audio/test_sound_catalog.cpp:31 | Un catalogue de sons valide se lit sans erreur. | 1. Charger un JSON de catalogue avec deux evenements. 2. Resoudre chacun des deux evenements. | Vérifie que result.ok() est vrai. Vérifie que result.catalog->resolve("saut") vaut "saut.wav". Vérifie que result.catalog->resolve("atterrissage") vaut "atterrissage.wav". |
| SoundCatalogTest.FichierAbsentEstFileNotFound (Majeur) Source/Test/Unit/HMI/Audio/test_sound_catalog.cpp:49 | Un fichier de catalogue de sons absent produit un catalogue vide. | 1. Charger un catalogue depuis un chemin inexistant. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::SoundCatalogError::FileNotFound. |
| SoundCatalogTest.EntreeMalformeeEchoueLeChargementEntier (Critique) Source/Test/Unit/HMI/Audio/test_sound_catalog.cpp:68 | Une entree malformee du catalogue de sons fait echouer tout le chargement. | 1. Charger un JSON dont une entree "sons" n'est pas une chaine. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::SoundCatalogError::MalformedStructure. |
| SoundCatalogTest.EvenementInconnuResoutNullopt (Majeur) Source/Test/Unit/HMI/Audio/test_sound_catalog.cpp:92 | Un evenement inconnu du catalogue de sons ne produit aucune erreur. | 1. Charger le catalogue de reference. 2. Resoudre un identifiant d'evenement absent du catalogue. | Vérifie que result.ok() est vrai. Vérifie que result.catalog->resolve("evenement_qui_n_existe_pas") vaut std::nullopt. |
| SoundCatalogTest.VersionSuperieureRefusee (Mineur) Source/Test/Unit/HMI/Audio/test_sound_catalog.cpp:109 | Une version de format superieure au catalogue de sons connu est refusee. | 1. Charger un JSON dont le champ "version" depasse SoundCatalog::FORMAT_VERSION. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::SoundCatalogError::UnsupportedVersion. |
| SoundCatalogTest.CatalogueLivreValide (Critique) Source/Test/Unit/HMI/Audio/test_sound_catalog.cpp:129 | Le fichier de sons livre avec le jeu se lit sans erreur. | 1. Lire Source/Elements/Audio/sounds.json depuis les sources. | Vérifie que std::filesystem::exists(path) est vrai. Vérifie que result.ok() est vrai. Vérifie que result.catalog->eventIds().empty() est faux. |
| SoundCatalogTest.AssetsDuCatalogueLivreExistent (Critique) Source/Test/Unit/HMI/Audio/test_sound_catalog.cpp:148 | Chaque son reference par le catalogue livre existe. | 1. Lire le catalogue livre. 2. Pour chaque evenement, verifier que le fichier resolu existe dans Source/Elements/Audio. | Vérifie que result.ok() est vrai. Vérifie que file.has_value() est vrai. Vérifie que std::filesystem::exists(assetPath) est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| SoundTriggersTest.TableExhaustive (Critique) Source/Test/Unit/HMI/Audio/test_sound_triggers.cpp:15 | La table evenement vers son est exhaustive. | 1. Parcourir toutes les valeurs de GameEvent (0 a GAME_EVENT_COUNT - 1). 2. Appeler soundForEvent sur chacune. | Aucun plantage : le switch interne couvre chaque cas (verifie par construction, pas par relecture – un GameEvent ajoute sans entree casserait la compilation avant ce test). |
| SoundTriggersTest.EvenementsDePersonnageResolvent (Critique) Source/Test/Unit/HMI/Audio/test_sound_triggers.cpp:35 | Les evenements de personnage resolvent les bons identifiants de son. | 1. Resoudre Jumped, Landed, Dashed, Died, ExitReached. | Vérifie que hmi::soundForEvent(hmi::GameEvent::Jumped) vaut "saut". Vérifie que hmi::soundForEvent(hmi::GameEvent::Landed) vaut "atterrissage". Vérifie que hmi::soundForEvent(hmi::GameEvent::Dashed) vaut "dash". Vérifie que hmi::soundForEvent(hmi::GameEvent::Died) vaut "mort". Vérifie que hmi::soundForEvent(hmi::GameEvent::ExitReached) vaut "sortie_atteinte". |
| SoundTriggersTest.EvenementsDeMecanismesResolvent (Majeur) Source/Test/Unit/HMI/Audio/test_sound_triggers.cpp:53 | Les evenements de mecanismes resolvent les bons identifiants de son. | 1. Resoudre SwitchToggled, PressurePlatePressed, PressurePlateReleased. | Vérifie que hmi::soundForEvent(hmi::GameEvent::SwitchToggled) vaut "interrupteur". Vérifie que hmi::soundForEvent(hmi::GameEvent::PressurePlatePressed) vaut "plaque_pression". Vérifie que hmi::soundForEvent(hmi::GameEvent::PressurePlateReleased) vaut "plaque_pression". |
| SoundTriggersTest.EvenementsSansBruitageResolventNullopt (Mineur) Source/Test/Unit/HMI/Audio/test_sound_triggers.cpp:68 | Des evenements sans bruitage dedie resolvent vers std::nullopt. | 1. Resoudre WallContactEnter et BlockPushed. | Vérifie que hmi::soundForEvent(hmi::GameEvent::WallContactEnter) vaut std::nullopt. Vérifie que hmi::soundForEvent(hmi::GameEvent::BlockPushed) vaut std::nullopt. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| SessionLogTest.SerialiseUneLigneParMessage (Majeur) Source/Test/Unit/HMI/Diagnostics/test_session_log.cpp:18 | Chaque message donne une ligne, dans l'ordre d'arrivée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::serializeSessionLog(entries) vaut "premier message\\nsecond message\\n". |
| SessionLogTest.VideDonneChaineVide (Majeur) Source/Test/Unit/HMI/Diagnostics/test_session_log.cpp:37 | Une session sans message produit un texte vide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::serializeSessionLog({}) vaut "". |
test_asset_file_operations.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AssetFileOps.ImporteUnAssetConforme (Critique) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:57 | Importer un asset conforme le copie sans déplacer l'original. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que std::filesystem::exists(result.path) est vrai. Vérifie que std::filesystem::exists(source) est vrai. |
| AssetFileOps.RefuseUnAssetNonConforme (Critique) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:81 | Un asset non conforme est refusé en nommant le fichier, sans rien copier. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.error.find("mur.png") diffère de std::string::npos. Vérifie que ops.list().empty() est vrai. |
| AssetFileOps.RefuseUneCollisionAlImport (Critique) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:106 | Importer un second fichier de même nom est refusé, sans écraser le premier. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que ops.import(first, hmi::AssetFamily::Background, 4, 4).ok() est vrai. Vérifie que result.ok() est faux. |
| AssetFileOps.RenommeEtConserveLExtension (Critique) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:133 | Renommer un asset conserve son extension et déplace le fichier. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que imported.ok() est vrai. Vérifie que renamed.ok() est vrai. Vérifie que renamed.path.filename().string() vaut "pierre.png". Vérifie que std::filesystem::exists(imported.path) est faux. |
| AssetFileOps.RefuseUnNomInvalideAuRenommage (Critique) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:156 | Un nom invalide au renommage est refusé sans rien changer. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que imported.ok() est vrai. Vérifie que ops.rename(imported.path, "a/b").ok() est faux. Vérifie que std::filesystem::exists(imported.path) est vrai. |
| AssetFileOps.DupliqueSousUnNomUnique (Majeur) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:179 | Dupliquer deux fois le même asset produit deux copies distinctes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que imported.ok() est vrai. Vérifie que first.ok() est vrai. Vérifie que second.ok() est vrai. Vérifie que first.path diffère de second.path. Vérifie que ops.list().size() vaut 3U. |
| AssetFileOps.SupprimeLeFichier (Majeur) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:204 | Supprimer retire effectivement l'asset du disque. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que imported.ok() est vrai. Vérifie que ops.remove(imported.path).ok() est vrai. Vérifie que std::filesystem::exists(imported.path) est faux. |
| AssetFileOps.OperationSurFichierAbsentEchoueProprement (Majeur) Source/Test/Unit/HMI/Editor/test_asset_file_operations.cpp:226 | Renommer, dupliquer ou supprimer un fichier absent échoue proprement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que ops.rename(absent, "autre").ok() est faux. Vérifie que ops.duplicate(absent).ok() est faux. Vérifie que ops.remove(absent).ok() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AssetLibraryTest.NeRetientQueLesImagesTrieesParOrdreAlphabetique (Majeur) Source/Test/Unit/HMI/Editor/test_asset_library.cpp:47 | Le balayage ne retient que les images, triées par ordre alphabétique. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que assets vaut (std::vector<std::string>{"crate.png", "stone.png"}). |
| AssetLibraryTest.ExtensionInsensibleALaCasse (Majeur) Source/Test/Unit/HMI/Editor/test_asset_library.cpp:69 | L'extension d'image est reconnue quelle que soit sa casse. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que assets vaut (std::vector<std::string>{"crate.Png", "stone.PNG"}). |
| AssetLibraryTest.FiltreParSousChaineInsensibleALaCasse (Majeur) Source/Test/Unit/HMI/Editor/test_asset_library.cpp:89 | La recherche filtre par sous-chaîne insensible à la casse, liste vide si rien ne correspond. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::listAssetFiles(dir, "STONE") vaut (std::vector<std::string>{"stone.png", "stone_cracked.png"}). Vérifie que hmi::listAssetFiles(dir, "crate") vaut (std::vector<std::string>{"crate.png"}). Vérifie que hmi::listAssetFiles(dir, "inexistant").empty() est vrai. |
| AssetLibraryTest.DossierAbsentListeVide (Majeur) Source/Test/Unit/HMI/Editor/test_asset_library.cpp:112 | Un dossier d'assets absent donne une liste vide, sans exception. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::listAssetFiles(std::filesystem::temp_directory_path() / "pg_asset_library_absent") .empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AssetReferencesTest.AssetCiteParUnJeuEstTrouve (Majeur) Source/Test/Unit/HMI/Editor/test_asset_references.cpp:21 | Un asset cité par un jeu de skins est retrouvé, avec le nom du jeu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que references.size() vaut 1U. Vérifie que references.front().setName vaut "foret". |
| AssetReferencesTest.AssetCiteParPlusieursJeuxEtTypesEstTrouveAChaqueFois (Majeur) Source/Test/Unit/HMI/Editor/test_asset_references.cpp:44 | Un asset cité par plusieurs jeux et types donne une référence par citation. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que references.size() vaut 3U. |
| AssetReferencesTest.AssetNonReferenceNeDonneAucuneReference (Majeur) Source/Test/Unit/HMI/Editor/test_asset_references.cpp:69 | Un asset non référencé ne donne aucune référence. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::findSkinCatalogReferences(catalog, "grass.png").empty() est vrai. |
| AssetReferencesTest.NomProcheMaisDifferentNeDeclenchePasDeFauxPositif (Majeur) Source/Test/Unit/HMI/Editor/test_asset_references.cpp:88 | Un nom proche mais différent ne déclenche pas de fausse référence. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::findSkinCatalogReferences(catalog, "stone.png").empty() est vrai. |
| AssetReferencesTest.DescribeReferencesEstVideSansReference (Mineur) Source/Test/Unit/HMI/Editor/test_asset_references.cpp:106 | Sans référence, le message descriptif est vide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::describeReferences({}).empty() est vrai. |
| AssetReferencesTest.DescribeReferencesNommeLesJeuxEtLesTypes (Majeur) Source/Test/Unit/HMI/Editor/test_asset_references.cpp:120 | Le message descriptif nomme les jeux de skins et les types concernés. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que message.find("foret") diffère de std::string::npos. Vérifie que message.find("grotte") diffère de std::string::npos. Vérifie que message.find("solid") diffère de std::string::npos. Vérifie que message.find("block") diffère de std::string::npos. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EditorStatusTest.AucunNiveauOuvertNAfficheRien (Critique) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:83 | Aucun niveau ouvert n'affiche aucune zone ni aide. | 1. Construire un contexte sans niveau. 2. Calculer les lignes. | Vérifie que lines.permanent.size() vaut 7u. Vérifie que zone vaut "". Vérifie que lines.help vaut "". |
| EditorStatusTest.AucuneCaseSurvoleeLaisseLaZoneVide (Majeur) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:104 | Aucune case survolee laisse la zone de coordonnees vide. | 1. Construire un niveau sans case survolee. 2. Calculer les lignes. | Vérifie que lines.permanent[0] vaut "Niveau : Salle des epreuves". Vérifie que lines.permanent[3] vaut "". |
| EditorStatusTest.IndicateurDeModificationSuitLEtatDirty (Critique) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:123 | L'indicateur de modification suit l'etat "dirty" du niveau. | 1. Calculer les lignes avec dirty=true, puis dirty=false. 2. Comparer la zone d'indicateur. | Vérifie que hmi::editorStatusLines(dirtyContext, localization).permanent[1] vaut "Modifie". Vérifie que hmi::editorStatusLines(cleanContext, localization).permanent[1] vaut "". |
| EditorStatusTest.ZoneDeCadrageAfficheLeModeCourant (Majeur) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:148 | La zone de cadrage affiche le mode courant, traduit. | 1. Calculer les lignes pour un niveau en mode par salle, puis suivi. 2. Comparer la zone de cadrage (index 6). | Vérifie que hmi::editorStatusLines(perRoomContext, localization).permanent[6] vaut "Cadrage : Par salle". Vérifie que hmi::editorStatusLines(followContext, localization).permanent[6] vaut "Cadrage : Suivi du personnage". |
| EditorStatusTest.AideChangeAvecLOutilActif (Critique) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:176 | L'aide contextuelle change avec l'outil actif. | 1. Calculer les lignes avec l'outil Pinceau, puis Lien. 2. Comparer l'aide. | Vérifie que hmi::editorStatusLines(paintContext, localization).help vaut "Aide pinceau". Vérifie que hmi::editorStatusLines(linkContext, localization).help vaut "Aide lien". |
| EditorStatusTest.MemeContexteProduitLaMemeAide (Majeur) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:202 | La decision est deterministe : meme contexte, meme resultat. | 1. Calculer deux fois les lignes pour le meme contexte. 2. Comparer. | Vérifie que first.help vaut second.help. Vérifie que first.permanent vaut second.permanent. |
| EditorStatusTest.ContextePixelEditProduitLesZonesEtLAideAttendues (Critique) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:225 | Le contexte d'atelier pixel art produit les zones et l'aide attendues. | 1. Construire un contexte d'edition d'asset avec un pixel survole. 2. Calculer les lignes. | Vérifie que lines.permanent[0] vaut "Asset : mur.png". Vérifie que lines.permanent[1] vaut "". Vérifie que lines.permanent[2] vaut "Pinceau". Vérifie que lines.permanent[3] vaut "(3, 5)". Vérifie que lines.permanent[4] vaut "Zoom : 800%". Vérifie que lines.permanent[5] vaut "Couleur : #ff0000ff". Vérifie que lines.help vaut "Aide pinceau pixel". |
| EditorStatusTest.ModeContraintFigureDansLaZoneCouleur (Majeur) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:252 | Le mode contraint figure dans la zone couleur. | 1. Calculer les lignes avec le mode contraint actif, puis inactif. 2. Comparer la zone couleur (index 5). | Vérifie que hmi::editorStatusLines(constrainedContext, localization).permanent[5] vaut "Couleur : #ff0000ff (contrainte)". Vérifie que hmi::editorStatusLines(freeContext, localization).permanent[5] vaut "Couleur : #ff0000ff". |
| EditorStatusTest.AucunAssetOuvertLaisseLaZoneVide (Majeur) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:279 | Aucun asset ouvert laisse la zone d'asset vide. | 1. Construire un contexte d'atelier sans nom d'asset. 2. Calculer les lignes. | Vérifie que lines.permanent[0] vaut "". Vérifie que lines.permanent[2] vaut "Pinceau". |
| EditorStatusTest.AideDeLAtelierChangeAvecLOutilActif (Majeur) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:300 | L'aide de l'atelier change avec l'outil de canevas actif. | 1. Calculer les lignes avec l'outil Gomme, puis Pipette. 2. Comparer l'aide. | Vérifie que hmi::editorStatusLines(eraserContext, localization).help vaut "Aide gomme". Vérifie que hmi::editorStatusLines(eyedropperContext, localization).help vaut "Aide pipette". |
| EditorStatusTest.ClesDeTraductionExistentDansLesDeuxCatalogues (Majeur) Source/Test/Unit/HMI/Editor/test_editor_status.cpp:326 | Les cles de traduction de la barre d'etat existent dans les deux catalogues. | 1. Charger fr.lang puis en.lang depuis les catalogues livres. 2. Resoudre chaque cle utilisee. | Vérifie que localization.loadDefaultLanguage(language) est vrai. Vérifie que localization.text(key) diffère de key. |
test_level_file_operations.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LevelFileOps.CreeUnNiveauValide (Critique) Source/Test/Unit/HMI/Editor/test_level_file_operations.cpp:39 | Créer un niveau écrit un fichier valide, immédiatement listé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que std::filesystem::exists(result.path) est vrai. Vérifie que ops.list().size() vaut 1U. |
| LevelFileOps.FichierDeSequenceExcluDeLaListe (Majeur) Source/Test/Unit/HMI/Editor/test_level_file_operations.cpp:58 | Un fichier de séquence n'apparaît jamais dans la liste des niveaux. | 1. Créer un niveau valide, puis écrire à côté un fichier sequence-demo.json quelconque. 2. Lister le dossier. | Vérifie que ops.create("MonNiveau", 10, 6).ok() est vrai. Vérifie que listed.size() vaut 1U. Vérifie que listed.front().filename().string() vaut "MonNiveau.json". |
| LevelFileOps.RefuseNomInvalideEtCollision (Critique) Source/Test/Unit/HMI/Editor/test_level_file_operations.cpp:82 | Un nom invalide ou déjà pris est refusé, sans écraser le niveau existant. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que ops.create("a/b", 10, 6).ok() est faux. Vérifie que ops.create("Niveau", 10, 6).ok() est vrai. Vérifie que ops.create("Niveau", 10, 6).ok() est faux. |
| LevelFileOps.RenommeEtDeplaceLeFichier (Critique) Source/Test/Unit/HMI/Editor/test_level_file_operations.cpp:99 | Renommer déplace le fichier : l'ancien chemin disparaît, le nouveau existe. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que created.ok() est vrai. Vérifie que renamed.ok() est vrai. Vérifie que std::filesystem::exists(created.path) est faux. Vérifie que std::filesystem::exists(renamed.path) est vrai. |
| LevelFileOps.DupliqueSousUnNomUnique (Critique) Source/Test/Unit/HMI/Editor/test_level_file_operations.cpp:119 | Dupliquer deux fois le même niveau produit deux copies distinctes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que base.ok() est vrai. Vérifie que first.ok() est vrai. Vérifie que second.ok() est vrai. Vérifie que first.path diffère de second.path. Vérifie que ops.list().size() vaut 3U. |
| LevelFileOps.SupprimeLeFichier (Critique) Source/Test/Unit/HMI/Editor/test_level_file_operations.cpp:141 | Supprimer retire effectivement le fichier du disque. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que created.ok() est vrai. Vérifie que ops.remove(created.path).ok() est vrai. Vérifie que std::filesystem::exists(created.path) est faux. |
test_level_name_validation.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LevelNameValidationTest.NomSimpleValide (Majeur) Source/Test/Unit/HMI/Editor/test_level_name_validation.cpp:15 | Un nom simple, sans caractère interdit, est valide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::isValidLevelName("Niveau 1") est vrai. Vérifie que hmi::isValidLevelName("Foret enchantee") est vrai. |
| LevelNameValidationTest.NomVideOuEspacesInvalide (Majeur) Source/Test/Unit/HMI/Editor/test_level_name_validation.cpp:30 | Un nom vide ou composé uniquement d'espaces est invalide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::isValidLevelName("") est faux. Vérifie que hmi::isValidLevelName(" ") est faux. |
| LevelNameValidationTest.CaractereInterditInvalide (Majeur) Source/Test/Unit/HMI/Editor/test_level_name_validation.cpp:45 | Un nom contenant un caractère interdit par le système de fichiers Windows est invalide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::isValidLevelName("Niveau:1") est faux. Vérifie que hmi::isValidLevelName("Niveau/1") est faux. Vérifie que hmi::isValidLevelName("Niveau\\\\1") est faux. Vérifie que hmi::isValidLevelName("Niveau*1") est faux. Vérifie que hmi::isValidLevelName("Niveau?1") est faux. Vérifie que hmi::isValidLevelName("Niveau\\"1\")</tt> est faux.<br/>Vérifie que <tt>hmi::isValidLevelName(\"Niveau\<1\")</tt> est faux.<br/>Vérifie que <tt>hmi::isValidLevelName(\"Niveau\>1\")</tt> est faux.<br/>Vérifie que <tt>hmi::isValidLevelName(\"Niveau\\|1\") est faux. |
| LevelNameValidationTest.NomAccentueValide (Mineur) Source/Test/Unit/HMI/Editor/test_level_name_validation.cpp:70 | Un nom accentué (Unicode) reste valide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::isValidLevelName("Fort\\xC3\\xA9resse") est vrai. |
| LevelNameValidationTest.TrimRetireLesEspacesDeBord (Mineur) Source/Test/Unit/HMI/Editor/test_level_name_validation.cpp:84 | trimLevelName retire les espaces de bord sans toucher au contenu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::trimLevelName(" Niveau 1 ") vaut "Niveau 1". Vérifie que hmi::trimLevelName("Niveau 1") vaut "Niveau 1". Vérifie que hmi::trimLevelName(" ") vaut "". |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LinkGeometry.LinkSegmentRelieLesCentresDeCase (Majeur) Source/Test/Unit/HMI/Editor/test_link_geometry.cpp:22 | Le trait de liaison relie les centres des deux cases. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que segment.a.x vaut 0.5f (comparaison flottante). Vérifie que segment.a.y vaut 0.5f (comparaison flottante). Vérifie que segment.b.x vaut 3.5f (comparaison flottante). Vérifie que segment.b.y vaut 0.5f (comparaison flottante). |
| LinkGeometry.LinkSegmentVertical (Majeur) Source/Test/Unit/HMI/Editor/test_link_geometry.cpp:41 | Un lien vertical ne fait varier que l'ordonnée, du déclencheur vers la cible. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que segment.a.x vaut segment.b.x (comparaison flottante). Vérifie que segment.a.y est strictement inférieur à segment.b.y. |
| LinkGeometry.LinkSegmentDiagonalSansDecalage (Majeur) Source/Test/Unit/HMI/Editor/test_link_geometry.cpp:58 | Un lien diagonal seul relie les centres sans aucun décalage. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que segment.a.x vaut 0.5f (comparaison flottante). Vérifie que segment.a.y vaut 0.5f (comparaison flottante). Vérifie que segment.b.x vaut 2.5f (comparaison flottante). Vérifie que segment.b.y vaut 2.5f (comparaison flottante). |
| LinkGeometry.LinkSegmentDecalageAntiSuperpositionBaseCommune (Critique) Source/Test/Unit/HMI/Editor/test_link_geometry.cpp:78 | Des liens frères gardent une base commune et écartent symétriquement leur extrémité cible. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first.a.x vaut second.a.x (comparaison flottante). Vérifie que first.a.y vaut second.a.y (comparaison flottante). Vérifie que second.a.x vaut third.a.x (comparaison flottante). Vérifie que second.a.y vaut third.a.y (comparaison flottante). Vérifie que second.b.y vaut 0.5f (comparaison flottante). Vérifie que first.b.y diffère de second.b.y. Vérifie que third.b.y diffère de second.b.y. Vérifie que second.b.y - first.b.y vaut third.b.y - second.b.y (comparaison flottante). Vérifie que hmi::linkSegment(trigger, target, 0, 3).b.y vaut first.b.y. |
| LinkGeometry.ArrowHeadOrienteeVersLaCible (Majeur) Source/Test/Unit/HMI/Editor/test_link_geometry.cpp:115 | La pointe de flèche a ses ailes en retrait et symétriques par rapport à l'axe. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que head.left.x est strictement inférieur à 4.0f. Vérifie que head.right.x est strictement inférieur à 4.0f. Vérifie que head.left.y vaut -head.right.y (comparaison flottante). Vérifie que head.left.y diffère de 0.0f. |
| LinkGeometry.ArrowHeadSegmentDegenere (Majeur) Source/Test/Unit/HMI/Editor/test_link_geometry.cpp:138 | Un segment dégénéré replie la pointe sur le point, sans division par zéro. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que head.left.x vaut point.x (comparaison flottante). Vérifie que head.left.y vaut point.y (comparaison flottante). Vérifie que head.right.x vaut point.x (comparaison flottante). Vérifie que head.right.y vaut point.y (comparaison flottante). |
| LinkGeometry.BuildLinkRowsVideSansLiaison (Mineur) Source/Test/Unit/HMI/Editor/test_link_geometry.cpp:157 | Un brouillon sans liaison donne une liste vide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::buildLinkRows(draft).empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LinkGesture.ClicHorsCategorieIgnore (Majeur) Source/Test/Unit/HMI/Editor/test_link_gesture.cpp:23 | Un clic hors catégorie est ignoré quand aucune attente n'est en cours. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut LinkGestureAction::Ignore. |
| LinkGesture.PremierClicSurDeclencheurPoseLAttente (Critique) Source/Test/Unit/HMI/Editor/test_link_gesture.cpp:39 | Sans attente, un clic sur un déclencheur pose l'attente. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut LinkGestureAction::SetPending. Vérifie que decision.cell vaut (GridPosition{2, 3}). |
| LinkGesture.PremierClicSurCiblePoseLAttente (Critique) Source/Test/Unit/HMI/Editor/test_link_gesture.cpp:56 | Sans attente, un clic sur une cible pose aussi l'attente. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut LinkGestureAction::SetPending. Vérifie que decision.cell vaut (GridPosition{4, 0}). |
| LinkGesture.DeuxDeclencheursRemplacentLAttente (Majeur) Source/Test/Unit/HMI/Editor/test_link_gesture.cpp:73 | Deux déclencheurs successifs remplacent l'attente au lieu de se lier. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut LinkGestureAction::ReplacePending. Vérifie que decision.cell vaut (GridPosition{1, 0}). |
| LinkGesture.DeclencheurPuisCibleNonLieeCreeLaLiaison (Critique) Source/Test/Unit/HMI/Editor/test_link_gesture.cpp:91 | Déclencheur en attente puis cible non liée crée la liaison. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut LinkGestureAction::Link. Vérifie que decision.switchPosition vaut (GridPosition{0, 0}). Vérifie que decision.targetPosition vaut (GridPosition{3, 3}). |
| LinkGesture.AttentePerimeeEstIgnoreeEtRemplacee (Critique) Source/Test/Unit/HMI/Editor/test_link_gesture.cpp:110 | Une attente périmée est ignorée et remplacée par le clic courant. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut LinkGestureAction::SetPending. Vérifie que decision.cell vaut (GridPosition{3, 3}). |
| LinkGesture.ClicHorsCategorieAvecAttenteIgnore (Majeur) Source/Test/Unit/HMI/Editor/test_link_gesture.cpp:127 | Un clic hors catégorie est ignoré sans perdre l'attente en cours. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut LinkGestureAction::Ignore. |
test_mechanism_animation_assignments.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MechanismAnimationAssignmentsTest.UneLigneParFamille (Critique) Source/Test/Unit/HMI/Editor/test_mechanism_animation_assignments.cpp:63 | La section Animations propose exactement les familles de mecanismes a etat. | 1. Construire les lignes pour un catalogue vide. | Vérifie que rows.size() vaut std::size(hmi::MECHANISM_ANIMATION_TYPES). Vérifie que rows[index].type vaut hmi::MECHANISM_ANIMATION_TYPES[index]. Vérifie que rows[index].asset.empty() est vrai. Vérifie que rows[index].missingClips.empty() est vrai. |
| MechanismAnimationAssignmentsTest.AssetSansAnimationListeToutManquant (Critique) Source/Test/Unit/HMI/Editor/test_mechanism_animation_assignments.cpp:88 | Un asset assigne sans .anim.json liste tous les clips attendus comme manquants. | 1. Assigner un asset a Door, sans creer de fichier d'animation. | Vérifie que door diffère de nullptr. Vérifie que door->asset vaut "door.png". Vérifie que door->missingClips vaut hmi::mechanismExpectedClips(core::TileType::Door). |
| MechanismAnimationAssignmentsTest.AssetCompletNeManqueRien (Critique) Source/Test/Unit/HMI/Editor/test_mechanism_animation_assignments.cpp:112 | Un asset fournissant tous les clips attendus ne signale rien de manquant. | 1. Assigner un asset a Switch et deposer un .anim.json avec ses deux clips attendus. | Vérifie que row diffère de nullptr. Vérifie que row->missingClips.empty() est vrai. |
| MechanismAnimationAssignmentsTest.AssetPartielSignaleLeReste (Majeur) Source/Test/Unit/HMI/Editor/test_mechanism_animation_assignments.cpp:138 | Un asset partiel signale uniquement les clips absents. | 1. Assigner un asset a Door dont le .anim.json ne fournit que « closed » et « open ». | Vérifie que door diffère de nullptr. Vérifie que door->missingClips vaut (std::vector<std::string>{hmi::MECHANISM_CLIP_DOOR_OPENING, hmi::MECHANISM_CLIP_DOOR_CLOSING}). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PaletteAppearanceTest.ModePhysiqueMontreLaCouleurPlate (Critique) Source/Test/Unit/HMI/Editor/test_palette_appearance.cpp:40 | En mode Physique, la palette montre la couleur plate du type. | 1. Demander la vignette de Solid en mode Physique, alors qu'un skin lui est assigne. | Vérifie que thumbnail.source vaut hmi::PaletteThumbnailSource::Atlas. Vérifie que thumbnail.region.x vaut physical.x. Vérifie que thumbnail.region.y vaut physical.y. Vérifie que thumbnail.masked est faux. |
| PaletteAppearanceTest.ModeTextureMontreLeSkin (Critique) Source/Test/Unit/HMI/Editor/test_palette_appearance.cpp:62 | En mode Texture, la palette montre le fichier reellement assigne. | 1. Demander la vignette de Block, assigne a un skin en mode image unique. | Vérifie que thumbnail.source vaut hmi::PaletteThumbnailSource::Skin. Vérifie que thumbnail.asset vaut "crate.png". Vérifie que thumbnail.region.width vaut TILE. Vérifie que thumbnail.masked est faux. |
| PaletteAppearanceTest.SkinARaccordsMontreLaCaseRepresentative (Majeur) Source/Test/Unit/HMI/Editor/test_palette_appearance.cpp:85 | Un skin a raccords montre l'interieur plein de sa planche. | 1. Demander la vignette de Solid, assigne a une planche a raccords. | Vérifie que thumbnail.region.x vaut cell.column * TILE. Vérifie que thumbnail.region.y vaut cell.row * TILE. Vérifie que thumbnail.region.width vaut TILE. |
| PaletteAppearanceTest.TypeNonSkinneMontreLeDamier (Critique) Source/Test/Unit/HMI/Editor/test_palette_appearance.cpp:109 | Un type non skinne montre le damier dans la palette, comme dans le niveau. | 1. Demander la vignette d'un type absent du catalogue, en mode Texture. 2. Demander une vignette sans catalogue du tout. | Vérifie que unassigned.source vaut hmi::PaletteThumbnailSource::MissingTexture. Vérifie que unassigned.region.width vaut hmi::MISSING_TEXTURE_SIZE. Vérifie que noCatalog.source vaut hmi::PaletteThumbnailSource::MissingTexture. |
| PaletteAppearanceTest.PaletteEtCanevasDecidentPareil (Critique) Source/Test/Unit/HMI/Editor/test_palette_appearance.cpp:135 | La palette et le canevas resolvent la meme source pour chaque type. | 1. Pour plusieurs types et les deux modes, comparer la source choisie par la palette a celle choisie par la resolution du canevas. | Vérifie que sameAtlas \|\| sameSkin \|\| sameMissing est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PanelFocusTest.OutilLienMetEnAvantLePanneauLiens (Majeur) Source/Test/Unit/HMI/Editor/test_panel_focus.cpp:16 | L'outil Lien met en avant le panneau Liens. | 1. Interroger la table pour l'outil Lien. 2. Verifier le panneau retourne. | Vérifie que hmi::panelForTool(hmi::EditorTool::Link) vaut hmi::PanelId::Links. |
| PanelFocusTest.OutilTextureMetEnAvantLePanneauTextures (Majeur) Source/Test/Unit/HMI/Editor/test_panel_focus.cpp:29 | L'outil Texture met en avant le panneau Textures. | 1. Interroger la table pour l'outil Texture par instance. 2. Verifier le panneau retourne. | Vérifie que hmi::panelForTool(hmi::EditorTool::TextureAssign) vaut hmi::PanelId::Textures. |
| PanelFocusTest.OutilsSansPanneauDedieNeMettentRienEnAvant (Majeur) Source/Test/Unit/HMI/Editor/test_panel_focus.cpp:44 | Les outils sans panneau dedie ne mettent rien en avant. | 1. Interroger la table pour chaque outil sans panneau dedie. 2. Verifier l'absence de resultat. | Vérifie que hmi::panelForTool(tool) vaut std::nullopt. |
| PanelFocusTest.AucunDoublonDOutilDansLaTable (Majeur) Source/Test/Unit/HMI/Editor/test_panel_focus.cpp:61 | La table ne contient aucun doublon d'outil. | 1. Parcourir toutes les paires d'entrees de la table. 2. Comparer leurs outils. | Vérifie que catalog[i].tool diffère de catalog[j].tool. |
| PanelFocusTest.OutilsDeCanevasMettentEnAvantLePanneauDuCanevas (Majeur) Source/Test/Unit/HMI/Editor/test_panel_focus.cpp:80 | Chaque outil de canevas pixel art met en avant le panneau du canevas. | 1. Interroger la table pour chacun des quatre outils de canevas. 2. Verifier le panneau retourne. | Vérifie que hmi::panelForPixelTool(tool) vaut hmi::PanelId::PixelCanvas. |
| PanelFocusTest.AucunDoublonDOutilDansLaTableDeCanevas (Mineur) Source/Test/Unit/HMI/Editor/test_panel_focus.cpp:99 | La table des outils de canevas ne contient aucun doublon. | 1. Parcourir toutes les paires d'entrees de la table des outils de canevas. 2. Comparer leurs outils. | Vérifie que catalog[i].tool diffère de catalog[j].tool. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PixelAssetIOTest.ChaqueTailleProposeeEstConforme (Critique) Source/Test/Unit/HMI/Editor/test_pixel_asset_io.cpp:18 | Chaque taille proposee est conforme au contrat de sa famille. | 1. Pour chaque famille, produire les tailles proposees. 2. Valider chacune contre le contrat de la meme famille. | Vérifie que validation.valid est vrai. |
| PixelAssetIOTest.FamilleADimensionsLibresNeProposeAucuneTaille (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_asset_io.cpp:44 | Une famille a dimensions libres ne propose aucune taille. | 1. Produire les tailles proposees pour Fond et Police. | Vérifie que hmi::validAssetSizes(hmi::AssetFamily::Background).empty() est vrai. Vérifie que hmi::validAssetSizes(hmi::AssetFamily::Font).empty() est vrai. |
| PixelAssetIOTest.TileSkinProposeDesLargeursMultiplesDeCase (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_asset_io.cpp:59 | Un skin de tuile propose des largeurs multiples de case, hauteur fixe. | 1. Produire les tailles proposees pour TileSkin. 2. Verifier la hauteur et la largeur de chaque taille. | Vérifie que sizes.empty() est faux. Vérifie que height vaut hmi::TextureAtlas::TILE_SIZE. Vérifie que width % hmi::TextureAtlas::TILE_SIZE vaut 0. |
| PixelAssetIOTest.AutotileSheetProposePlusieursTailles (Mineur) Source/Test/Unit/HMI/Editor/test_pixel_asset_io.cpp:80 | Les familles a taille non contrainte proposent plusieurs options. | 1. Produire les tailles proposees pour AutotileSheet. | Vérifie que sizes.size() est strictement supérieur à 1U. |
test_pixel_autotile_preview.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PixelAutotilePreviewTest.SeuleUneImage4x4EstUnePlancheARaccords (Critique) Source/Test/Unit/HMI/Editor/test_pixel_autotile_preview.cpp:34 | Seule une image de dimensions exactement 4x4 cases est une planche a raccords. | 1. Tester une image 4x4 cases. 2. Tester des images plus petites, plus grandes, et non carrees. | Vérifie que hmi::isBitmask16Candidate(sheetImage(4, 4, 0), TILE) est vrai. Vérifie que hmi::isBitmask16Candidate(sheetImage(3, 4, 0), TILE) est faux. Vérifie que hmi::isBitmask16Candidate(sheetImage(4, 3, 0), TILE) est faux. Vérifie que hmi::isBitmask16Candidate(sheetImage(8, 8, 0), TILE) est faux. Vérifie que hmi::isBitmask16Candidate(sheetImage(1, 1, 0), TILE) est faux. |
| PixelAutotilePreviewTest.BitmaskCellAtPixelResoutLaCaseAttendue (Critique) Source/Test/Unit/HMI/Editor/test_pixel_autotile_preview.cpp:54 | bitmaskCellAtPixel resout la case attendue ou nullopt. | 1. Interroger une position au milieu de la case (2,1) d'une planche 4x4. 2. Interroger une position hors bornes. 3. Interroger la meme position sur une image qui n'est pas une planche. | Vérifie que cell.has_value() est vrai. Vérifie que cell->column vaut 2. Vérifie que cell->row vaut 1. Vérifie que hmi::bitmaskCellAtPixel(sheet, TILE, sheet.width, 0).has_value() est faux. Vérifie que hmi::bitmaskCellAtPixel(sheet, TILE, -1, 0).has_value() est faux. Vérifie que hmi::bitmaskCellAtPixel(notASheet, TILE, 1, 1).has_value() est faux. |
| PixelAutotilePreviewTest.ApercuDAssemblageUtiliseLaMemeTableQueLeRendu (Critique) Source/Test/Unit/HMI/Editor/test_pixel_autotile_preview.cpp:83 | L'apercu d'assemblage utilise la meme table que le rendu. | 1. Construire une planche 4x4 dont chaque case a une couleur distincte. 2. Construire l'apercu d'assemblage. 3. Comparer la case centrale de l'apercu a la case attendue de la source (via autotileCell du masque plein). | Vérifie que preview.width vaut TILE * 3. Vérifie que preview.height vaut TILE * 3. Vérifie que hmi::pickColor(preview, TILE + 1, TILE + 1) vaut expectedColor. |
| PixelAutotilePreviewTest.PlancheTropPetiteNeDebordePas (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_autotile_preview.cpp:124 | Une planche trop petite laisse la case correspondante transparente. | 1. Construire l'apercu d'assemblage a partir d'une planche degeneree (1x1 case). | EXPECT_NO_THROW(preview = hmi::buildAutotileAssemblyPreview(tinySheet, TILE)) Vérifie que preview.width vaut TILE * 3. Vérifie que preview.height vaut TILE * 3. |
test_pixel_canvas_geometry.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PixelCanvasGeometryTest.ScreenToImagePixelPourDiversesVues (Critique) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:19 | screenToImagePixel donne le bon pixel pour diverses combinaisons de zoom et de decalage. | 1. Construire plusieurs vues (zoom, decalage) differentes. 2. Convertir une position ecran connue vers un pixel image. | Vérifie que hmi::screenToImagePixel(view, 16, 16, 0.0, 0.0) vaut std::make_pair(0, 0). Vérifie que hmi::screenToImagePixel(view, 16, 16, 20.0, 12.0) vaut std::make_pair(2, 1). Vérifie que hmi::screenToImagePixel(zoomed, 16, 16, 20.0, 12.0) vaut std::make_pair(1, 0). Vérifie que hmi::screenToImagePixel(panned, 16, 16, 0.0, 0.0) vaut std::make_pair(3, 1). |
| PixelCanvasGeometryTest.ScreenToImagePixelHorsBornesRenvoieAbsence (Critique) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:43 | screenToImagePixel renvoie nullopt hors de l'image, y compris en negatif. | 1. Convertir une position ecran negative. 2. Convertir une position au-dela du bord droit/bas de l'image. | Vérifie que hmi::screenToImagePixel(view, 4, 4, -1.0, 0.0).has_value() est faux. Vérifie que hmi::screenToImagePixel(view, 4, 4, 0.0, -8.0).has_value() est faux. Vérifie que hmi::screenToImagePixel(view, 4, 4, 32.0, 0.0).has_value() est faux. |
| PixelCanvasGeometryTest.AllerRetourRectangleVersPixel (Critique) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:62 | Le centre du rectangle d'un pixel reconverti donne ce meme pixel, a tout zoom. | 1. Pour plusieurs zooms et decalages, calculer le rectangle ecran d'un pixel. 2. Reconvertir le centre de ce rectangle. | Vérifie que roundTrip.has_value() est vrai. Vérifie que *roundTrip vaut std::make_pair(x, y). |
| PixelCanvasGeometryTest.PixelCanvasRealSizeReutiliseThumbnailPixelSize (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:98 | pixelCanvasRealSize reutilise thumbnailPixelSize (LOT-56) sans la redefinir. | 1. Calculer la taille reelle du canevas a plusieurs facteurs d'echelle. 2. Calculer independamment thumbnailPixelSize sur les memes tailles logiques. | Vérifie que real.width vaut hmi::thumbnailPixelSize(IMAGE_WIDTH * ZOOM, factor). Vérifie que real.height vaut hmi::thumbnailPixelSize(IMAGE_HEIGHT * ZOOM, factor). |
| PixelCanvasGeometryTest.CommandesDeZoomRestentBorneesEtEntieres (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:123 | Les commandes de zoom restent bornees et entieres. | 1. Zoomer avant a repetition au-dela du maximum. 2. Zoomer arriere a repetition en-deca du minimum. | Vérifie que zoom vaut hmi::PIXEL_CANVAS_MAX_ZOOM. Vérifie que zoom vaut hmi::PIXEL_CANVAS_MIN_ZOOM. |
| PixelCanvasGeometryTest.GrilleVisibleAuSeuilAttendu (Mineur) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:147 | pixelCanvasGridVisible bascule au seuil attendu. | 1. Evaluer pixelCanvasGridVisible juste en-deca et juste au niveau du seuil. | Vérifie que hmi::pixelCanvasGridVisible(hmi::PIXEL_CANVAS_GRID_VISIBLE_MIN_ZOOM - 1) est faux. Vérifie que hmi::pixelCanvasGridVisible(hmi::PIXEL_CANVAS_GRID_VISIBLE_MIN_ZOOM) est vrai. |
| PixelCanvasGeometryTest.AllerRetourExactSousLeUnPourUn (Critique) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:165 | L'aller-retour vue vers image reste exact sous le 1:1. | 1. Pour les denominateurs 2 et 4, convertir chaque pixel image en rectangle ecran. 2. Reconvertir le centre de ce rectangle en pixel image. | Vérifie que hmi::isValidPixelCanvasDenominator(denominator) est vrai. Vérifie que back.has_value() est vrai. Vérifie que back->first vaut x. Vérifie que back->second vaut y. |
| PixelCanvasGeometryTest.PixelsCarresATousLesZooms (Critique) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:194 | Les pixels restent carres a tout zoom. | 1. Parcourir plusieurs numerateurs et les quatre denominateurs admis. 2. Comparer largeur et hauteur du rectangle ecran d'un pixel. | Vérifie que rect.width vaut rect.height (comparaison flottante). Vérifie que hmi::pixelCanvasScale(view) vaut static_cast<double>(numerator) / denominator (comparaison flottante). |
| PixelCanvasGeometryTest.CourseDeZoomRationnelleBornee (Critique) Source/Test/Unit/HMI/Editor/test_pixel_canvas_geometry.cpp:218 | La course de zoom descend sous le 1:1 et y remonte. | 1. Reduire depuis le 1:1 jusqu'a la borne basse. 2. Agrandir jusqu'a repasser au 1:1. | Vérifie que view.zoomDenominator vaut hmi::PIXEL_CANVAS_MAX_DENOMINATOR. Vérifie que hmi::pixelCanvasScale(view) vaut 1.0 / hmi::PIXEL_CANVAS_MAX_DENOMINATOR (comparaison flottante). Vérifie que hmi::pixelCanvasGridVisible(view) est faux. Vérifie que view.zoomDenominator vaut 1. Vérifie que hmi::pixelCanvasScale(view) vaut 1.0 (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PixelHistoryTest.SuiteDOperationsAnnulableEtRetablissable (Critique) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:50 | Une suite d'operations est annulable puis retablissable a l'identique. | 1. Appliquer trois operations successives. 2. Annuler deux fois. 3. Retablir deux fois. | Vérifie que hmi::pickColor(image, 0, 0) vaut RED. Vérifie que hmi::pickColor(image, 1, 0) vaut GREEN. Vérifie que hmi::pickColor(image, 2, 0) vaut BLUE. Vérifie que history.undo(image) est vrai. Vérifie que hmi::pickColor(image, 2, 0) vaut 0u. Vérifie que history.undo(image) est vrai. Vérifie que hmi::pickColor(image, 1, 0) vaut 0u. Vérifie que hmi::pickColor(image, 0, 0) vaut RED. Vérifie que history.redo(image) est vrai. Vérifie que hmi::pickColor(image, 1, 0) vaut GREEN. Vérifie que history.redo(image) est vrai. Vérifie que hmi::pickColor(image, 2, 0) vaut BLUE. |
| PixelHistoryTest.NouvelleOperationApresAnnulationVideLeRetablissement (Critique) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:85 | Une nouvelle operation apres une annulation vide la pile de retablissement. | 1. Appliquer deux operations. 2. Annuler la derniere. 3. Appliquer une operation differente. | Vérifie que history.undo(image) est vrai. Vérifie que history.canRedo() est vrai. Vérifie que history.canRedo() est faux. Vérifie que history.redo(image) est faux. |
| PixelHistoryTest.AnnulerAuDelaDuFondDePileSansEffet (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:111 | Annuler au-dela du fond de pile est sans effet. | 1. Sur un historique vide, appeler undo(). 2. Appliquer une operation, l'annuler, puis annuler une seconde fois. | Vérifie que history.undo(image) est faux. Vérifie que history.undo(image) est vrai. Vérifie que history.undo(image) est faux. Vérifie que hmi::pickColor(image, 0, 0) vaut RED. |
| PixelHistoryTest.JumpToEquivautADesAnnulationsSuccessives (Critique) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:134 | jumpTo produit le meme tampon que des annulations successives. | 1. Appliquer quatre operations sur deux tampons identiques independants. 2. Sur le premier, annuler successivement jusqu'a l'entree d'index 1. 3. Sur le second, appeler jumpTo(1) directement. | Vérifie que undoHistory.undo(byUndo) est vrai. Vérifie que undoHistory.undo(byUndo) est vrai. Vérifie que jumpHistory.jumpTo(byJump, 1) est vrai. Vérifie que byUndo.pixels vaut byJump.pixels. |
| PixelHistoryTest.JumpToHorsBornesEchoueProprement (Mineur) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:167 | jumpTo hors bornes echoue proprement. | 1. Appliquer une operation. 2. Appeler jumpTo avec un index hors bornes. | Vérifie que history.jumpTo(image, 5) est faux. Vérifie que hmi::pickColor(image, 0, 0) vaut GREEN. |
| PixelHistoryTest.ProfondeurPlafonneeOublieLesEntreesLesPlusAnciennes (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:186 | Au-dela de la profondeur maximale, les entrees les plus anciennes sont oubliees. | 1. Construire un historique de profondeur 2. 2. Appliquer trois operations. | Vérifie que history.appliedEntries().size() vaut 2U. Vérifie que hmi::pickColor(image, 0, 0) vaut RED. Vérifie que hmi::pickColor(image, 1, 0) vaut GREEN. Vérifie que hmi::pickColor(image, 2, 0) vaut BLUE. |
| PixelHistoryTest.AppliedEntriesExposeLaListeOrdonnee (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:213 | appliedEntries expose la liste ordonnee des operations. | 1. Appliquer pinceau puis gomme. 2. Lire appliedEntries(). | Vérifie que history.appliedEntries().size() vaut 2U. Vérifie que history.appliedEntries()[0].kind vaut hmi::PixelOperationKind::Brush. Vérifie que history.appliedEntries()[1].kind vaut hmi::PixelOperationKind::Eraser. |
| PixelHistoryTest.ClesDeNomDOperationExistentDansLesDeuxCatalogues (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_history.cpp:235 | Chaque cle de nom d'operation existe dans les deux catalogues. | 1. Charger fr.lang puis en.lang. 2. Resoudre la cle de chaque type d'operation. | Vérifie que localization.loadDefaultLanguage(language) est vrai. Vérifie que localization.text(key) diffère de key. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PixelOperationsTest.SetPixelChangeLaCouleurEtRenvoieLaRegion (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:39 | setPixel change la couleur du pixel vise et renvoie la region attendue. | 1. Poser un pixel dans les bornes d'une image. 2. Poser un pixel hors bornes. | Vérifie que region.empty() est faux. Vérifie que region.minX vaut 1. Vérifie que region.maxX vaut 1. Vérifie que region.minY vaut 2. Vérifie que region.maxY vaut 2. Vérifie que hmi::pickColor(image, 1, 2) vaut GREEN. Vérifie que outOfBounds.empty() est vrai. |
| PixelOperationsTest.ErasePixelPreserveLaTeinteRvb (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:64 | erasePixel met l'alpha a zero sans changer la teinte RVB. | 1. Effacer un pixel colore. 2. Lire sa couleur. | Vérifie que erased.has_value() est vrai. Vérifie que *erased & 0xFF000000u vaut 0u. Vérifie que *erased & 0x00FFFFFFu vaut RED & 0x00FFFFFFu. |
| PixelOperationsTest.PickColorRenvoieLaCouleurOuAbsentHorsBornes (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:83 | pickColor renvoie la couleur du pixel ou nullopt hors bornes. | 1. Poser une couleur connue sur un pixel. 2. La prelever avec pickColor. 3. Prelever hors bornes. | Vérifie que hmi::pickColor(image, 1, 1) vaut BLUE. Vérifie que hmi::pickColor(image, -1, 0).has_value() est faux. Vérifie que hmi::pickColor(image, 3, 0).has_value() est faux. |
| PixelOperationsTest.DrawLineDiagonaleSansTrou (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:102 | drawLine peint un segment diagonal sans trou. | 1. Tracer une ligne diagonale entre deux positions eloignees. 2. Lire chaque pixel du chemin attendu. | Vérifie que region.minX vaut 0. Vérifie que region.minY vaut 0. Vérifie que region.maxX vaut 5. Vérifie que region.maxY vaut 5. Vérifie que hmi::pickColor(image, i, i) vaut GREEN. |
| PixelOperationsTest.DrawLineVerticaleSansTrou (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:125 | drawLine peint un segment purement vertical sans trou. | 1. Tracer une ligne verticale. 2. Lire chaque pixel de la colonne. | Vérifie que hmi::pickColor(image, 1, y) vaut RED. Vérifie que hmi::pickColor(image, 0, 3) vaut TRANSPARENT_BLACK. |
| PixelOperationsTest.EraseLineEffaceSansTrou (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:145 | eraseLine efface un segment complet sans trou. | 1. Effacer une ligne diagonale sur une image coloree. 2. Lire chaque pixel du chemin. | Vérifie que region vaut (hmi::PixelRegion{0, 0, 4, 4}). Vérifie que pixel.has_value() est vrai. Vérifie que *pixel & 0xFF000000u vaut 0u. Vérifie que *pixel & 0x00FFFFFFu vaut RED & 0x00FFFFFFu. |
| PixelOperationsTest.FloodFillZoneFermeeNeDeborde (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:169 | floodFill remplit une zone fermee sans deborder. | 1. Construire une image avec un carre interieur cerne d'une bordure d'une autre couleur. 2. Remplir depuis le centre du carre. | Vérifie que hmi::pickColor(image, x, y) vaut GREEN. Vérifie que hmi::pickColor(image, i, 0) vaut BLUE. Vérifie que hmi::pickColor(image, i, 4) vaut BLUE. Vérifie que hmi::pickColor(image, 0, i) vaut BLUE. Vérifie que hmi::pickColor(image, 4, i) vaut BLUE. |
| PixelOperationsTest.FloodFillZoneOuverteRempliJusquAuBord (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:205 | floodFill remplit une zone ouverte jusqu'au bord sans deborder du tampon. | 1. Construire une image entierement d'une couleur (zone "ouverte" par construction : aucune bordure). 2. Remplir depuis un coin. | Vérifie que region.minX vaut 0. Vérifie que region.minY vaut 0. Vérifie que region.maxX vaut 3. Vérifie que region.maxY vaut 2. Vérifie que pixel vaut GREEN. |
| PixelOperationsTest.FloodFillCouleurDejaPresenteNeChangeRien (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:229 | floodFill sur la couleur deja presente est un no-op sans boucle infinie. | 1. Construire une grande image uniforme. 2. La remplir avec sa propre couleur. | Vérifie que region.empty() est vrai. Vérifie que pixel vaut BLUE. |
| PixelOperationsTest.FloodFillImageUnPixel (Mineur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:251 | floodFill fonctionne sur une image d'un seul pixel. | 1. Construire une image 1x1. 2. La remplir d'une autre couleur. | Vérifie que region vaut (hmi::PixelRegion{0, 0, 0, 0}). Vérifie que hmi::pickColor(image, 0, 0) vaut GREEN. |
| PixelOperationsTest.FloodFillImageEntierementUniformeRecoloreTout (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:269 | floodFill sur une image entierement uniforme la recolore integralement. | 1. Construire une image uniforme. 2. La remplir d'une autre couleur depuis un pixel quelconque. | Vérifie que pixel vaut GREEN. |
| PixelOperationsTest.UnionPixelRegionCouvreLesDeuxRegions (Mineur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:290 | unionPixelRegion couvre les deux regions, une region vide etant neutre. | 1. Unir deux regions disjointes. 2. Unir une region avec une region vide. | Vérifie que hmi::unionPixelRegion(a, b) vaut (hmi::PixelRegion{0, 0, 7, 7}). Vérifie que hmi::unionPixelRegion(a, hmi::PixelRegion{}) vaut a. Vérifie que hmi::unionPixelRegion(hmi::PixelRegion{}, b) vaut b. |
| PixelOperationsTest.DeuxSymetriesHorizontalesRestituentLOrigine (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:324 | Deux symetries horizontales restituent l'image d'origine. | 1. Appliquer flipHorizontal deux fois sur une sous-region. 2. Repeter sur l'image entiere. | Vérifie que partial.pixels vaut original.pixels. Vérifie que whole.pixels vaut original.pixels. |
| PixelOperationsTest.DeuxSymetriesVerticalesRestituentLOrigine (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:350 | Deux symetries verticales restituent l'image d'origine. | 1. Appliquer flipVertical deux fois sur une sous-region. | Vérifie que image.pixels vaut original.pixels. |
| PixelOperationsTest.QuatreRotationsRestituentLOrigineSurRegionCarree (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:371 | Quatre rotations restituent l'image d'origine sur une region carree. | 1. Appliquer rotateClockwise quatre fois sur une region carree. | Vérifie que image.pixels vaut original.pixels. |
| PixelOperationsTest.RotationNonCarreeTronqueLeDebordement (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:393 | Rotation non carree : le debordement est tronque au cadre. | 1. Pivoter une region rectangulaire proche du bord de l'image. 2. Verifier que l'image garde sa taille et qu'aucune ecriture n'a debord du tampon. | EXPECT_NO_THROW(hmi::rotateClockwise(image, region)) Vérifie que image.pixels.size() vaut originalSize. Vérifie que image.width vaut 5. Vérifie que image.height vaut 5. |
| PixelOperationsTest.CollerPresDUnBordTronqueSansDeborder (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:419 | Coller pres d'un bord tronque sans ecriture hors limites. | 1. Copier une region. 2. La coller a une position debordant du cadre. | EXPECT_NO_THROW(touched = hmi::pasteClipboard(image, clip, 3, 3)) Vérifie que image.pixels.size() vaut originalSize. Vérifie que touched vaut (hmi::PixelRegion{3, 3, 3, 3}). |
| PixelOperationsTest.TransformationSurRegionVideEstSansEffet (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:443 | Une transformation sur une region vide est sans effet. | 1. Appliquer flipHorizontal, rotateClockwise et moveRegion sur une region vide. | Vérifie que hmi::flipHorizontal(image, empty).empty() est vrai. Vérifie que hmi::rotateClockwise(image, empty).empty() est vrai. Vérifie que hmi::moveRegion(image, empty, 1, 1).empty() est vrai. Vérifie que image.pixels vaut original.pixels. |
| PixelOperationsTest.DeplacerUneRegionLaisseLaZoneQuitteeTransparente (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:464 | Deplacer une region laisse la zone quittee transparente. | 1. Deplacer une region a l'interieur du cadre. 2. Verifier la zone quittee et la zone reposee. 3. Deplacer une region entierement hors cadre. | Vérifie que hmi::pickColor(image, 1, 1).value() & 0xFF000000u vaut 0u. Vérifie que hmi::pickColor(image, 4, 4) vaut GREEN. EXPECT_NO_THROW(hmi::moveRegion(farImage, hmi::PixelRegion{0, 0, 1, 1}, 100, 100)) Vérifie que farImage.pixels.size() vaut 16U. |
| PixelOperationsTest.ReadRegionPuisWriteRegionRestitueLeContenu (Critique) Source/Test/Unit/HMI/Editor/test_pixel_operations.cpp:490 | readRegion puis writeRegion restituent le contenu d'origine. | 1. Lire une region d'une image. 2. Modifier l'image dans cette region. 3. Reecrire les pixels lus a l'etape 1. | Vérifie que before.size() vaut 9U. Vérifie que hmi::pickColor(image, 2, 2) vaut GREEN. Vérifie que hmi::pickColor(image, x, y) vaut RED. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PixelPaletteFile.AllerRetourJsonRestitueLeContenu (Critique) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:53 | Ecrire puis relire une palette restitue le meme contenu, alpha compris. | 1. Construire une palette de trois entrees, dont une avec alpha partiel. 2. L'enregistrer puis la relire. | Vérifie que original.saveToFile(path) est vrai. Vérifie que reloaded.entries().size() vaut 3U. Vérifie que reloaded.entries()[0].name vaut "Rouge". Vérifie que reloaded.entries()[0].color vaut RED. Vérifie que reloaded.entries()[1].name vaut "Vert". Vérifie que reloaded.entries()[1].color vaut GREEN. Vérifie que reloaded.entries()[2].name vaut "Bleu translucide". Vérifie que reloaded.entries()[2].color vaut BLUE_SEMI. |
| PixelPaletteFile.FichierAbsentProduitUnePaletteVide (Critique) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:82 | Un fichier absent produit une palette vide sans exception. | 1. Charger un chemin qui n'existe pas. | EXPECT_NO_THROW(palette = hmi::PixelPalette::loadFromFile(path)) Vérifie que palette.entries().empty() est vrai. |
| PixelPaletteFile.FichierMalformeProduitUnePaletteVide (Critique) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:97 | Un fichier malforme produit une palette vide sans exception. | 1. Ecrire un contenu JSON invalide au chemin de test. 2. Le charger. | EXPECT_NO_THROW(palette = hmi::PixelPalette::loadFromFile(path)) Vérifie que palette.entries().empty() est vrai. |
| PixelPaletteTest.DeuxExtractionsProduisentLaMemeListe (Critique) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:117 | Deux extractions du meme asset produisent la meme liste. | 1. Construire une image avec des couleurs repetees. 2. L'extraire deux fois. | Vérifie que first.size() vaut 2U. Vérifie que first[0].color vaut RED. Vérifie que first[0].count vaut 2. Vérifie que first[1].color vaut GREEN. Vérifie que first[1].count vaut 2. Vérifie que second.size() vaut first.size(). Vérifie que first[i].color vaut second[i].color. Vérifie que first[i].count vaut second[i].count. |
| PixelPaletteTest.ImageEntierementTransparenteProduitUneExtractionVide (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:148 | Une image entierement transparente produit une extraction vide. | 1. Construire une image entierement transparente. 2. L'extraire. | Vérifie que hmi::extractPalette(image).empty() est vrai. |
| PixelPaletteTest.CouleurDejaPresenteRenvoyeeTelleQuelle (Critique) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:162 | Une couleur deja presente est renvoyee telle quelle. | 1. Contraindre une couleur presente dans la palette. | Vérifie que hmi::nearestPaletteColor(GREEN, palette) vaut GREEN. |
| PixelPaletteTest.DepartageADistanceEgaleEstStable (Critique) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:177 | Le departage a distance egale est stable. | 1. Construire une palette avec deux couleurs equidistantes d'une couleur cible. 2. Contraindre la couleur cible plusieurs fois. | Vérifie que first vaut CANDIDATE_A. Vérifie que second vaut first. |
| PixelPaletteTest.PaletteVideLaisseLaCouleurInchangee (Majeur) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:202 | Une palette vide laisse la couleur inchangee. | 1. Contraindre une couleur avec une palette vide. | Vérifie que hmi::nearestPaletteColor(RED, {}) vaut RED. |
| PixelPaletteTest.ContraintePreserveToujoursLAlpha (Critique) Source/Test/Unit/HMI/Editor/test_pixel_palette.cpp:216 | La contrainte preserve toujours l'alpha d'origine. | 1. Contraindre un pixel totalement transparent. 2. Contraindre un pixel semi-transparent. | Vérifie que hmi::nearestPaletteColor(transparent, palette) vaut transparent. Vérifie que constrained & 0xFF000000u vaut semiTransparentGreen & 0xFF000000u. Vérifie que constrained & 0x00FFFFFFu vaut GREEN & 0x00FFFFFFu. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PlaneFileNamingTest.DimensionsDecoulentDeLaTailleEtDeLaDensite (Critique) Source/Test/Unit/HMI/Editor/test_plane_file_naming.cpp:19 | Les dimensions d'un plan decoulent de la taille et de la densite. | 1. Deriver les dimensions d'un niveau 50x26 aux trois densites admises. | Vérifie que hmi::planePixelSize(50, 26, 16) vaut (hmi::PlanePixelSize{800, 416}). Vérifie que hmi::planePixelSize(50, 26, 8) vaut (hmi::PlanePixelSize{400, 208}). Vérifie que hmi::planePixelSize(50, 26, 4) vaut (hmi::PlanePixelSize{200, 104}). |
| PlaneFileNamingTest.DensiteOuTailleInvalideRefusee (Majeur) Source/Test/Unit/HMI/Editor/test_plane_file_naming.cpp:35 | Une densite ou une taille invalide ne produit aucune dimension. | 1. Deriver les dimensions avec une densite hors format, puis avec une largeur nulle. | Vérifie que hmi::planePixelSize(50, 26, 6) vaut (hmi::PlanePixelSize{0, 0}). Vérifie que hmi::planePixelSize(0, 26, 16) vaut (hmi::PlanePixelSize{0, 0}). Vérifie que hmi::planePixelSize(50, -1, 16) vaut (hmi::PlanePixelSize{0, 0}). |
| PlaneFileNamingTest.NomUniqueParSuffixeCroissant (Critique) Source/Test/Unit/HMI/Editor/test_plane_file_naming.cpp:51 | Le nom d'un plan est unique par suffixe numerique croissant. | 1. Demander un nom pour un dossier vide. 2. Le redemander avec ce nom deja pris, puis avec les deux premiers pris. | Vérifie que hmi::uniquePlaneFileName("foret", {}) vaut "foret.png". Vérifie que hmi::uniquePlaneFileName("foret", {"foret.png"}) vaut "foret-2.png". Vérifie que hmi::uniquePlaneFileName("foret", {"foret.png", "foret-2.png"}) vaut "foret-3.png". Vérifie que hmi::uniquePlaneFileName("foret", {"foret.png", "foret-3.png"}) vaut "foret-2.png". |
| PlaneFileNamingTest.CaracteresRefusesRetires (Majeur) Source/Test/Unit/HMI/Editor/test_plane_file_naming.cpp:70 | Les caracteres refuses sont retires du nom de plan. | 1. Assainir des noms contenant espaces, accents, ponctuation et tirets de bord. | Vérifie que hmi::sanitizePlaneBaseName("Foret Sombre") vaut "Foret-Sombre". Vérifie que hmi::sanitizePlaneBaseName("niveau/../secret") vaut "niveausecret". Vérifie que hmi::sanitizePlaneBaseName("--bord--") vaut "bord". Vérifie que hmi::sanitizePlaneBaseName("ciel_2") vaut "ciel_2". |
| PlaneFileNamingTest.NomSansCaractereUtilisableRefuse (Majeur) Source/Test/Unit/HMI/Editor/test_plane_file_naming.cpp:87 | Un nom sans caractere utilisable ne produit aucun fichier. | 1. Demander un nom pour un niveau nomme uniquement de ponctuation. | Vérifie que hmi::uniquePlaneFileName("///", {}).empty() est vrai. Vérifie que hmi::uniquePlaneFileName("", {}).empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PlaneReferenceTest.ReechantillonnageSeizeVersHuitEstExact (Critique) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:55 | Le reechantillonnage 16 vers 8 est exact, sans interpolation. | 1. Reechantillonner un damier 4x4 de la densite 16 vers la densite 8. | Vérifie que reduced.width vaut 2. Vérifie que reduced.height vaut 2. Vérifie que reduced.pixels[0] vaut source.pixels[0]. Vérifie que reduced.pixels[1] vaut source.pixels[2]. Vérifie que reduced.pixels[2] vaut source.pixels[8]. Vérifie que reduced.pixels[3] vaut source.pixels[10]. |
| PlaneReferenceTest.ReechantillonnageHuitVersSeizeDuplique (Majeur) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:77 | Le reechantillonnage 8 vers 16 duplique chaque pixel. | 1. Reechantillonner une image 2x2 de la densite 8 vers la densite 16. | Vérifie que grown.width vaut 4. Vérifie que grown.height vaut 4. Vérifie que grown.pixels[static_cast<std::size_t>(y) * 4 + static_cast<std::size_t>(x)] vaut expected. |
| PlaneReferenceTest.RapportNonEntierRefuse (Majeur) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:109 | Un rapport de densites non entier est refuse. | 1. Reechantillonner de la densite 16 vers une densite qui n'en est pas un diviseur. | Vérifie que reduced.width vaut 0. Vérifie que reduced.pixels.empty() est vrai. |
| PlaneReferenceTest.AlphaOverEstAssociatif (Critique) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:125 | L'alpha-over est associatif. | 1. Composer trois pixels semi-transparents en groupant a gauche, puis a droite. | Vérifie que std::abs(leftChannel - rightChannel) est inférieur ou égal à 1. |
| PlaneReferenceTest.AplatissementIgnoreUneCoucheMasquee (Critique) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:150 | L'aplatissement ignore une couche masquee. | 1. Aplatir deux couches opaques dont la seconde est masquee. 2. Recommencer sans la seconde couche. | Vérifie que flattenedWithHidden.pixels.size() vaut flattenedWithout.pixels.size(). Vérifie que flattenedWithHidden.pixels vaut flattenedWithout.pixels. Vérifie que flattenedWithHidden.pixels.front() vaut first.pixels.front(). |
| PlaneReferenceTest.AplatissementRameneChaqueCoucheALaDensiteCible (Majeur) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:180 | L'aplatissement ramene chaque couche a la densite cible. | 1. Aplatir une couche de densite 8 sur une cible de densite 16. | Vérifie que flattened.width vaut 16. Vérifie que flattened.height vaut 16. Vérifie que flattened.pixels.front() vaut coarse.pixels.front(). Vérifie que flattened.pixels.back() vaut coarse.pixels.front(). |
| PlaneReferenceTest.PelureDOignonDeterministe (Critique) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:202 | La pelure d'oignon est deterministe et aux dimensions du plan. | 1. Construire la pelure d'un brouillon a deux tuiles, en densite 8. 2. La reconstruire a l'identique. | Vérifie que skin.width vaut 3 * DENSITY. Vérifie que skin.height vaut 2 * DENSITY. Vérifie que skin.pixels vaut again.pixels. Vérifie que (painted >> 24) & 0xFFu vaut 255u. Vérifie que skin.pixels[static_cast<std::size_t>(y) * static_cast<std::size_t>(skin.width) + static_cast<std::size_t>(x)] vaut painted. Vérifie que skin.pixels[static_cast<std::size_t>(DENSITY)] vaut 0u. |
| PlaneReferenceTest.DensiteInvalideNeProduitAucunePelure (Majeur) Source/Test/Unit/HMI/Editor/test_plane_reference.cpp:241 | Une densite invalide ne produit aucune pelure d'oignon. | 1. Construire la pelure a une densite hors format. | Vérifie que skin.width vaut 0. Vérifie que skin.pixels.empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| SkinAssignmentsTest.ChaqueTypeApparaitUneFois (Critique) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:62 | Chaque type de tuile peignable apparait exactement une fois dans le panneau. | 1. Construire les lignes du panneau pour un catalogue quelconque. 2. Collecter les types de toutes les lignes. | Vérifie que seen.insert(row.type).second est vrai. Vérifie que row.type diffère de core::TileType::Empty. Vérifie que seen vaut expected. |
| SkinAssignmentsTest.LignesRefletentLAssignation (Critique) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:99 | Les lignes du panneau refletent l'assignation courante du jeu consulte. | 1. Construire les lignes pour un catalogue ou seul Solid est assigne. | Vérifie que row.asset vaut "stone.png". Vérifie que row.mode vaut hmi::SkinMode::Bitmask16. Vérifie que row.asset.empty() est vrai. |
| SkinAssignmentsTest.SectionsSuiventLaPalette (Majeur) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:124 | Les sections du panneau suivent les categories de la palette. | 1. Comparer les libelles de sections aux categories de la taxonomie. | Vérifie que sectionLabels vaut categoryLabels. |
| SkinAssignmentsTest.AssignationPuisRetraitDepuisLePanneau (Critique) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:151 | Assigner puis retirer un skin depuis le panneau modifie le catalogue. | 1. Appliquer une assignation a un type non skinne, puis relire les lignes. 2. Appliquer une assignation vide au meme type, puis relire. | Vérifie que assigned.has_value() est vrai. Vérifie que assigned->asset vaut "spikes.png". Vérifie que catalog.resolve("foret", core::TileType::Danger).has_value() est faux. |
| SkinAssignmentsTest.JeuNonPreciseViseLeDefaut (Majeur) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:176 | Une assignation sans jeu precise vise le jeu par defaut. | 1. Appliquer une assignation en passant un nom de jeu vide. | Vérifie que catalog.defaultSetName() vaut "foret". Vérifie que assignments.find(core::TileType::Door) diffère de assignments.end(). |
| SkinAssignmentsTest.BalayageNeRetientQueLesImages (Majeur) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:195 | Le balayage du dossier de skins ne retient que les images, triees. | 1. Creer un dossier contenant deux PNG, un fichier texte et un README. | Vérifie que assets vaut expected. |
| SkinAssignmentsTest.DossierAbsentListeVide (Majeur) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:219 | Un dossier de skins absent donne une liste vide, sans erreur. | 1. Balayer un chemin qui n'existe pas. | Vérifie que hmi::listSkinAssets(std::filesystem::temp_directory_path() / "jadg_dossier_inexistant") .empty() est vrai. |
| SkinAssignmentsTest.LibellesTaxonomieTraduitsDansLesDeuxLangues (Critique) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:235 | Chaque libelle de la taxonomie a une traduction dans les deux catalogues. | 1. Pour chaque libelle de la taxonomie, obtenir sa cle de traduction. 2. Verifier que la cle est resolue en francais puis en anglais. | Vérifie que loc.loadLanguage(language) est vrai. Vérifie que key.empty() est faux. Vérifie que loc.text(key) diffère de key. |
| SkinAssignmentsTest.LibellesDuPanneauTraduits (Critique) Source/Test/Unit/HMI/Editor/test_skin_assignments.cpp:275 | Les libelles propres au panneau Textures existent dans les deux catalogues. | 1. Pour chaque cle utilisee par le panneau, la resoudre en francais puis en anglais. | Vérifie que loc.loadLanguage(language) est vrai. Vérifie que loc.text(key) diffère de key. |
test_texture_assign_gesture.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TextureAssignGesture.CaseVideIgnoree (Majeur) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:26 | Une case vide est toujours ignorée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Ignore. |
| TextureAssignGesture.AucunAssetSelectionneIgnore (Majeur) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:42 | Sans asset sélectionné, le clic est ignoré. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Ignore. |
| TextureAssignGesture.CaseSansOverrideAssigneLAssetSelectionne (Critique) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:58 | Sur une case sans surcharge, le clic assigne l'asset sélectionné. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Assign. Vérifie que decision.cell vaut (GridPosition{2, 3}). Vérifie que decision.assetName vaut "door_red.png". |
| TextureAssignGesture.CaseAvecOverrideDifferentRemplace (Majeur) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:76 | Sur une case surchargée avec un autre asset, le clic remplace. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Assign. Vérifie que decision.assetName vaut "door_red.png". |
| TextureAssignGesture.ReclicSurLeMemeAssetRetire (Majeur) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:94 | Recliquer avec le même asset retire la surcharge. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Remove. Vérifie que decision.cell vaut (GridPosition{2, 3}). |
| TextureAssignGesture.ClicDroitAvecOverrideRetire (Majeur) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:112 | Le clic droit retire la surcharge, indépendamment de la sélection. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Remove. Vérifie que decision.cell vaut (GridPosition{2, 3}). |
| TextureAssignGesture.ClicDroitSansOverrideIgnore (Majeur) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:129 | Le clic droit sur une case sans surcharge est sans effet. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Ignore. |
| TextureAssignGesture.ClicDroitSurCaseVideIgnore (Majeur) Source/Test/Unit/HMI/Editor/test_texture_assign_gesture.cpp:145 | Le clic droit sur une case vide est ignoré. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que decision.action vaut TextureAssignAction::Ignore. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ThumbnailGeometryTest.DimensionnementAuxFacteursUsuels (Critique) Source/Test/Unit/HMI/Editor/test_thumbnail_geometry.cpp:17 | Le dimensionnement produit la taille en pixels reels attendue. | 1. Calculer la taille en pixels pour une taille logique de 48 aux facteurs 1, 1.25, 1.5 et 2. | Vérifie que hmi::thumbnailPixelSize(48, 1.0) vaut 48. Vérifie que hmi::thumbnailPixelSize(48, 1.25) vaut 60. Vérifie que hmi::thumbnailPixelSize(48, 1.5) vaut 72. Vérifie que hmi::thumbnailPixelSize(48, 2.0) vaut 96. |
| ThumbnailGeometryTest.FacteurNonEntierNeProduitJamaisZero (Critique) Source/Test/Unit/HMI/Editor/test_thumbnail_geometry.cpp:35 | Un facteur non entier ne produit jamais de dimension nulle. | 1. Calculer la taille en pixels pour la plus petite icone (16) a 1.25 et a un facteur tres faible (0.1). | Vérifie que hmi::thumbnailPixelSize(16, 1.25) est strictement supérieur à 0. Vérifie que hmi::thumbnailPixelSize(1, 0.1) est strictement supérieur à 0. Vérifie que hmi::thumbnailPixelSize(0, 2.0) est strictement supérieur à 0. |
| ThumbnailGeometryTest.FonctionPure (Mineur) Source/Test/Unit/HMI/Editor/test_thumbnail_geometry.cpp:51 | Le dimensionnement est une fonction pure. | 1. Appeler deux fois avec les memes entrees. | Vérifie que hmi::thumbnailPixelSize(32, 1.5) vaut hmi::thumbnailPixelSize(32, 1.5). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TileTaxonomy.ChaqueTypeFigureExactementUneFois (Majeur) Source/Test/Unit/HMI/Editor/test_tile_taxonomy.cpp:47 | Chaque type de tuile figure exactement une fois dans la taxonomie. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que types.size() vaut TILE_TYPE_COUNT. Vérifie que unique.size() vaut types.size(). Vérifie que unique.size() vaut TILE_TYPE_COUNT. |
| TileTaxonomy.ChaqueEntreeAUnLibelle (Majeur) Source/Test/Unit/HMI/Editor/test_tile_taxonomy.cpp:69 | Chaque catégorie, sous-groupe et tuile de la taxonomie porte un libellé non vide. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que category.label.empty() est faux. Vérifie que entry.label.empty() est faux. Vérifie que subgroup.label.empty() est faux. Vérifie que entry.label.empty() est faux. |
| TileTaxonomy.ChaqueLibelleEstTraduitDansLesDeuxCatalogues (Majeur) Source/Test/Unit/HMI/Editor/test_tile_taxonomy.cpp:96 | Chaque libelle de la palette est traduit dans les deux catalogues livres. | 1. Charger fr.lang puis en.lang. 2. Resoudre la cle de chaque categorie et de chaque tuile de la taxonomie. | Vérifie que localization.loadDefaultLanguage(language) est vrai. Vérifie que categoryKey.empty() est faux. Vérifie que localization.text(categoryKey) diffère de categoryKey. Vérifie que key.empty() est faux. Vérifie que localization.text(key) diffère de key. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| FrameRateAverageTest.SansEchantillonLaCadenceVautZero (Critique) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:33 | Sans echantillon, la cadence moyenne vaut zero. | 1. Construire une moyenne glissante neuve. 2. Lire la cadence. | Vérifie que average.framesPerSecond() vaut 0.0f (comparaison flottante). |
| FrameRateAverageTest.CadenceStableConvergeVersLInverseDeLaDureeDImage (Critique) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:47 | Une cadence stable converge vers l'inverse de la duree d'image. | 1. Ajouter de nombreux echantillons de 1/60 seconde. 2. Lire la cadence moyenne. | Vérifie que average.framesPerSecond() vaut 60.0f, à 0.5f près. |
| FrameRateAverageTest.MoyenneExacteSurUneSuiteDeDureesConnues (Majeur) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:66 | La moyenne glissante est exacte sur une suite de durees connues. | 1. Ajouter trois echantillons de 0,1 seconde (0,3s < fenetre). 2. Lire la cadence. | Vérifie que average.framesPerSecond() vaut 10.0f, à 1e-3f près. |
| FrameRateAverageTest.RafaleAncienneSortDeLaFenetre (Majeur) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:85 | Une rafale ancienne sort de la fenetre et n'influence plus la moyenne. | 1. Ajouter une image tres lente (1 seconde). 2. Ajouter ensuite de nombreuses images rapides (1/120 seconde) jusqu'a largement depasser la fenetre. | Vérifie que average.framesPerSecond() vaut 120.0f, à 1.0f près. |
| FrameRateAverageTest.ResetOublieTousLesEchantillons (Majeur) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:105 | reset oublie tous les echantillons accumules. | 1. Ajouter des echantillons. 2. Appeler reset. 3. Lire la cadence. | Vérifie que average.framesPerSecond() est strictement supérieur à 0.0f. Vérifie que average.framesPerSecond() vaut 0.0f (comparaison flottante). |
| FrameRateAverageTest.DureeNulleOuNegativeEstIgnoree (Mineur) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:126 | Une duree nulle ou negative est ignoree. | 1. Ajouter un echantillon negatif puis nul sur une moyenne neuve. | Vérifie que average.framesPerSecond() vaut 0.0f (comparaison flottante). |
| DiagnosticsHudTest.MesuresConnuesProduisentLesQuatreLignesAttendues (Critique) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:142 | Des valeurs mesurees produisent les quatre lignes attendues. | 1. Composer les lignes a partir de mesures connues. | Vérifie que lines.size() vaut 4u. Vérifie que lines[0] vaut "Images/s : 59.6". Vérifie que lines[1] vaut "Primitives : 128 composees / 96 soumises". Vérifie que lines[2] vaut "Passes : 5". Vérifie que lines[3] vaut "Pas de simulation : 1". |
| DiagnosticsHudTest.AucuneImageMesureeProduitDesLignesValides (Majeur) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:172 | Aucune image mesuree produit des lignes valides. | 1. Composer les lignes a partir de mesures toutes nulles (etat de depart). | Vérifie que lines.size() vaut 4u. Vérifie que lines[0] vaut "Images/s : 0.0". Vérifie que lines[1] vaut "Primitives : 0 composees / 0 soumises". Vérifie que lines[2] vaut "Passes : 0". Vérifie que lines[3] vaut "Pas de simulation : 0". |
| DiagnosticsHudTest.ClesDeTraductionExistentDansLesDeuxCatalogues (Majeur) Source/Test/Unit/HMI/Game/test_diagnostics_hud.cpp:195 | Les cles de traduction du compteur existent dans les deux catalogues livres. | 1. Charger fr.lang puis en.lang depuis les catalogues livres. 2. Resoudre les cles du compteur de diagnostic. | Vérifie que localization.loadDefaultLanguage(language) est vrai. Vérifie que localization.text(key) diffère de key. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| GameEventsTest.InterrupteurBasculeProduitSwitchToggled (Critique) Source/Test/Unit/HMI/Game/test_game_events.cpp:30 | Un interrupteur bascule produit l'evenement SwitchToggled. | 1. Un mecanisme non continu passe de ferme a ouvert. | Vérifie que events.size() vaut 1U. Vérifie que events[0] vaut GameEvent::SwitchToggled. |
| GameEventsTest.PlaquePresseeProduitPressurePlatePressed (Critique) Source/Test/Unit/HMI/Game/test_game_events.cpp:49 | Une plaque de pression enfoncee produit PressurePlatePressed. | 1. Un mecanisme continu passe de ferme a ouvert. | Vérifie que events.size() vaut 1U. Vérifie que events[0] vaut GameEvent::PressurePlatePressed. |
| GameEventsTest.PlaqueRelacheeProduitPressurePlateReleased (Majeur) Source/Test/Unit/HMI/Game/test_game_events.cpp:68 | Une plaque de pression relachee produit PressurePlateReleased. | 1. Un mecanisme continu passe d'ouvert a ferme. | Vérifie que events.size() vaut 1U. Vérifie que events[0] vaut GameEvent::PressurePlateReleased. |
| GameEventsTest.MecanismeStableNeProduitRien (Majeur) Source/Test/Unit/HMI/Game/test_game_events.cpp:87 | Un mecanisme stable ne produit aucun evenement. | 1. previous et current identiques pour un jeu de mecanismes. | Vérifie que hmi::detectMechanismEvents(state, state, continuous).empty() est vrai. |
| GameEventsTest.SeulLeMecanismeQuiChangeProduitUnEvenement (Majeur) Source/Test/Unit/HMI/Game/test_game_events.cpp:103 | Un seul mecanisme sur plusieurs qui change produit un seul evenement. | 1. Trois mecanismes, un seul change d'etat. | Vérifie que events.size() vaut 1U. Vérifie que events[0] vaut GameEvent::SwitchToggled. |
| GameEventsTest.TaillesIncoherentesNIgnorentSansPlanter (Mineur) Source/Test/Unit/HMI/Game/test_game_events.cpp:122 | Des vecteurs de tailles differentes ne provoquent aucun acces hors bornes. | 1. previous a 2 elements, current en a 3, isContinuous en a 2. | Vérifie que hmi::detectMechanismEvents(previous, current, continuous).empty() est vrai. |
| GameEventsTest.IssueEnCoursNeProduitRien (Majeur) Source/Test/Unit/HMI/Game/test_game_events.cpp:139 | Une partie en cours ne produit aucun evenement d'issue. | 1. Traduire core::LevelOutcome::Playing. | Vérifie que hmi::detectOutcomeEvent(core::LevelOutcome::Playing) vaut std::nullopt. |
| GameEventsTest.IssueGagneeProduitExitReached (Critique) Source/Test/Unit/HMI/Game/test_game_events.cpp:152 | Une issue gagnee produit l'evenement ExitReached. | 1. Traduire core::LevelOutcome::Won. | Vérifie que hmi::detectOutcomeEvent(core::LevelOutcome::Won) vaut GameEvent::ExitReached. |
| GameEventsTest.IssuePerdueProduitDied (Critique) Source/Test/Unit/HMI/Game/test_game_events.cpp:165 | Une issue perdue produit l'evenement Died. | 1. Traduire core::LevelOutcome::Lost. | Vérifie que hmi::detectOutcomeEvent(core::LevelOutcome::Lost) vaut GameEvent::Died. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| GameHudTest.HorsContexteSeulLeNomDuTableauEstAffiche (Critique) Source/Test/Unit/HMI/Game/test_game_hud.cpp:34 | Le HUD n'affiche que le nom du tableau hors contexte particulier. | 1. Composer le HUD d'un tableau, sans contact avec une cle. | Vérifie que lines.size() vaut 1u. Vérifie que lines[0] vaut "Promenade". |
| GameHudTest.ClesDeTraductionExistentDansLesDeuxCatalogues (Majeur) Source/Test/Unit/HMI/Game/test_game_hud.cpp:51 | Les cles de traduction du HUD existent dans les deux catalogues livres. | 1. Charger fr.lang puis en.lang depuis les catalogues livres. 2. Resoudre les cles du HUD. | Vérifie que localization.loadDefaultLanguage(language) est vrai. Vérifie que localization.text("hud.interact_prompt") diffère de "hud.interact_prompt". |
| GameHudTest.InviteInteragirSeulementAuContactDUneCle (Majeur) Source/Test/Unit/HMI/Game/test_game_hud.cpp:77 | L'invite Interagir n'apparait qu'au contact d'une cle non ramassee, en premiere ligne du HUD. | 1. Composer le HUD hors contact d'une cle. 2. Le composer au contact d'une cle non ramassee. | Vérifie que sansCle.size() vaut 1u. Vérifie que sansCle[0] vaut "Cle". Vérifie que surUneCle.size() vaut 2u. Vérifie que surUneCle[0] vaut "Interagir pour ramasser". Vérifie que surUneCle[1] vaut "Cle". |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ModeDeJeuTest.OrdreAppeleIdentiqueALOrdreAnnonce (Majeur) Source/Test/Unit/HMI/Game/test_game_mode.cpp:98 | L'ordre des passes appele est celui annonce. | 1. Avancer le mode d'exploration d'un pas fixe sur des passes qui enregistrent leurs appels. 2. Comparer la sequence enregistree a passOrder(). | Vérifie que outcome vaut core::LevelOutcome::Playing. Vérifie que passes.calls() vaut announcedOrder(mode). |
| ModeDeJeuTest.SequenceStableSur600Pas (Majeur) Source/Test/Unit/HMI/Game/test_game_mode.cpp:119 | 600 pas produisent 600 fois la meme sequence de passes. | 1. Avancer le mode de 600 pas fixes, avec une intention qui change a chaque pas. 2. Comparer la sequence de chaque pas a celle du premier. | Vérifie que passes.calls() vaut expected. |
| ModeDeJeuTest.EchecDeclencheSesConsequencesApresLEvaluation (Majeur) Source/Test/Unit/HMI/Game/test_game_mode.cpp:144 | Un echec declenche ses consequences apres l'evaluation. | 1. Avancer le mode d'un pas sur des passes qui repondent Lost a l'evaluation. | Vérifie que outcome vaut core::LevelOutcome::Lost. Vérifie que passes.calls().size() est supérieur ou égal à 2u. Vérifie que passes.calls().back() vaut "onLevelLost". Vérifie que passes.calls()[passes.calls().size() - 2] vaut "evaluateOutcome". |
| ModeDeJeuTest.ReussiteNeDeclenchePasLesConsequencesDUnEchec (Majeur) Source/Test/Unit/HMI/Game/test_game_mode.cpp:166 | Une reussite ne declenche pas les consequences d'un echec. | 1. Avancer le mode d'un pas sur des passes qui repondent Won a l'evaluation. | Vérifie que outcome vaut core::LevelOutcome::Won. Vérifie que passes.calls() vaut announcedOrder(mode). |
| ModeDeJeuTest.ModeSansEtatEtNomme (Mineur) Source/Test/Unit/HMI/Game/test_game_mode.cpp:186 | Le mode d'exploration est sans etat et se nomme. | 1. Charger puis decharger le mode. | Vérifie que passes.calls().empty() est vrai. Vérifie que mode.name() vaut "exploration". |
| ModeDeJeuTest.LeModeCombatGeleLeMonde (?) Source/Test/Unit/HMI/Game/test_game_mode.cpp:207 | Le mode combat gele le monde. cat Unitaire · Mode de jeu crit Critique etapes 1. Avancer le mode combat d'un pas fixe sur des passes qui enregistrent leurs appels. 2. Comparer la sequence a passOrder(). 3. Verifier l'absence des passes d'exploration. attendu moveCharacter, updateMechanisms, detectEvents et evaluateOutcome ne sont jamais appeles, et l'issue rendue est Playing. | Vérifie que passes.calls() vaut announcedOrder(mode). Vérifie que issue vaut core::LevelOutcome::Playing. Vérifie que std::ranges::find(passes.calls(), gelee) vaut passes.calls().end(). | |
| ModeDeJeuTest.LeModeCombatEstNommeEtSansEtat (?) Source/Test/Unit/HMI/Game/test_game_mode.cpp:235 | Le mode combat est nomme et sans etat. cat Unitaire · Mode de jeu crit Mineur etapes 1. Avancer deux instances distinctes du mode d'un meme pas. attendu Les deux produisent la meme sequence, et le mode porte un nom distinct de l'exploration. | Vérifie que premier.name() vaut "combat". Vérifie que premier.name() diffère de hmi::ExplorationMode{}.name(). Vérifie que passesA.calls() vaut passesB.calls(). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AnimatedTilesTest.SkinAnimeProduitDesRegionsDifferentesAuFilDesPas (Majeur) Source/Test/Unit/HMI/Graphics/test_animated_tiles.cpp:66 | Un skin animé produit des régions différentes au fil des pas, sur un même rang. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first.x diffère de second.x. Vérifie que first.y vaut second.y. |
| AnimatedTilesTest.SkinNonAnimeProduitUneRegionConstante (Majeur) Source/Test/Unit/HMI/Graphics/test_animated_tiles.cpp:94 | Un skin non animé produit une région constante d'un appel à l'autre. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first.region.x vaut 0. Vérifie que first.region.x vaut second.region.x. Vérifie que first.region.width vaut TILE. |
| AnimatedTilesTest.SkinAnimeUtiliseLaRegionCouranteDeAnimatedFrame (Majeur) Source/Test/Unit/HMI/Graphics/test_animated_tiles.cpp:134 | Un skin animé utilise la région de l'image courante, pas la planche entière. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que appearance.region.x vaut currentFrame.x. Vérifie que appearance.region.width vaut TILE. |
| AnimatedTilesTest.MiseEnPhaseDeuxTuilesDuMemeTypeAffichentLaMemeImageAuMemePas (Critique) Source/Test/Unit/HMI/Graphics/test_animated_tiles.cpp:169 | Deux tuiles du même asset affichent la même image à chaque pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que regionOne.x vaut regionTwo.x. Vérifie que tileOne.frameIndex vaut tileTwo.frameIndex. |
| AnimatedTilesTest.Bitmask16ExclutLAnimation (Majeur) Source/Test/Unit/HMI/Graphics/test_animated_tiles.cpp:201 | Le mode à raccords automatiques exclut l'animation. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::animationExcludedForTile(hmi::SkinMode::Bitmask16, core::TileType::Solid) est vrai. |
| AnimatedTilesTest.SingleSansSilhouetteNExclutPasLAnimation (Majeur) Source/Test/Unit/HMI/Graphics/test_animated_tiles.cpp:216 | Une tuile pleine en mode image simple n'exclut pas l'animation. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::animationExcludedForTile(hmi::SkinMode::Single, core::TileType::Solid) est faux. Vérifie que hmi::animationExcludedForTile(hmi::SkinMode::Single, core::TileType::Block) est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AnimationCatalogTest.RoundTripClipsMultiplesDureeParDefautEtOneShot (Critique) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:31 | Un descripteur valide se relit intégralement, durée par défaut et clip suivant compris. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que description.frameWidth vaut 16. Vérifie que description.frameHeight vaut 16. Vérifie que description.clips.clipCount() vaut 3. Vérifie que closed.frames vaut (std::vector<int>{0}). Vérifie que closed.endMode vaut core::ClipEndMode::Loop. Vérifie que closed.frameDuration vaut hmi::AnimationCatalog::DEFAULT_FRAME_DURATION_SECONDS (comparaison flottante). Vérifie que opening.frames vaut (std::vector<int>{1, 2, 3, 4}). Vérifie que opening.frameDuration vaut 0.06f (comparaison flottante). Vérifie que opening.endMode vaut core::ClipEndMode::OneShot. Vérifie que opening.nextClip vaut "open". Vérifie que description.clips.indexOf(opening.nextClip) est supérieur ou égal à 0. |
| AnimationCatalogTest.JsonInvalideEstUneErreurExploitable (Majeur) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:69 | Un JSON invalide donne une erreur d'analyse avec un message exploitable. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::AnimationCatalogError::ParseError. Vérifie que result.error.empty() est faux. |
| AnimationCatalogTest.VersionInconnueEstRefusee (Majeur) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:87 | Une version de format inconnue est refusée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::AnimationCatalogError::UnsupportedVersion. |
| AnimationCatalogTest.ClipSuivantInexistantEstRefuse (Critique) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:108 | Un clip suivant inexistant est refusé au chargement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::AnimationCatalogError::MalformedStructure. |
| AnimationCatalogTest.IndiceDImageNegatifEstRefuse (Majeur) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:130 | Un indice d'image négatif est refusé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::AnimationCatalogError::MalformedStructure. |
| AnimationCatalogTest.ClipSansFramesEstRefuse (Majeur) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:151 | Un clip sans images est refusé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::AnimationCatalogError::MalformedStructure. |
| AnimationCatalogTest.FichierAbsentEstFileNotFoundSansException (Critique) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:172 | Un fichier absent donne un code dédié, sans exception. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::AnimationCatalogError::FileNotFound. |
| AnimationCatalogTest.DescriptorFileNameRemplaceLExtension (Critique) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:190 | Le nom du descripteur remplace l'extension en conservant le chemin. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::AnimationCatalog::descriptorFileName("water.png") vaut "water.anim.json". Vérifie que hmi::AnimationCatalog::descriptorFileName("Skins/lava.png") vaut "Skins/lava.anim.json". |
| AnimationCatalogTest.CoherenceAvecLePngValideeSurSpritesheetAUnRang (Majeur) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:205 | Un descripteur cohérent avec les dimensions du PNG est validé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que valid.valid est vrai. |
| AnimationCatalogTest.TailleDImageIncoherenteAvecLePngEstRefusee (Majeur) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:227 | Des dimensions de PNG incohérentes avec l'image sont refusées. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que wrongHeight.valid est faux. Vérifie que wrongHeight.message.empty() est faux. Vérifie que wrongWidth.valid est faux. |
| AnimationCatalogTest.IndiceDImageHorsBornesDeLaSpritesheetReelleEstRefuse (Critique) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:255 | Un indice d'image hors des bornes réelles de la spritesheet est refusé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que tooShort.valid est faux. Vérifie que tooShort.message.empty() est faux. |
| AnimationCatalogTest.FrameRegionPremiereEtDerniereImageSpritesheetAUnRang (Majeur) Source/Test/Unit/HMI/Graphics/test_animation_catalog.cpp:279 | La région d'une image se déduit de son indice par décalage horizontal, ordonnée constante. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first.x vaut 0. Vérifie que first.y vaut 0. Vérifie que first.width vaut 16. Vérifie que first.height vaut 16. Vérifie que last.x vaut 5 * 16. Vérifie que last.y vaut 0. Vérifie que last.width vaut 16. Vérifie que last.height vaut 16. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AssetContractTest.SkinDeTuileConformeAccepte (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:25 | Un skin de tuile de 16x16 px est accepte. | 1. Valider un asset de la famille « skin de tuile » aux dimensions d'une case. | Vérifie que validation.valid est vrai. Vérifie que validation.message.empty() est vrai. |
| AssetContractTest.SkinDeTuileNonConformeRefuseAvecMessage (Critique) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:44 | Un skin de tuile non conforme est refuse avec un message exploitable. | 1. Valider un skin de tuile de 24x16 px. 2. Inspecter le message d'erreur. | Vérifie que validation.valid est faux. Vérifie que contains(validation.message, "mur.png") est vrai. Vérifie que contains(validation.message, "24x16") est vrai. Vérifie que contains(validation.message, "16x16") est vrai. |
| AssetContractTest.SkinDeTuileAnimeSpritesheetHorizontaleAcceptee (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:65 | Une spritesheet animee (plusieurs cases de large, une case de haut) est acceptee. | 1. Valider un skin de tuile de 64x16 px (4 images). | Vérifie que validation.valid est vrai. |
| AssetContractTest.SkinDeTuileSurPlusieursRangsRefuse (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:84 | Une image sur plusieurs rangs (hauteur non conforme) est refusee. | 1. Valider un skin de tuile de 16x32 px. | Vérifie que validation.valid est faux. |
| AssetContractTest.PlancheARaccordsExigeQuatreCasesMinimum (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:102 | Une planche a raccords exige un multiple de case et au moins 4x4 cases. | 1. Valider une planche 4x4 cases, puis 3x4 cases, puis un multiple rompu. | Vérifie que hmi::validateAsset(hmi::AssetFamily::AutotileSheet, "sol.png", 4 * TILE, 4 * TILE).valid est vrai. Vérifie que hmi::validateAsset(hmi::AssetFamily::AutotileSheet, "sol.png", 3 * TILE, 4 * TILE).valid est faux. Vérifie que hmi::validateAsset(hmi::AssetFamily::AutotileSheet, "sol.png", 4 * TILE + 1, 4 * TILE) .valid est faux. |
| AssetContractTest.FondDeNiveauSansContrainteDeGrille (Mineur) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:124 | Un fond de niveau accepte toute dimension strictement positive. | 1. Valider un fond aux dimensions quelconques, puis un fond de largeur nulle. | Vérifie que hmi::validateAsset(hmi::AssetFamily::Background, "foret.png", 640, 361).valid est vrai. Vérifie que hmi::validateAsset(hmi::AssetFamily::Background, "foret.png", 0, 361).valid est faux. |
| AssetContractTest.SpritesheetPersonnageMultipleDeCase (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:138 | Une spritesheet de personnage doit se decouper en cases entieres. | 1. Valider une spritesheet multiple de la case, puis une spritesheet decalee. | Vérifie que hmi::validateAsset(hmi::AssetFamily::CharacterSheet, "heros.png", 5 * TILE, 3 * TILE) .valid est vrai. Vérifie que hmi::validateAsset(hmi::AssetFamily::CharacterSheet, "heros.png", 5 * TILE, 3 * TILE + 7) .valid est faux. |
| AssetContractTest.AtlasLivreConforme (Critique) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:159 | L'atlas historique reste conforme au contrat de sa famille. | 1. Valider les dimensions de la grille d'atlas livree. | Vérifie que hmi::validateAsset(hmi::AssetFamily::Atlas, "atlas.png", gridSide, gridSide + 2 * hmi::TextureAtlas::PLAYER_FRAME_SIZE) .valid est vrai. |
| AssetContractTest.ToutesLesFamillesSontNommees (Mineur) Source/Test/Unit/HMI/Graphics/test_asset_contract.cpp:176 | Chaque famille d'asset porte un nom lisible non vide. | 1. Nommer chaque famille declaree. | Vérifie que name.empty() est faux. Vérifie que name diffère de "Inconnu". |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AssetPathsTest.FichierExistantResolu (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_paths.cpp:45 | Un fichier existant dans le dossier d'assets est résolu vers son chemin complet. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que resolved.has_value() est vrai. Vérifie que *resolved vaut filePath. |
| AssetPathsTest.AssetAbsentSignaleSansException (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_paths.cpp:68 | Un asset absent est signalé par std::nullopt, sans exception. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que assetPaths.resolve("introuvable.png") vaut std::nullopt. |
| AssetPathsTest.DossierInexistantSansException (Majeur) Source/Test/Unit/HMI/Graphics/test_asset_paths.cpp:86 | Un dossier d'assets inexistant est traité comme rien à résoudre. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que assetPaths.resolve("atlas.png") vaut std::nullopt. |
| AssetPathsTest.DossierNestPasUnAssetValide (Mineur) Source/Test/Unit/HMI/Graphics/test_asset_paths.cpp:103 | Un chemin désignant un dossier n'est pas résolu comme un asset. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que assetPaths.resolve("sous-dossier") vaut std::nullopt. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| BackgroundFitTest.MemeRatioAucunRecadrage (Majeur) Source/Test/Unit/HMI/Graphics/test_background_fit.cpp:25 | Meme ratio : aucun recadrage. | 1. Calculer le recadrage d'une image carree sur une cible carree. | Vérifie que fit.u0 vaut 0.0f (comparaison flottante). Vérifie que fit.v0 vaut 0.0f (comparaison flottante). Vérifie que fit.u1 vaut 1.0f (comparaison flottante). Vérifie que fit.v1 vaut 1.0f (comparaison flottante). |
| BackgroundFitTest.ImagePlusLargeRecadreeHorizontalementEtCentree (Critique) Source/Test/Unit/HMI/Graphics/test_background_fit.cpp:44 | Image plus large que la cible : recadrage horizontal centre. | 1. Calculer le recadrage d'une image 16:9 sur une cible carree. | Vérifie que fit.v0 vaut 0.0f (comparaison flottante). Vérifie que fit.v1 vaut 1.0f (comparaison flottante). Vérifie que fit.u0 est strictement supérieur à 0.0f. Vérifie que fit.u1 est strictement inférieur à 1.0f. Vérifie que fit.u0 vaut 1.0f - fit.u1 (comparaison flottante). Vérifie que fit.u1 - fit.u0 vaut 9.0f / 16.0f, à 1e-4f près. |
| BackgroundFitTest.ImagePlusHauteRecadreeVerticalementEtCentree (Critique) Source/Test/Unit/HMI/Graphics/test_background_fit.cpp:67 | Image plus haute que la cible : recadrage vertical centre. | 1. Calculer le recadrage d'une image 9:16 sur une cible carree. | Vérifie que fit.u0 vaut 0.0f (comparaison flottante). Vérifie que fit.u1 vaut 1.0f (comparaison flottante). Vérifie que fit.v0 est strictement supérieur à 0.0f. Vérifie que fit.v1 est strictement inférieur à 1.0f. Vérifie que fit.v0 vaut 1.0f - fit.v1 (comparaison flottante). Vérifie que fit.v1 - fit.v0 vaut 9.0f / 16.0f, à 1e-4f près. |
| BackgroundFitTest.SansFondDesigneAucunQuadCompose (Critique) Source/Test/Unit/HMI/Graphics/test_background_fit.cpp:88 | Sans fond designe, aucun quad n'est compose. | 1. Composer une scene sans texture de fond, en mode Texture. | Vérifie que scene.size() vaut 0u. |
| BackgroundFitTest.FondResoluEmetUnQuadSurLesBornesDuNiveau (Critique) Source/Test/Unit/HMI/Graphics/test_background_fit.cpp:105 | Fond designe et resolu : quad emis sur Background, bornes du niveau. | 1. Composer une scene avec une texture de fond resolue, en mode Texture. | Vérifie que recorder.size() vaut 1u. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Background) vaut 1. Vérifie que recorder.containsSpriteAt(0.0f, 0.0f) est vrai. Vérifie que quad.sprite.width vaut 20.0f (comparaison flottante). Vérifie que quad.sprite.height vaut 12.0f (comparaison flottante). |
| BackgroundFitTest.ModePhysiqueAucunQuadDeFond (Critique) Source/Test/Unit/HMI/Graphics/test_background_fit.cpp:132 | Mode Physique : aucun quad de fond, meme fond resolu. | 1. Composer la meme scene qu'en mode Texture, mais en mode Physique. | Vérifie que scene.size() vaut 0u. |
| BackgroundFitTest.RepliEnDamierEmetUnQuadCommeUnFondValide (Majeur) Source/Test/Unit/HMI/Graphics/test_background_fit.cpp:152 | Repli en damier : meme composition qu'un fond valide. | 1. Composer une scene avec une texture de repli (damier), en mode Texture. | Vérifie que scene.size() vaut 1u. Vérifie que scene.statistics().submitted vaut 1. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| BitmapFontTest.MesureChaineVideLargeurNulle (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:33 | La mesure d'une chaîne vide donne une largeur nulle et une hauteur d'une ligne. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que extent.width vaut 0.0f (comparaison flottante). Vérifie que extent.height vaut static_cast<float>(font.metrics.lineHeight) (comparaison flottante). |
| BitmapFontTest.MesureUnCaractere (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:51 | La mesure d'un seul caractère donne exactement son avance. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que glyphA diffère de nullptr. Vérifie que extent.width vaut static_cast<float>(glyphA->advance) (comparaison flottante). Vérifie que extent.height vaut static_cast<float>(font.metrics.lineHeight) (comparaison flottante). |
| BitmapFontTest.MesureChaineAccentueeParPointsDeCode (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:71 | Une chaîne accentuée est mesurée par points de code, pas par octets UTF-8. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que glyphE diffère de nullptr. Vérifie que extent.width vaut static_cast<float>(glyphE->advance) * 6.0f (comparaison flottante). |
| BitmapFontTest.CaractereAbsentEstSubstitue (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:94 | Un caractère absent de la police est substitué par le glyphe de remplacement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que substituted diffère de nullptr. Vérifie que replacement diffère de nullptr. Vérifie que substituted->x vaut replacement->x. Vérifie que substituted->y vaut replacement->y. |
| BitmapFontTest.MetriquesJsonValideEstLue (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:115 | Un fichier de métriques JSON valide se lit correctement (champs et glyphes). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que result.metrics->lineHeight vaut 10. Vérifie que result.metrics->replacementCodePoint vaut U'?'. Vérifie que glyphB diffère de nullptr. Vérifie que glyphB->x vaut 6. Vérifie que glyphB->y vaut 0. Vérifie que glyphB->width vaut 6. Vérifie que glyphB->height vaut 10. Vérifie que glyphB->advance vaut 6. |
| BitmapFontTest.JsonInvalideEstUneErreurExploitable (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:141 | Un JSON de métriques malformé est une erreur exploitable, jamais une exception. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::FontMetricsError::ParseError. Vérifie que result.error.empty() est faux. |
| BitmapFontTest.VersionInconnueEstRefusee (Mineur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:159 | Une version de format supérieure à celle gérée est refusée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::FontMetricsError::UnsupportedVersion. |
| BitmapFontTest.FichierMetriquesAbsentEstFileNotFound (Mineur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:179 | Un fichier de métriques absent est un échec FileNotFound, sans exception. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::FontMetricsError::FileNotFound. |
| BitmapFontTest.MetriquesCoherentesAvecLePngValidees (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:196 | Des métriques cohérentes avec les dimensions du PNG sont validées. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que valid.valid est vrai. |
| BitmapFontTest.MetriquesIncoherentesAvecLePngRefusees (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:215 | Des métriques dont un glyphe déborde des dimensions du PNG sont refusées. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que invalid.valid est faux. Vérifie que invalid.message.find("font.png") diffère de std::string::npos. |
| BitmapFontTest.ReplitProceduralCouvreAsciiEtAccentsDeFaconDeterministe (Critique) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:236 | Le repli procédural couvre l'ASCII imprimable et les accents français, de façon déterministe. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first.image.width vaut second.image.width. Vérifie que first.image.height vaut second.image.height. Vérifie que first.image.pixels vaut second.image.pixels. Vérifie que first.metrics.glyphs.size() vaut second.metrics.glyphs.size(). Vérifie que first.metrics.glyph(codePoint) diffère de nullptr. Vérifie que first.metrics.glyph(codePoint) diffère de nullptr. |
| BitmapFontTest.ReplitProceduralEstAutoCoherent (Majeur) Source/Test/Unit/HMI/Graphics/test_bitmap_font.cpp:274 | Chaque glyphe procédural désigne une région entièrement contenue dans l'image générée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que coherence.valid est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CacheRegistryTest.ChargeUneSeuleFoisPourUneCleRepetee (Critique) Source/Test/Unit/HMI/Graphics/test_cache_registry.cpp:43 | Une clé demandée deux fois n'est chargée qu'une fois et rend la même entrée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first diffère de nullptr. Vérifie que second diffère de nullptr. Vérifie que *first vaut 42. Vérifie que second vaut first. Vérifie que loader.callCount() vaut 1. |
| CacheRegistryTest.InvalidateForceLeRechargementDeLaCleSeule (Critique) Source/Test/Unit/HMI/Graphics/test_cache_registry.cpp:68 | invalidate ne force le rechargement que de la clé visée, pas des autres. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que loaderA.callCount() vaut 2. Vérifie que loaderB.callCount() vaut 1. |
| CacheRegistryTest.InvalidateAllViseTout (Critique) Source/Test/Unit/HMI/Graphics/test_cache_registry.cpp:95 | invalidateAll vide le registre et fait relire toutes les clés. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que registry.size() vaut 2U. Vérifie que registry.size() vaut 0U. Vérifie que loaderA.callCount() vaut 2. Vérifie que loaderB.callCount() vaut 2. |
| CacheRegistryTest.UnEchecEstMemoriseSansRetenterLeChargement (Critique) Source/Test/Unit/HMI/Graphics/test_cache_registry.cpp:123 | Un échec de chargement est mémorisé : la clé absente n'est pas relue. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first vaut nullptr. Vérifie que second vaut nullptr. Vérifie que loader.callCount() vaut 1. |
| CacheRegistryTest.InvalidateSurUnEchecPermetUnNouvelEssai (Critique) Source/Test/Unit/HMI/Graphics/test_cache_registry.cpp:146 | Invalider une clé en échec autorise un nouvel essai, qui peut réussir. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result diffère de nullptr. Vérifie que *result vaut 7. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| Camera2DTest.CentreAuMilieuDeLEcran (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:25 | Le centre de la caméra se projette au centre de l'écran. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que screen.x vaut WIDTH * 0.5f, à TOLERANCE près. Vérifie que screen.y vaut HEIGHT * 0.5f, à TOLERANCE près. |
| Camera2DTest.CenterEtZoomRenvoientLesValeursPosees (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:45 | center() et zoom() renvoient exactement les valeurs posées. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que camera.center().x vaut 3.0f (comparaison flottante). Vérifie que camera.center().y vaut 4.0f (comparaison flottante). Vérifie que camera.zoom() vaut 2.5f (comparaison flottante). |
| Camera2DTest.EchelleEtAxeY (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:64 | Une unité monde vaut 16 pixels ; l'axe Y va vers le bas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que right.x vaut WIDTH * 0.5f + 16.0f, à TOLERANCE près. Vérifie que right.y vaut HEIGHT * 0.5f, à TOLERANCE près. Vérifie que down.y vaut HEIGHT * 0.5f + 16.0f, à TOLERANCE près. |
| Camera2DTest.Zoom (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:86 | Le zoom multiplie l'échelle en pixels. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que right.x vaut WIDTH * 0.5f + 32.0f, à TOLERANCE près. |
| Camera2DTest.ConversionsReciproques (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:104 | screenToWorld est la réciproque de worldToScreen. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que roundTrip.x vaut world.x, à TOLERANCE près. Vérifie que roundTrip.y vaut world.y, à TOLERANCE près. |
| Camera2DTest.ProjectionCentreVersOrigineClip (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:125 | La matrice de projection envoie le centre de la caméra à l'origine du clip space. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.x vaut 0.0f, à TOLERANCE près. Vérifie que result.y vaut 0.0f, à TOLERANCE près. Vérifie que result.w vaut 1.0f, à TOLERANCE près. |
| Camera2DTest.BordEcranVersBordClip (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:152 | Un coin de l'écran correspond à un bord du clip space (±1). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.x vaut 1.0f, à TOLERANCE près. |
| Camera2DTest.FitZoomEntierPourPetitNiveau (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:176 | fitZoom reste entier tant que le facteur brut est supérieur ou égal à 1 (petit niveau). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que zoom est supérieur ou égal à 1.0f. Vérifie que zoom vaut std::floor(zoom) (comparaison flottante). |
| Camera2DTest.FitZoomFractionnairePourGrandNiveau (Majeur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:195 | fitZoom devient fractionnaire pour un niveau plus grand que la surface disponible. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que zoom est strictement supérieur à 0.0f. Vérifie que zoom est strictement inférieur à 1.0f. Vérifie que 100.0f * hmi::Camera2D::PIXELS_PER_UNIT * zoom est inférieur ou égal à 1280.0f + TOLERANCE. Vérifie que 100.0f * hmi::Camera2D::PIXELS_PER_UNIT * zoom est inférieur ou égal à 720.0f + TOLERANCE. |
| Camera2DTest.FitZoomAppliqueLaMarge (Mineur) Source/Test/Unit/HMI/Graphics/test_camera2d.cpp:216 | fitZoom applique la marge avant l'arrondi. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que zoomSansMarge vaut 5.0f (comparaison flottante). Vérifie que zoomAvecMarge vaut 4.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CameraZonesTest.PositionDansUneZoneUniqueRenvoieSonIndice (Critique) Source/Test/Unit/HMI/Graphics/test_camera_zones.cpp:21 | Une position dans une zone unique renvoie son indice. | 1. Construire une liste avec une seule zone. 2. Résoudre une position à l'intérieur. | Vérifie que result.has_value() est vrai. Vérifie que *result vaut 0u. |
| CameraZonesTest.PositionHorsDeToutesLesZonesNeRenvoieRien (Critique) Source/Test/Unit/HMI/Graphics/test_camera_zones.cpp:39 | Une position hors de toutes les zones ne renvoie aucun indice. | 1. Construire une liste de zones qui ne couvre pas toute la grille. 2. Résoudre une position dans le trou. | Vérifie que result.has_value() est faux. |
| CameraZonesTest.BornesInclusivesHautGaucheExclusivesBasDroit (Majeur) Source/Test/Unit/HMI/Graphics/test_camera_zones.cpp:58 | Les bornes d'une zone sont inclusives haut-gauche, exclusives bas-droit. | 1. Construire une zone de 5x5 à l'origine. 2. Résoudre sa case d'origine, puis la case juste après son bord droit/bas. | Vérifie que hmi::activeCameraZoneIndex(zones, GridPosition{0, 0}).has_value() est vrai. Vérifie que hmi::activeCameraZoneIndex(zones, GridPosition{4, 4}).has_value() est vrai. Vérifie que hmi::activeCameraZoneIndex(zones, GridPosition{5, 4}).has_value() est faux. Vérifie que hmi::activeCameraZoneIndex(zones, GridPosition{4, 5}).has_value() est faux. |
| CameraZonesTest.ZonesChevauchantesLaPremiereDeLaListeGagne (Majeur) Source/Test/Unit/HMI/Graphics/test_camera_zones.cpp:77 | Deux zones chevauchantes : la première zone de la liste gagne. | 1. Construire deux zones qui se chevauchent. 2. Résoudre une position dans le chevauchement. 3. Inverser l'ordre des deux zones et répéter. | Vérifie que resultA.has_value() est vrai. Vérifie que *resultA vaut 0u. Vérifie que resultB.has_value() est vrai. Vérifie que *resultB vaut 0u. |
| CameraZonesTest.ListeDeZonesVideNeRenvoieRien (Mineur) Source/Test/Unit/HMI/Graphics/test_camera_zones.cpp:103 | Une liste de zones vide ne renvoie jamais d'indice. | 1. Résoudre une position avec une liste de zones vide. | Vérifie que hmi::activeCameraZoneIndex({}, GridPosition{0, 0}).has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TriParProfondeurTest.TroisPrimitivesSortentParPiedCroissant (Critique) Source/Test/Unit/HMI/Graphics/test_depth_sort.cpp:73 | Trois primitives a Y croissants sortent dans l'ordre de leur pied. | 1. Composer trois primitives de la bande de profondeur, dans le desordre, avec deux textures differentes. 2. Trier la scene. | Vérifie que scene.size() vaut 3u. Vérifie que scene.quads()[0].sprite.x vaut 1.0f (comparaison flottante). Vérifie que scene.quads()[1].sprite.x vaut 2.0f (comparaison flottante). Vérifie que scene.quads()[2].sprite.x vaut 0.0f (comparaison flottante). |
| TriParProfondeurTest.PersonnageEntreDeuxObjets (Critique) Source/Test/Unit/HMI/Graphics/test_depth_sort.cpp:100 | Le personnage passe derriere un objet plus bas et devant un objet plus haut. | 1. Composer un arbre au-dessus du personnage, le personnage, puis un arbre en dessous. 2. Trier. | Vérifie que scene.size() vaut 3u. Vérifie que scene.quads()[0].layer vaut hmi::RenderLayer::Object. Vérifie que scene.quads()[1].layer vaut hmi::RenderLayer::Player. Vérifie que scene.quads()[2].layer vaut hmi::RenderLayer::Object. Vérifie que scene.quads()[2].sprite.x vaut 2.0f (comparaison flottante). |
| TriParProfondeurTest.PiedEgalConserveLOrdreDeComposition (Critique) Source/Test/Unit/HMI/Graphics/test_depth_sort.cpp:128 | A pied egal, l'ordre de composition est preserve : aucun scintillement. | 1. Composer trois primitives de meme pied, a des positions differentes. 2. Trier. 3. Recomposer et retrier a l'identique. | Vérifie que first vaut second. Vérifie que first.size() vaut 3u. Vérifie que first[0] vaut 3.0f (comparaison flottante). |
| TriParProfondeurTest.QuantificationAuPixel (Majeur) Source/Test/Unit/HMI/Graphics/test_depth_sort.cpp:164 | Un ecart inferieur au pixel ne departage pas deux profondeurs. | 1. Calculer l'ordre de deux pieds distants d'un centieme d'unite. 2. Le comparer a celui de deux pieds distants d'une demi-unite. | Vérifie que hmi::depthSortOrder(4.0f) vaut hmi::depthSortOrder(4.01f). Vérifie que hmi::depthSortOrder(4.0f) est strictement inférieur à hmi::depthSortOrder(4.5f). Vérifie que hmi::depthSortOrder(1.0f) est strictement inférieur à hmi::depthSortOrder(9.0f). |
| TriParProfondeurTest.LaProfondeurNeDebordePasDeSaBande (Critique) Source/Test/Unit/HMI/Graphics/test_depth_sort.cpp:182 | La profondeur ne deborde pas de sa bande. | 1. Composer une tuile, un objet tres bas, un plan de premier plan tres haut. 2. Trier. | Vérifie que scene.size() vaut 3u. Vérifie que scene.quads()[0].layer vaut hmi::RenderLayer::Tile. Vérifie que scene.quads()[1].layer vaut hmi::RenderLayer::Object. Vérifie que scene.quads()[2].layer vaut hmi::RenderLayer::Foreground. Vérifie que recorder.isLayerOrderRespected() est vrai. |
| TriParProfondeurTest.CompositionAlimenteLaProfondeurDepuisLePied (Critique) Source/Test/Unit/HMI/Graphics/test_depth_sort.cpp:213 | La composition alimente l'ordre de profondeur depuis le pied du quad. | 1. Peupler un monde d'un objet haut et d'un personnage bas, poses sur la meme ligne. 2. Composer depuis l'ECS et trier. | Vérifie que scene.size() vaut 2u. Vérifie que scene.quads()[0].sortOrder vaut hmi::depthSortOrder(4.0f). Vérifie que scene.quads()[1].sortOrder vaut hmi::depthSortOrder(4.0f). |
| TriParProfondeurTest.HorsBandeLeTriFinResteCeluiDeLaCouche (Majeur) Source/Test/Unit/HMI/Graphics/test_depth_sort.cpp:241 | Hors bande de profondeur, le tri fin reste celui de Sprite::layer. | 1. Peupler un monde de deux tuiles de rangs de couche differents, la seconde plus basse. 2. Composer et trier. | Vérifie que scene.size() vaut 2u. Vérifie que scene.quads()[0].sortOrder vaut 0. Vérifie que scene.quads()[1].sortOrder vaut 1. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| FollowCameraTest.PremierAppelDemarreSurLePersonnage (Majeur) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:37 | Le premier appel démarre la caméra sur le personnage. | 1. Avancer un état non initialisé pour un personnage loin des bords. 2. Vérifier le centre résultant. | Vérifie que result.initialized est vrai. Vérifie que result.center.x vaut characterPosition.x (comparaison flottante). Vérifie que result.center.y vaut characterPosition.y (comparaison flottante). |
| FollowCameraTest.ZoneMorteImmobiliseLaCameraTantQueLePersonnageYReste (Critique) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:59 | La zone morte immobilise la caméra tant que le personnage y reste. | 1. Initialiser la caméra sur le personnage. 2. Déplacer le personnage d'une distance inférieure à la zone morte. 3. Le déplacer d'une distance qui en sort. | Vérifie que state.anchor.x vaut anchorAfterInit.x (comparaison flottante). Vérifie que state.anchor.y vaut anchorAfterInit.y (comparaison flottante). Vérifie que state.anchor.x diffère de anchorAfterInit.x. |
| FollowCameraTest.BornageEmpecheDeMontrerHorsDesLimitesSurLesQuatreBords (Critique) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:91 | Le bornage empêche de montrer hors des limites du niveau, sur les quatre bords. | 1. Amener le personnage successivement dans chaque coin du niveau. 2. Avancer suffisamment de pas pour que la caméra rattrape sa cible. | Vérifie que state.center.x est supérieur ou égal à LARGE_LEVEL.position.x + VIEW_HALF_EXTENT.x - 1e-3f. Vérifie que state.center.x est inférieur ou égal à LARGE_LEVEL.position.x + LARGE_LEVEL.size.x - VIEW_HALF_EXTENT.x + 1e-3f. Vérifie que state.center.y est supérieur ou égal à LARGE_LEVEL.position.y + VIEW_HALF_EXTENT.y - 1e-3f. Vérifie que state.center.y est inférieur ou égal à LARGE_LEVEL.position.y + LARGE_LEVEL.size.y - VIEW_HALF_EXTENT.y + 1e-3f. |
| FollowCameraTest.NiveauPlusEtroitQueLeCadrageCentreLaCameraSurCetAxe (Majeur) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:123 | Un axe plus étroit que le cadrage centre la caméra, sans la coller à un bord. | 1. Construire un niveau plus étroit que le cadrage sur l'axe horizontal. 2. Amener le personnage tout contre le bord gauche puis avancer suffisamment de pas. | Vérifie que state.center.x vaut narrowLevel.size.x * 0.5f, à 1e-3f près. |
| FollowCameraTest.AnticipationSInverseProgressivementSansDiscontinuite (Majeur) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:145 | L'anticipation s'inverse progressivement, sans discontinuité. | 1. Avancer de nombreux pas vers la droite (anticipation proche de +1). 2. Inverser le sens d'un seul pas. | Vérifie que state.anticipation.x est strictement supérieur à 0.9f. Vérifie que afterReversal.anticipation.x est strictement inférieur à state.anticipation.x. Vérifie que afterReversal.anticipation.x est strictement supérieur à 0.0f. |
| FollowCameraTest.ArretConserveLaDerniereAnticipation (Mineur) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:173 | À l'arrêt, l'anticipation conserve sa dernière valeur. | 1. Établir une anticipation vers la droite. 2. Avancer un pas avec un sens nul (personnage immobile). | Vérifie que stopped.anticipation.x vaut anticipationBeforeStop (comparaison flottante). |
| FollowCameraTest.MemesEntreesMemeTrajectoire (Majeur) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:198 | Mêmes entrées, même trajectoire de caméra. | 1. Rejouer deux fois la même séquence de positions depuis un état vierge. 2. Comparer les états finaux. | Vérifie que first.center.x vaut second.center.x (comparaison flottante). Vérifie que first.center.y vaut second.center.y (comparaison flottante). Vérifie que first.anticipation.x vaut second.anticipation.x (comparaison flottante). |
| FollowCameraTest.SuiviIsotropeSurLesDeuxAxes (Majeur) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:231 | Le suivi est isotrope : haut, bas, gauche et droite se valent. | 1. Faire marcher le personnage vers la droite sur 60 pas, camera suivie. 2. Recommencer vers le bas. | Vérifie que versLeBas est strictement supérieur à 0.0f. Vérifie que versLeBas vaut parcourir(RIGHT), à 1e-4f près. |
| FollowCameraTest.AnticipationVerticale (Majeur) Source/Test/Unit/HMI/Graphics/test_follow_camera.cpp:267 | L'anticipation suit la marche verticale, pas seulement l'horizontale. | 1. Faire marcher le personnage vers le haut, sans bouger, sur 60 pas. | Vérifie que state.anticipation.y est strictement inférieur à -0.9f. Vérifie que state.anticipation.x vaut 0.0f, à 1e-5f près. Vérifie que state.center.y est strictement inférieur à position.y. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ImageEncode.AllerRetourExactAlphaCompris (Critique) Source/Test/Unit/HMI/Graphics/test_image_encode.cpp:76 | Encoder puis decoder une image restitue exactement les memes pixels, alpha compris. | 1. Encoder une image 2x2 couvrant plusieurs niveaux d'alpha vers un fichier PNG. 2. Decoder ce fichier. | Vérifie que hmi::encodeImageFile(path, original) est vrai. Vérifie que decoded.has_value() est vrai. Vérifie que decoded->width vaut original.width. Vérifie que decoded->height vaut original.height. Vérifie que decoded->pixels vaut original.pixels. |
| ImageEncode.DossierInexistantEchoueProprement (Majeur) Source/Test/Unit/HMI/Graphics/test_image_encode.cpp:101 | Encoder vers un dossier inexistant echoue proprement, sans exception. | 1. Tenter d'encoder une image vers un chemin dont le dossier parent n'existe pas. | EXPECT_NO_THROW(result = hmi::encodeImageFile(path, original)) Vérifie que result est faux. |
| ImageEncode.DimensionsIncoherentesEchouentProprement (Majeur) Source/Test/Unit/HMI/Graphics/test_image_encode.cpp:120 | Encoder une image aux dimensions incoherentes echoue proprement. | 1. Construire une image dont le nombre de pixels ne correspond pas a largeur*hauteur. 2. Tenter de l'encoder. | EXPECT_NO_THROW(result = hmi::encodeImageFile(path, broken)) Vérifie que result est faux. Vérifie que fileCount() vaut 0U. |
| ImageEncode.AucunFichierTemporaireApresSucces (Majeur) Source/Test/Unit/HMI/Graphics/test_image_encode.cpp:143 | Aucun fichier temporaire ne subsiste apres un encodage reussi. | 1. Encoder une image vers un fichier. 2. Lister le dossier de destination. | Vérifie que hmi::encodeImageFile(dir / "asset.png", sampleImage()) est vrai. Vérifie que fileCount() vaut 1U. Vérifie que std::filesystem::exists(dir / "asset.png") est vrai. |
| ImageEncode.EcrasementAtomiqueSansResidu (Majeur) Source/Test/Unit/HMI/Graphics/test_image_encode.cpp:161 | Enregistrer par-dessus un asset existant remplace son contenu sans residu. | 1. Encoder une premiere image vers un fichier. 2. Encoder une seconde image differente vers le meme fichier. 3. Decoder le fichier et lister le dossier. | Vérifie que hmi::encodeImageFile(path, sampleImage()) est vrai. Vérifie que hmi::encodeImageFile(path, second) est vrai. Vérifie que decoded.has_value() est vrai. Vérifie que decoded->width vaut 1. Vérifie que decoded->height vaut 1. Vérifie que fileCount() vaut 1U. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LayerVisibilityTest.TousLesCalquesSontVisiblesParDefaut (Critique) Source/Test/Unit/HMI/Graphics/test_layer_visibility.cpp:75 | Tous les calques sont visibles par defaut. | 1. Construire un jeu de visibilités par defaut. 2. Interroger chaque calque. | Vérifie que visibility.visible(hmi::RenderLayer::Background) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Plane) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Shadow) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Tile) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Object) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Player) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Foreground) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::UI) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::EditorOverlay) est vrai. |
| LayerVisibilityTest.MasquerUnCalqueNeChangeQueCeCalque (Critique) Source/Test/Unit/HMI/Graphics/test_layer_visibility.cpp:98 | Masquer un calque ne change que ce calque. | 1. Masquer le calque Plans. 2. Interroger Plans et Personnage. | Vérifie que visibility.visible(hmi::RenderLayer::Plane) est faux. Vérifie que visibility.visible(hmi::RenderLayer::Player) est vrai. |
| LayerVisibilityTest.ShowAllRetablitTousLesCalques (Majeur) Source/Test/Unit/HMI/Graphics/test_layer_visibility.cpp:115 | showAll retablit tous les calques. | 1. Masquer plusieurs calques. 2. Appeler showAll. | Vérifie que visibility.visible(hmi::RenderLayer::Background) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Player) est vrai. Vérifie que visibility.visible(hmi::RenderLayer::Foreground) est vrai. |
| LayerVisibilityTest.CalqueMasqueNEmetAucunePrimitiveLesAutresInchanges (Critique) Source/Test/Unit/HMI/Graphics/test_layer_visibility.cpp:138 | Un calque masque n'emet aucune primitive ; les autres sont inchanges. | 1. Peupler une entite Personnage et une entite Tuile. 2. Masquer Personnage et composer en mode Texture. | Vérifie que recorder.countOnLayer(hmi::RenderLayer::Player) vaut 0. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Tile) vaut 1. |
| LayerVisibilityTest.CombinaisonsDeuxUnSeulAucun (Critique) Source/Test/Unit/HMI/Graphics/test_layer_visibility.cpp:167 | Combinaisons de visibilite : deux, un seul, aucun. | 1. Peupler une Tuile et un Personnage. 2. Composer en mode Texture avec les deux visibles, puis un seul, puis aucun. | Vérifie que scene.size() vaut 2u. Vérifie que scene.size() vaut 1u. Vérifie que scene.quads().front().layer vaut hmi::RenderLayer::Tile. Vérifie que scene.size() vaut 0u. |
| LayerVisibilityTest.DefautNeutreSurLaCompositionDUneScene (Critique) Source/Test/Unit/HMI/Graphics/test_layer_visibility.cpp:214 | Un jeu de visibilite par defaut est neutre sur la composition. | 1. Peupler une tuile et un personnage. 2. Composer avec et sans jeu de visibilites explicite, en mode Texture. | Vérifie que withoutVisibility.size() vaut withDefaultVisibility.size(). Vérifie que withoutVisibility.size() vaut 2u. |
test_mechanism_transitions.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MechanismTransitionsTest.PremierCalculRejointEtatCibleSansTransition (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_transitions.cpp:74 | Le premier calcul rejoint l'état cible sans jouer de transition. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que state.animation.clips->clipAt(state.animation.clipIndex).name vaut MECHANISM_CLIP_DOOR_OPEN. |
| MechanismTransitionsTest.ChangementDetatDeclencheLaTransitionUneSeuleFois (Critique) Source/Test/Unit/HMI/Graphics/test_mechanism_transitions.cpp:98 | Un changement d'état déclenche la transition une seule fois, puis la laisse aboutir. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que state.animation.clips->clipAt(state.animation.clipIndex).name vaut MECHANISM_CLIP_DOOR_CLOSED. Vérifie que state.animation.clips->clipAt(state.animation.clipIndex).name vaut MECHANISM_CLIP_DOOR_OPENING. Vérifie que state.animation.clips->clipAt(state.animation.clipIndex).name vaut MECHANISM_CLIP_DOOR_OPEN. |
| MechanismTransitionsTest.ClipDeTransitionAbsentBasculeDirectementSansAvertissement (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_transitions.cpp:134 | Un clip de transition absent fait basculer directement, sans avertissement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que state.animation.clips->clipAt(state.animation.clipIndex).name vaut MECHANISM_CLIP_DOOR_OPEN. Vérifie que warned.empty() est vrai. |
| MechanismTransitionsTest.ClipDEtatAbsentReplieEtJournaliseUneSeuleFois (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_transitions.cpp:169 | Un clip d'état absent se replie et n'est journalisé qu'une fois par asset. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que warned.size() vaut 1u. Vérifie que warned.size() vaut 1u. |
| MechanismTransitionsTest.AucunChangementNeReinitialisePasLimageEnCours (Critique) Source/Test/Unit/HMI/Graphics/test_mechanism_transitions.cpp:200 | À état inchangé, un appel supplémentaire ne réinitialise pas l'image en cours. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que state.animation.clips->clipAt(state.animation.clipIndex).name vaut MECHANISM_CLIP_DOOR_OPENING. Vérifie que state.animation.frameIndex vaut 1. Vérifie que state.animation.frameIndex vaut 1. |
| MechanismTransitionsTest.SeuleLaPorteTransitionneLesAutresBasculentDirectement (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_transitions.cpp:231 | Un interrupteur bascule directement entre ses deux états, sans avertissement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que state.animation.clips->clipAt(state.animation.clipIndex).name vaut MECHANISM_CLIP_SWITCH_ACTIVE. Vérifie que warned.empty() est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MechanismVisualsTest.DoorTargetClips (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:17 | La porte demande le clip fermé ou ouvert selon son état logique. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismTargetClip(core::TileType::Door, false) vaut MECHANISM_CLIP_DOOR_CLOSED. Vérifie que mechanismTargetClip(core::TileType::Door, true) vaut MECHANISM_CLIP_DOOR_OPEN. |
| MechanismVisualsTest.SwitchTargetClips (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:31 | L'interrupteur demande le clip inactif ou actif selon son état. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismTargetClip(core::TileType::Switch, false) vaut MECHANISM_CLIP_SWITCH_INACTIVE. Vérifie que mechanismTargetClip(core::TileType::Switch, true) vaut MECHANISM_CLIP_SWITCH_ACTIVE. |
| MechanismVisualsTest.PressurePlateTargetClips (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:45 | La plaque de pression demande le clip relâché ou enfoncé selon son état. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismTargetClip(core::TileType::PressurePlate, false) vaut MECHANISM_CLIP_PLATE_RELEASED. Vérifie que mechanismTargetClip(core::TileType::PressurePlate, true) vaut MECHANISM_CLIP_PLATE_PRESSED. |
| MechanismVisualsTest.KeyTargetClips (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:62 | La clé demande le clip présente ou ramassée selon son état. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismTargetClip(core::TileType::Key, false) vaut MECHANISM_CLIP_KEY_PRESENT. Vérifie que mechanismTargetClip(core::TileType::Key, true) vaut MECHANISM_CLIP_KEY_COLLECTED. |
| MechanismVisualsTest.LockedDoorTargetClips (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:77 | La porte verrouillée demande le clip fermée ou ouverte selon son état. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismTargetClip(core::TileType::LockedDoor, false) vaut MECHANISM_CLIP_LOCKED_DOOR_CLOSED. Vérifie que mechanismTargetClip(core::TileType::LockedDoor, true) vaut MECHANISM_CLIP_LOCKED_DOOR_OPEN. |
| MechanismVisualsTest.StatelessTileProducesNoClipRequest (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:94 | Une tuile sans état ne demande aucun clip et n'est pas un mécanisme. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismTargetClip(core::TileType::Solid, false).has_value() est faux. Vérifie que mechanismTargetClip(core::TileType::Block, true).has_value() est faux. Vérifie que mechanismTargetClip(core::TileType::Empty, false).has_value() est faux. Vérifie que isStatefulMechanism(core::TileType::Solid) est faux. Vérifie que isStatefulMechanism(core::TileType::Block) est faux. |
| MechanismVisualsTest.DoorTransitionsOnStateChangeOnly (Critique) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:113 | La porte ne demande une transition que sur un changement d'état. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que opening.has_value() est vrai. Vérifie que *opening vaut MECHANISM_CLIP_DOOR_OPENING. Vérifie que closing.has_value() est vrai. Vérifie que *closing vaut MECHANISM_CLIP_DOOR_CLOSING. Vérifie que mechanismTransitionClip(core::TileType::Door, true, true).has_value() est faux. Vérifie que mechanismTransitionClip(core::TileType::Door, false, false).has_value() est faux. |
| MechanismVisualsTest.TextureModeAlwaysFullyOpaque (Critique) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:136 | En mode Texture, l'opacité de diagnostic vaut toujours 1. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismDiagnosticAlpha(RenderMode::Texture, true, 0.25f, 1.0f) vaut 1.0f (comparaison flottante). Vérifie que mechanismDiagnosticAlpha(RenderMode::Texture, false, 0.25f, 1.0f) vaut 1.0f (comparaison flottante). |
| MechanismVisualsTest.PhysiqueModeUsesTheProvidedAlphaPair (Majeur) Source/Test/Unit/HMI/Graphics/test_mechanism_visuals.cpp:152 | En mode Physique, la paire d'opacités fournie est utilisée dans les deux sens. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mechanismDiagnosticAlpha(RenderMode::Physique, true, 0.25f, 1.0f) vaut 0.25f (comparaison flottante). Vérifie que mechanismDiagnosticAlpha(RenderMode::Physique, false, 0.25f, 1.0f) vaut 1.0f (comparaison flottante). Vérifie que mechanismDiagnosticAlpha(RenderMode::Physique, true, 1.0f, 0.35f) vaut 1.0f (comparaison flottante). Vérifie que mechanismDiagnosticAlpha(RenderMode::Physique, false, 1.0f, 0.35f) vaut 0.35f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| MissingTextureTest.DimensionsAttendues (Majeur) Source/Test/Unit/HMI/Graphics/test_missing_texture.cpp:30 | Le damier genere a les dimensions demandees. | 1. Generer le damier par defaut, puis un damier de 32 px. | Vérifie que image.width vaut hmi::MISSING_TEXTURE_SIZE. Vérifie que image.height vaut hmi::MISSING_TEXTURE_SIZE. Vérifie que image.pixels.size() vaut static_cast<std::size_t>(image.width) * static_cast<std::size_t>(image.height). Vérifie que large.width vaut 32. Vérifie que large.height vaut 32. |
| MissingTextureTest.GenerationDeterministe (Majeur) Source/Test/Unit/HMI/Graphics/test_missing_texture.cpp:52 | La generation du damier est deterministe. | 1. Generer deux fois le damier. | Vérifie que hmi::buildMissingTextureImage().pixels vaut hmi::buildMissingTextureImage().pixels. |
| MissingTextureTest.CarreauxAlternesMagentaEtNoir (Critique) Source/Test/Unit/HMI/Graphics/test_missing_texture.cpp:66 | Les carreaux du damier alternent magenta et noir. | 1. Generer le damier. 2. Lire un pixel de chacun des quatre premiers carreaux. | Vérifie que pixelAt(image, 0, 0) vaut MAGENTA. Vérifie que pixelAt(image, STEP, 0) vaut BLACK. Vérifie que pixelAt(image, 0, STEP) vaut BLACK. Vérifie que pixelAt(image, STEP, STEP) vaut MAGENTA. |
| MissingTextureTest.DamierEntierementOpaque (Critique) Source/Test/Unit/HMI/Graphics/test_missing_texture.cpp:87 | Tous les pixels du damier sont opaques. | 1. Generer le damier. 2. Verifier le canal alpha de chaque pixel. | Vérifie que pixel >> 24 vaut 0xFFu. |
| MissingTextureTest.AvertissementNommeAsset (Majeur) Source/Test/Unit/HMI/Graphics/test_missing_texture.cpp:105 | L'avertissement de texture manquante nomme l'asset attendu. | 1. Construire le message pour un asset donne. | Vérifie que message.find("Backgrounds/foret.png") diffère de std::string::npos. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ParallaxTest.FacteurUnLaissePositionInchangee (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:30 | Facteur 1 laisse la position inchangee. | 1. Calculer la position de rendu a facteur 1.0 sur les deux axes. | Vérifie que rendered.x vaut position.x (comparaison flottante). Vérifie que rendered.y vaut position.y (comparaison flottante). |
| ParallaxTest.FacteurParAxeAgitIndependamment (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:50 | Le facteur de parallaxe agit axe par axe. | 1. Calculer la position de rendu avec un facteur different sur X et sur Y. | Vérifie que rendered.x vaut 65.0f (comparaison flottante). Vérifie que rendered.y vaut position.y (comparaison flottante). |
| ParallaxTest.FacteursOpposesProduisentDesDecalagesOpposesEtProportionnels (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:71 | Des facteurs opposes autour de 1 produisent des decalages opposes. | 1. Calculer le decalage pour un facteur inferieur et un facteur superieur a 1, equidistants. | Vérifie que offsetLower vaut -offsetHigher (comparaison flottante). Vérifie que offsetLower diffère de 0.0f. |
| ParallaxTest.MemePositionRelativeDonneMemePositionEcranEntreSalles (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:98 | Meme position relative -> meme position ecran dans deux salles. | 1. Placer un point a la meme position RELATIVE dans deux salles de centres differents. 2. Comparer leurs positions de rendu, ramenees au centre de leur salle. | Vérifie que rendered1.x - room1Center.x vaut rendered2.x - room2Center.x (comparaison flottante). Vérifie que rendered1.y - room1Center.y vaut rendered2.y - room2Center.y (comparaison flottante). |
| ParallaxTest.ParallaxModelPositionEstLInverseDeParallaxRenderPosition (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:127 | parallaxModelPosition est l'inverse de parallaxRenderPosition. | 1. Convertir une position modele en position de rendu, puis revenir. | Vérifie que back.x vaut model.x (comparaison flottante). Vérifie que back.y vaut model.y (comparaison flottante). |
| ParallaxTest.DecalageBorneLaisseLePlanCouvrantAuBordDuNiveau (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:152 | Un plan borne couvre toujours le cadrage, camera au bord du niveau. | 1. Placer la camera contre le bord droit d'un niveau et calculer le decalage d'un plan a facteur 0,1. 2. Borner ce decalage. | Vérifie que rendered.x - origin.x diffère de clamped.x. Vérifie que left est inférieur ou égal à camera.position.x. Vérifie que left + plane.size.x est supérieur ou égal à camera.position.x + camera.size.x. Vérifie que top est inférieur ou égal à camera.position.y. Vérifie que top + plane.size.y est supérieur ou égal à camera.position.y + camera.size.y. |
| ParallaxTest.PlanPlusPetitQueLeCadrageNEstPasDecale (Majeur) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:186 | Un plan plus petit que le cadrage n'est pas decale. | 1. Borner un decalage pour un plan plus petit que le cadrage. | Vérifie que clamped.x vaut 0.0f (comparaison flottante). Vérifie que clamped.y vaut 0.0f (comparaison flottante). |
| ParallaxTest.RoundToScreenPixelArrondiAuPixelEcran (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:206 | roundToScreenPixel arrondit au pixel ecran le plus proche. | 1. Arrondir une position fractionnaire a une echelle de 16 px par unite. 2. Recommencer a echelle nulle. | Vérifie que rounded.x * SCALE vaut std::round(1.03f * SCALE) (comparaison flottante). Vérifie que rounded.y * SCALE vaut std::round(-2.97f * SCALE) (comparaison flottante). Vérifie que untouched.x vaut 1.03f (comparaison flottante). Vérifie que untouched.y vaut -2.97f (comparaison flottante). |
| ParallaxTest.TableDActivationExhaustive (Critique) Source/Test/Unit/HMI/Graphics/test_parallax.cpp:235 | La table d'activation de la parallaxe est exhaustive. | 1. Interroger planeParallaxActive pour les trois modes de cadrage, drapeau actif puis inactif. | Vérifie que hmi::planeParallaxActive(CameraFramingMode::Follow, true) est vrai. Vérifie que hmi::planeParallaxActive(CameraFramingMode::PerRoom, true) est vrai. Vérifie que hmi::planeParallaxActive(CameraFramingMode::WholeLevel, true) est faux. Vérifie que hmi::planeParallaxActive(CameraFramingMode::Follow, false) est faux. Vérifie que hmi::planeParallaxActive(CameraFramingMode::PerRoom, false) est faux. Vérifie que hmi::planeParallaxActive(CameraFramingMode::WholeLevel, false) est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ParticleRenderTest.UneParticuleUnQuadCentreOpaciteProportionnelle (Critique) Source/Test/Unit/HMI/Graphics/test_particle_render.cpp:45 | Une particule -> un quad centré, opacité = life/maxLife. | 1. Peupler une particule à mi-vie (life = maxLife / 2). 2. Composer en mode Texture. | Vérifie que recorder.size() vaut 1u. Vérifie que quad.sprite.x vaut 3.0f - hmi::PARTICLE_QUAD_SIZE * 0.5f (comparaison flottante). Vérifie que quad.sprite.y vaut 2.0f - hmi::PARTICLE_QUAD_SIZE * 0.5f (comparaison flottante). Vérifie que quad.sprite.width vaut hmi::PARTICLE_QUAD_SIZE (comparaison flottante). Vérifie que quad.sprite.height vaut hmi::PARTICLE_QUAD_SIZE (comparaison flottante). Vérifie que quad.sprite.a vaut 0.5f (comparaison flottante). |
| ParticleRenderTest.CalqueSelonLEffet (Critique) Source/Test/Unit/HMI/Graphics/test_particle_render.cpp:75 | Calque selon l'effet : Object pour le dash, Foreground pour le reste. | 1. Peupler une particule de chaque type. 2. Composer en mode Texture. | Vérifie que recorder.size() vaut 3u. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Object) vaut 1. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Foreground) vaut 2. |
| ParticleRenderTest.ModePhysiqueAucunQuad (Critique) Source/Test/Unit/HMI/Graphics/test_particle_render.cpp:101 | Mode Physique : aucun quad de particule. | 1. Peupler une particule vivante. 2. Composer en mode Physique. | Vérifie que scene.size() vaut 0u. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PlaneRenderTest.QuatrePlansRessortentDansLOrdreDuNiveau (Critique) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:73 | Quatre plans ressortent dans l'ordre du niveau apres tri. | 1. Composer quatre plans d'un meme calque, chacun avec sa propre texture. 2. Trier la scene, puis lire l'ordre des textures liees. | Vérifie que scene.quads().size() vaut 4u. Vérifie que scene.quads()[rank].texture vaut planeTexture(static_cast<int>(rank)).texture. |
| PlaneRenderTest.ProfondeurChoisitLeCalque (Critique) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:96 | La profondeur d'un plan choisit son calque de rendu. | 1. Projeter les deux profondeurs sur leur calque. 2. Composer un plan de chaque profondeur. | Vérifie que hmi::planeRenderLayer(PlaneDepth::Behind) vaut hmi::RenderLayer::Plane. Vérifie que hmi::planeRenderLayer(PlaneDepth::Front) vaut hmi::RenderLayer::Foreground. Vérifie que hmi::RenderLayer::Plane est strictement inférieur à hmi::RenderLayer::Tile. Vérifie que hmi::RenderLayer::Player est strictement inférieur à hmi::RenderLayer::Foreground. Vérifie que scene.quads().size() vaut 2u. Vérifie que scene.quads()[0].layer vaut hmi::RenderLayer::Plane. Vérifie que scene.quads()[1].layer vaut hmi::RenderLayer::Foreground. |
| PlaneRenderTest.QuadCouvreLeNiveauQuelleQueSoitLaDensite (Critique) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:131 | Un plan couvre les bornes du niveau, densite comprise. | 1. Composer un plan a densite native, puis le meme a densite 8. 2. Comparer les deux quads. | Vérifie que natif.quads().size() vaut 1u. Vérifie que reduit.quads().size() vaut 1u. Vérifie que first.x vaut 0.0f (comparaison flottante). Vérifie que first.y vaut 0.0f (comparaison flottante). Vérifie que first.width vaut static_cast<float>(LEVEL_WIDTH) (comparaison flottante). Vérifie que first.height vaut static_cast<float>(LEVEL_HEIGHT) (comparaison flottante). Vérifie que first.u0 vaut 0.0f (comparaison flottante). Vérifie que first.v0 vaut 0.0f (comparaison flottante). Vérifie que first.u1 vaut 1.0f (comparaison flottante). Vérifie que first.v1 vaut 1.0f (comparaison flottante). Vérifie que second.x vaut first.x (comparaison flottante). Vérifie que second.y vaut first.y (comparaison flottante). Vérifie que second.width vaut first.width (comparaison flottante). Vérifie que second.height vaut first.height (comparaison flottante). Vérifie que second.u1 vaut first.u1 (comparaison flottante). Vérifie que second.v1 vaut first.v1 (comparaison flottante). |
| PlaneRenderTest.OpaciteDevientAlphaDuQuad (Majeur) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:174 | L'opacite d'un plan devient l'alpha de son quad. | 1. Composer un plan a opacite 0,5 et un plan a opacite hors bornes. | Vérifie que scene.quads().size() vaut 2u. Vérifie que scene.quads()[0].sprite.a vaut 0.5f (comparaison flottante). Vérifie que scene.quads()[1].sprite.a vaut 1.0f (comparaison flottante). |
| PlaneRenderTest.RienNEstComposeEnModePhysique (Critique) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:198 | Aucun plan n'est compose en mode Physique. | 1. Composer trois plans en mode Physique. | Vérifie que scene.size() vaut 0u. |
| PlaneRenderTest.PlanMasqueOuIsoleNEmetRien (Critique) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:215 | Masquage et isolement d'un plan. | 1. Masquer un plan sur trois et composer. 2. Isoler un plan et composer. 3. Tout reafficher et composer. | Vérifie que scene.quads().size() vaut 2u. Vérifie que scene.quads()[0].texture vaut planeTexture(0).texture. Vérifie que scene.quads()[1].texture vaut planeTexture(2).texture. Vérifie que scene.quads().size() vaut 1u. Vérifie que scene.quads()[0].texture vaut planeTexture(1).texture. Vérifie que scene.size() vaut 3u. |
| PlaneRenderTest.PlanSansTextureNEmetRien (Majeur) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:259 | Un plan sans texture resolue n'emet aucun quad. | 1. Composer trois plans dont celui du milieu sans texture. | Vérifie que scene.quads().size() vaut 2u. Vérifie que scene.quads()[0].texture vaut planeTexture(0).texture. Vérifie que scene.quads()[1].texture vaut planeTexture(2).texture. |
| PlaneRenderTest.CoutConstantEnTailleDeNiveau (Majeur) Source/Test/Unit/HMI/Graphics/test_plane_render.cpp:283 | Le cout d'un plan ne depend pas de la taille du niveau. | 1. Composer quatre plans sur un niveau, puis sur un niveau deux fois plus grand. | Vérifie que petit.size() vaut grand.size(). Vérifie que petit.batchCount() vaut grand.batchCount(). Vérifie que grand.batchCount() vaut 4. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PlayerSpriteTest.AncrageImageDeMemeTailleQueLaHitbox (Majeur) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:34 | Image de la taille de la hitbox : quad sans decalage. | 1. Calculer le quad pour une image 16x16 px (1x1 unite) et une hitbox 1x1 unite. | Vérifie que quad.size.x vaut 1.0f (comparaison flottante). Vérifie que quad.size.y vaut 1.0f (comparaison flottante). Vérifie que quad.offset.x vaut 0.0f (comparaison flottante). Vérifie que quad.offset.y vaut 0.0f (comparaison flottante). |
| PlayerSpriteTest.ImagePlusGrandeCentreeEtAncreeParLeBas (Critique) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:56 | Image plus grande que la hitbox : centree horizontalement, alignee par le bas. | 1. Calculer le quad pour une image 32x32 px et la hitbox reelle du personnage (core::playerSize()). | Vérifie que quad.size.x vaut imageWidthWorld (comparaison flottante). Vérifie que quad.size.y vaut imageHeightWorld (comparaison flottante). Vérifie que quad.offset.x vaut (hitboxSize.x - imageWidthWorld) * 0.5f (comparaison flottante). Vérifie que quad.offset.x est strictement inférieur à 0.0f. Vérifie que quad.offset.y + quad.size.y vaut hitboxSize.y (comparaison flottante). |
| PlayerSpriteTest.ImagePlusGrandeNeDeplacePasLaHitbox (Critique) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:83 | Le calcul du quad ne modifie jamais la hitbox (fonction pure). | 1. Calculer le quad pour plusieurs tailles d'image, avec la meme hitbox. | Vérifie que small.size.x diffère de large.size.x. Vérifie que hitboxSize.x vaut core::playerSize().x. Vérifie que hitboxSize.y vaut core::playerSize().y. |
| PlayerSpriteTest.AncrageHorizontalSymetrique (Majeur) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:109 | L'ancrage horizontal est symetrique (prealable au retournement). | 1. Calculer le quad d'une image plus large que la hitbox. | Vérifie que overflowLeft vaut overflowRight (comparaison flottante). |
| PlayerSpriteTest.ClipDeclareUtiliseTelQuel (Majeur) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:128 | Un clip declare est utilise tel quel. | 1. Resoudre "run" dans un jeu qui le declare. | Vérifie que hmi::resolveDeclaredPlayerClip(declared, "fall") vaut "fall". |
| PlayerSpriteTest.ClipsLot48RepliSurLAtlasProcedural (Critique) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:142 | Chute/atterrissage/glissade/dash retombent sur le clip le plus proche. | 1. Resoudre fall/land/wallslide/dash dans le jeu procedural (idle/run/jump seulement). | Vérifie que hmi::resolveDeclaredPlayerClip(declared, "fall") vaut "jump". Vérifie que hmi::resolveDeclaredPlayerClip(declared, "land") vaut "idle". Vérifie que hmi::resolveDeclaredPlayerClip(declared, "wallslide") vaut "jump". Vérifie que hmi::resolveDeclaredPlayerClip(declared, "dash") vaut "run". |
| PlayerSpriteTest.AucunClipDeclareRetombeSurIdle (Mineur) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:161 | Aucun clip declare : repli final sur idle. | 1. Resoudre "dash" dans un jeu totalement vide. | Vérifie que hmi::resolveDeclaredPlayerClip(declared, "dash") vaut "idle". |
| PlayerSpriteTest.NomsProceduralsSontIdleRunJump (Mineur) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:176 | L'atlas procedural ne declare que idle/run/jump. | 1. Lire proceduralPlayerClipNames(). | Vérifie que hmi::proceduralPlayerClipNames() vaut expected. |
| PlayerSpriteTest.ModePhysiqueIgnoreLeTag (Critique) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:218 | RenderMode::Physique ignore PlayerSpriteTag. | 1. Composer un personnage taggue en RenderMode::Physique. | Vérifie que recorder.size() vaut 1u. Vérifie que recorder.containsSpriteAt(5.0f, 5.0f) est vrai. |
| PlayerSpriteTest.ModeTextureAppliqueLeQuadDuTag (Critique) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:247 | RenderMode::Texture applique le quad du tag. | 1. Composer un personnage taggue (quad plus grand que la hitbox) en RenderMode::Texture. | Vérifie que scene.quads().size() vaut 1u. Vérifie que quad.x vaut 5.0f - 0.5f (comparaison flottante). Vérifie que quad.y vaut 5.0f - 1.0f (comparaison flottante). Vérifie que quad.width vaut 2.0f (comparaison flottante). Vérifie que quad.height vaut 2.0f (comparaison flottante). Vérifie que scene.quads().front().texture vaut characterSheetTexture. |
| PlayerSpriteTest.ReplinProceduralLieLAtlasEnModeTexture (Majeur) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:280 | Sans spritesheet, RenderMode::Texture lie l'atlas. | 1. Composer un personnage taggue avec usesCharacterSheet=false. | Vérifie que scene.quads().size() vaut 1u. Vérifie que scene.quads().front().texture vaut atlasTexture. |
| PlayerSpriteTest.RetournementEchangeUvSansDeplacerLeQuad (Critique) Source/Test/Unit/HMI/Graphics/test_player_sprite.cpp:305 | Le retournement echange u0/u1 sans deplacer le quad. | 1. Composer le meme personnage, flipHorizontal=false puis true. | Vérifie que right.u0 vaut left.u1 (comparaison flottante). Vérifie que right.u1 vaut left.u0 (comparaison flottante). Vérifie que right.x vaut left.x (comparaison flottante). Vérifie que right.y vaut left.y (comparaison flottante). Vérifie que right.width vaut left.width (comparaison flottante). Vérifie que right.height vaut left.height (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ProceduralAtlasTest.DimensionsAttendues (Majeur) Source/Test/Unit/HMI/Graphics/test_procedural_atlas.cpp:22 | L'image générée a les dimensions attendues (grille de tuiles + lignes de personnage). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que image.width vaut gridSide. Vérifie que image.height vaut gridSide + frameRows * hmi::TextureAtlas::PLAYER_FRAME_SIZE. Vérifie que image.pixels.size() vaut static_cast<std::size_t>(image.width) * static_cast<std::size_t>(image.height). |
| ProceduralAtlasTest.GenerationDeterministe (Majeur) Source/Test/Unit/HMI/Graphics/test_procedural_atlas.cpp:48 | La génération est déterministe : deux appels produisent des pixels identiques. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que first.width vaut second.width. Vérifie que first.height vaut second.height. Vérifie que first.pixels vaut second.pixels. |
| ProceduralAtlasTest.DamierDeTransparenceDansLaDerniereTuile (Mineur) Source/Test/Unit/HMI/Graphics/test_procedural_atlas.cpp:69 | La dernière tuile de la grille contient des pixels opaques et transparents (damier). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que sawOpaque est vrai. Vérifie que sawTransparent est vrai. |
| ProceduralAtlasTest.ChaqueTypeDeTuileAUneCouleurDeRepliDistincte (Critique) Source/Test/Unit/HMI/Graphics/test_procedural_atlas.cpp:113 | Chaque type de tuile a une couleur de repli visible et distincte. | 1. Generer l'atlas procedural. 2. Echantillonner le centre de la case de chaque type de tuile, hors case vide. | Vérifie que color diffère de 0xFF000000u. Vérifie que inserted.second est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| QuadRecorderTest.CalquePrimeSurTexture (Critique) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:68 | Le calque prime sur la texture dans l'ordre de soumission. | 1. Composer un quad Player (texture A) puis un quad Tile (texture B). 2. Trier et capturer la scene. | Vérifie que recorder.size() vaut 2u. Vérifie que recorder.quads()[0].layer vaut hmi::RenderLayer::Tile. Vérifie que recorder.quads()[1].layer vaut hmi::RenderLayer::Player. Vérifie que recorder.isLayerOrderRespected() est vrai. |
| QuadRecorderTest.TroisCalquesDeuxTexturesOrdonnes (Critique) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:94 | Trois calques et deux textures : ordre des calques et groupes de texture contigus. | 1. Composer six quads en alternant calques et textures. 2. Trier et capturer. | Vérifie que recorder.isLayerOrderRespected() est vrai. Vérifie que recorder.areTextureGroupsContiguous() est vrai. Vérifie que layers.size() vaut 3u. Vérifie que layers[0] vaut hmi::RenderLayer::Background. Vérifie que layers[1] vaut hmi::RenderLayer::Tile. Vérifie que layers[2] vaut hmi::RenderLayer::Player. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Tile) vaut 3. Vérifie que recorder.countWithTexture(textureA) vaut 3. Vérifie que recorder.countWithTexture(textureB) vaut 3. |
| QuadRecorderTest.TriStableAClefEgale (Majeur) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:131 | Le tri est stable : a cle egale l'ordre de composition est preserve. | 1. Composer trois quads identiques en cle, a des positions differentes. 2. Trier. | Vérifie que scene.size() vaut 3u. Vérifie que scene.quads()[0].sprite.x vaut 3.0f (comparaison flottante). Vérifie que scene.quads()[1].sprite.x vaut 1.0f (comparaison flottante). Vérifie que scene.quads()[2].sprite.x vaut 2.0f (comparaison flottante). |
| QuadRecorderTest.TriFinParSpriteLayer (Majeur) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:155 | Le tri fin par Sprite::layer subsiste a l'interieur d'un calque. | 1. Composer trois quads du meme calque avec des tris fins decroissants. 2. Trier. | Vérifie que scene.size() vaut 3u. Vérifie que scene.quads()[0].sortOrder vaut 0. Vérifie que scene.quads()[1].sortOrder vaut 1. Vérifie que scene.quads()[2].sortOrder vaut 2. |
| QuadRecorderTest.DeuxTexturesDeuxPasses (Majeur) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:179 | Le nombre de passes egale le nombre de groupes de texture. | 1. Composer quatre quads d'un meme calque en alternant deux textures. 2. Trier. | Vérifie que scene.batchCount() vaut 2. Vérifie que recorder.textureSequence().size() vaut 2u. Vérifie que recorder.areTextureGroupsContiguous() est vrai. |
| QuadRecorderTest.RectanglesEtSegmentsMelanges (Mineur) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:206 | Segments et rectangles cohabitent dans la meme scene ordonnee. | 1. Composer un rectangle puis un segment sur le meme calque. 2. Trier et capturer. | Vérifie que scene.size() vaut 2u. Vérifie que scene.quads()[0].kind vaut hmi::QuadKind::Sprite. Vérifie que scene.quads()[1].kind vaut hmi::QuadKind::Line. |
| QuadRecorderTest.SceneDeReferenceNonRegression (Critique) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:235 | Non-regression : la scene de reference produit les primitives attendues. | 1. Peupler un monde de trois tuiles puis d'un personnage tague Player. 2. Composer la scene et la trier. 3. Capturer et inspecter la liste. | Vérifie que recorder.size() vaut 4u. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Tile) vaut 3. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Player) vaut 1. Vérifie que recorder.isLayerOrderRespected() est vrai. Vérifie que recorder.quads()[0].sprite.x vaut 0.0f (comparaison flottante). Vérifie que recorder.quads()[1].sprite.x vaut 1.0f (comparaison flottante). Vérifie que recorder.quads()[2].sprite.x vaut 2.0f (comparaison flottante). Vérifie que recorder.quads()[3].layer vaut hmi::RenderLayer::Player. Vérifie que recorder.quads()[0].sprite.width vaut 1.0f (comparaison flottante). Vérifie que recorder.quads()[3].sprite.width vaut 0.4f (comparaison flottante). Vérifie que recorder.quads()[3].sprite.height vaut 0.8f (comparaison flottante). Vérifie que recorder.quads()[3].sprite.v0 vaut 1.0f (comparaison flottante). Vérifie que recorder.statistics().batches vaut 1. Vérifie que recorder.statistics().culled vaut 0. Vérifie que recorder.statistics().submitted vaut 4. |
| QuadRecorderTest.CalqueParDefautSansTag (Majeur) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:293 | Une entite sans RenderLayerTag est composee sur le calque des tuiles. | 1. Composer un monde d'une seule entite non taguee. | Vérifie que scene.size() vaut 1u. Vérifie que scene.quads()[0].layer vaut hmi::DEFAULT_RENDER_LAYER. Vérifie que hmi::DEFAULT_RENDER_LAYER vaut hmi::RenderLayer::Tile. |
| QuadRecorderTest.OrdonnancementDeclare (Critique) Source/Test/Unit/HMI/Graphics/test_quad_recorder.cpp:315 | L'ordonnancement place le premier plan au-dessus du personnage. | 1. Comparer les valeurs declarees de l'enumeration des calques. | Vérifie que hmi::RenderLayer::Background est strictement inférieur à hmi::RenderLayer::Plane. Vérifie que hmi::RenderLayer::Plane est strictement inférieur à hmi::RenderLayer::Shadow. Vérifie que hmi::RenderLayer::Shadow est strictement inférieur à hmi::RenderLayer::Tile. Vérifie que hmi::RenderLayer::Tile est strictement inférieur à hmi::RenderLayer::Object. Vérifie que hmi::RenderLayer::Object est strictement inférieur à hmi::RenderLayer::Player. Vérifie que hmi::RenderLayer::Player est strictement inférieur à hmi::RenderLayer::Foreground. Vérifie que hmi::RenderLayer::Foreground est strictement inférieur à hmi::RenderLayer::UI. Vérifie que hmi::RenderLayer::UI est strictement inférieur à hmi::RenderLayer::EditorOverlay. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RenderBudgetTest.UnPlanDePlusSurUnNiveauAuPlafondDepasseLeBudgetDeMemoire (Critique) Source/Test/Unit/HMI/Graphics/test_render_budget.cpp:289 | Un plan de plus sur un niveau au plafond fait echouer le budget de memoire. | 1. Construire un niveau de la taille du plus grand niveau livre, charge de plans a densite native jusqu'au plafond. 2. Ajouter un plan de plus, a la meme densite. | Vérifie que perPlane est strictement supérieur à 0u. Vérifie que atCeiling est strictement supérieur à 0u. Vérifie que atCeiling est strictement inférieur à core::MAX_PLANES_PER_LEVEL. Vérifie que bytesAtCeiling est inférieur ou égal à MAX_PLANE_TEXTURE_BYTES_PER_LEVEL. Vérifie que bytesOneMore est strictement supérieur à MAX_PLANE_TEXTURE_BYTES_PER_LEVEL. |
| RenderBudgetTest.LeCoutDesPlansEstInvariantEnTailleDeNiveau (Critique) Source/Test/Unit/HMI/Graphics/test_render_budget.cpp:326 | Le cout en primitives des plans ne depend pas de la taille du niveau. | 1. Composer quatre plans sur un niveau, puis sur un niveau deux fois plus grand sur chaque axe. | Vérifie que small.considered vaut large.considered. Vérifie que small.submitted vaut large.submitted. Vérifie que small.batches vaut large.batches. Vérifie que large.textureBytes vaut small.textureBytes * 4. |
| RenderBudgetTest.ChaquePlanCouteUnePrimitiveEtUnePasseJamaisEcartee (Majeur) Source/Test/Unit/HMI/Graphics/test_render_budget.cpp:361 | N plans coutent N primitives soumises, N passes et aucune ecartee. | 1. Composer quatre plans dans une scene cadree sur une salle du niveau. | Vérifie que stats.considered vaut PLANE_COUNT. Vérifie que stats.submitted vaut PLANE_COUNT. Vérifie que stats.culled vaut 0. Vérifie que stats.batches vaut PLANE_COUNT. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RenderCullingTest.SansCadrageAucunRejet (Majeur) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:62 | Sans cadrage fixe, aucune primitive n'est ecartee. | 1. Composer un quad tres eloigne dans une scene sans cadrage. | Vérifie que scene.isCullingEnabled() est faux. Vérifie que scene.addSprite(hmi::RenderLayer::Tile, texture, 0, tileQuad(9999.0f, 9999.0f)) est vrai. Vérifie que scene.statistics().culled vaut 0. |
| RenderCullingTest.HorsCadrageEcarte (Critique) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:80 | Une primitive hors cadrage est ecartee, la meme dans le cadrage est conservee. | 1. Fixer le cadrage de reference. 2. Composer un quad dedans, puis un quad loin dehors. | Vérifie que scene.addSprite(hmi::RenderLayer::Tile, texture, 0, tileQuad(15.0f, 15.0f)) est vrai. Vérifie que scene.addSprite(hmi::RenderLayer::Tile, texture, 0, tileQuad(80.0f, 15.0f)) est faux. Vérifie que recorder.size() vaut 1u. Vérifie que recorder.containsSpriteAt(15.0f, 15.0f) est vrai. Vérifie que recorder.statistics().considered vaut 2. Vérifie que recorder.statistics().culled vaut 1. Vérifie que recorder.statistics().submitted vaut 1. |
| RenderCullingTest.AChevalSurLaFrontiereConserve (Critique) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:109 | Une primitive a cheval sur la frontiere du cadrage est conservee. | 1. Fixer le cadrage de reference. 2. Composer un quad chevauchant le bord droit, puis un quad entierement dans la marge. | Vérifie que scene.addSprite(hmi::RenderLayer::Tile, texture, 0, tileQuad(29.5f, 15.0f)) est vrai. Vérifie que scene.addSprite(hmi::RenderLayer::Tile, texture, 0, tileQuad(30.2f, 15.0f)) est vrai. Vérifie que scene.addSprite(hmi::RenderLayer::Tile, texture, 0, tileQuad(31.5f, 15.0f)) est faux. |
| RenderCullingTest.SegmentHorizontalConserve (Majeur) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:132 | Un segment horizontal traversant le cadrage est conserve. | 1. Fixer le cadrage de reference. 2. Composer un segment horizontal a l'interieur, puis un segment horizontal tres au-dessus. | Vérifie que scene.addLine(hmi::RenderLayer::EditorOverlay, texture, 0, inside) est vrai. Vérifie que scene.addLine(hmi::RenderLayer::EditorOverlay, texture, 0, outside) est faux. |
| RenderCullingTest.PrimitiveEtireeConservee (Critique) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:162 | Une primitive etiree dont l'ancrage est hors cadrage reste soumise. | 1. Fixer le cadrage de reference. 2. Composer un quad ancre en (0, 0) et large de 200 unites. | Vérifie que scene.addSprite(hmi::RenderLayer::Background, texture, 0, background) est vrai. |
| RenderCullingTest.SpriteQuadBoundsSansRotationEstLeRectangleBrut (Majeur) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:186 | spriteQuadBounds sans rotation vaut le rectangle brut. | 1. Calculer la boite englobante d'un quad de rotation nulle. | Vérifie que bounds.position.x vaut 5.0f (comparaison flottante). Vérifie que bounds.position.y vaut 3.0f (comparaison flottante). Vérifie que bounds.size.x vaut 4.0f (comparaison flottante). Vérifie que bounds.size.y vaut 2.0f (comparaison flottante). |
| RenderCullingTest.SpriteQuadBoundsA90DegresPermuteLargeurEtHauteur (Critique) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:212 | spriteQuadBounds a 90 degres permute largeur et hauteur. | 1. Calculer la boite englobante d'un quad large tourne de 90 degres. | Vérifie que bounds.size.x vaut 2.0f, à 1e-3f près. Vérifie que bounds.size.y vaut 4.0f, à 1e-3f près. Vérifie que bounds.position.x + bounds.size.x * 0.5f vaut 2.0f, à 1e-3f près. Vérifie que bounds.position.y + bounds.size.y * 0.5f vaut 1.0f, à 1e-3f près. |
| RenderCullingTest.QuadTourneChevauchantLeCadrageResteSoumis (Critique) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:240 | Un quad tourne dont la boite reelle chevauche le cadrage reste soumis. | 1. Fixer un cadrage de reference. 2. Composer un quad tourne de 45 degres juste a l'exterieur du rectangle non tourne, mais dont la diagonale rentre dans le cadrage. | Vérifie que scene.addSprite(hmi::RenderLayer::EditorOverlay, texture, 0, quad) est vrai. |
| RenderCullingTest.VolumeProportionnelALaSalleVisible (Critique) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:269 | Le volume compose depend de la salle visible, pas de la taille du niveau. | 1. Peupler une ligne de tuiles couvrant trois salles. 2. Cadrer la premiere salle. 3. Composer la scene. | Vérifie que scene.statistics().considered vaut LEVEL_WIDTH. Vérifie que scene.statistics().submitted vaut ROOM_WIDTH + 1. Vérifie que scene.statistics().culled vaut LEVEL_WIDTH - ROOM_WIDTH - 1. |
| RenderCullingTest.MargeAppliqueeSurLesQuatreCotes (Mineur) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:304 | Le cadrage de culling est le cadrage visible elargi de la marge. | 1. Fixer le cadrage de reference. 2. Lire le rectangle de culling. | Vérifie que bounds.left() vaut VISIBLE_BOUNDS.left() - MARGIN (comparaison flottante). Vérifie que bounds.top() vaut VISIBLE_BOUNDS.top() - MARGIN (comparaison flottante). Vérifie que bounds.right() vaut VISIBLE_BOUNDS.right() + MARGIN (comparaison flottante). Vérifie que bounds.bottom() vaut VISIBLE_BOUNDS.bottom() + MARGIN (comparaison flottante). |
| RenderCullingTest.CadrageDeLaCamera (Majeur) Source/Test/Unit/HMI/Graphics/test_render_culling.cpp:325 | La camera fournit le rectangle monde qu'elle cadre. | 1. Centrer une camera 320x160 sur (10, 5) au zoom 1. 2. Lire son cadrage. | Vérifie que bounds.left() vaut 0.0f (comparaison flottante). Vérifie que bounds.top() vaut 0.0f (comparaison flottante). Vérifie que bounds.size.x vaut 20.0f (comparaison flottante). Vérifie que bounds.size.y vaut 10.0f (comparaison flottante). Vérifie que camera.visibleBounds().size.x vaut 10.0f (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RenderModeTest.AllerRetourDuNomPersiste (Majeur) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:77 | Le nom persiste du mode fait l'aller-retour sans perte. | 1. Convertir chaque mode en nom, puis le nom en mode. | Vérifie que hmi::renderModeFromName(hmi::renderModeName(hmi::RenderMode::Physique)) vaut hmi::RenderMode::Physique. Vérifie que hmi::renderModeFromName(hmi::renderModeName(hmi::RenderMode::Texture)) vaut hmi::RenderMode::Texture. |
| RenderModeTest.PreferenceInvalideRetombeSurLeDefaut (Critique) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:94 | Une preference absente ou invalide retombe sur le mode Texture. | 1. Convertir une chaine vide, une chaine inconnue et une chaine tronquee. | Vérifie que hmi::DEFAULT_RENDER_MODE vaut hmi::RenderMode::Texture. Vérifie que hmi::renderModeFromName("") vaut hmi::DEFAULT_RENDER_MODE. Vérifie que hmi::renderModeFromName("plein-ecran") vaut hmi::DEFAULT_RENDER_MODE. Vérifie que hmi::renderModeFromName("phys") vaut hmi::DEFAULT_RENDER_MODE. |
| RenderModeTest.LectureInsensibleALaCasse (Mineur) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:111 | La lecture du nom persiste est insensible a la casse. | 1. Convertir « PHYSIQUE » et « Texture ». | Vérifie que hmi::renderModeFromName("PHYSIQUE") vaut hmi::RenderMode::Physique. Vérifie que hmi::renderModeFromName("Texture") vaut hmi::RenderMode::Texture. |
| RenderModeTest.ModePhysiqueRendLaRegionDAtlas (Critique) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:126 | En mode Physique, le resolveur rend la region d'atlas de chaque type de tuile. | 1. Pour chaque type de tuile, resoudre l'apparence en mode Physique. | Vérifie que appearance.source vaut hmi::AppearanceSource::Atlas. Vérifie que appearance.region.x vaut expected.x. Vérifie que appearance.region.y vaut expected.y. Vérifie que appearance.region.width vaut expected.width. Vérifie que appearance.region.height vaut expected.height. |
| RenderModeTest.ModeTextureRetombeSurLeDamier (Critique) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:157 | En mode Texture, une entite sans marque d'habillage retombe sur le damier. | 1. Resoudre l'apparence en mode Texture sans marque d'habillage. | Vérifie que appearance.source vaut hmi::AppearanceSource::MissingTexture. Vérifie que appearance.region.x vaut 0. Vérifie que appearance.region.y vaut 0. Vérifie que appearance.region.width vaut hmi::MISSING_TEXTURE_SIZE. Vérifie que appearance.region.height vaut hmi::MISSING_TEXTURE_SIZE. |
| RenderModeTest.ModePhysiqueNonRegression (Critique) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:185 | Non-regression : le mode Physique produit les primitives d'avant le lot. | 1. Composer la scene de reference en mode Physique. 2. Inspecter la liste capturee. | Vérifie que recorder.size() vaut 4u. Vérifie que recorder.isLayerOrderRespected() est vrai. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Tile) vaut 3. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Player) vaut 1. Vérifie que recorder.countWithTexture(testTextures().atlas) vaut 4. Vérifie que recorder.statistics().batches vaut 1. Vérifie que recorder.quads()[1].sprite.u0 vaut 16.0f / 80.0f (comparaison flottante). Vérifie que recorder.quads()[1].sprite.u1 vaut 32.0f / 80.0f (comparaison flottante). |
| RenderModeTest.ModeTextureConserveLaGeometrie (Critique) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:220 | Le mode Texture lie le damier sans changer la geometrie composee. | 1. Composer la scene de reference dans les deux modes. 2. Comparer textures, positions et tailles. | Vérifie que physique.size() vaut texture.size(). Vérifie que texture[i].texture vaut testTextures().missing. Vérifie que texture[i].layer vaut physique[i].layer. Vérifie que texture[i].sprite.x vaut physique[i].sprite.x (comparaison flottante). Vérifie que texture[i].sprite.y vaut physique[i].sprite.y (comparaison flottante). Vérifie que texture[i].sprite.width vaut physique[i].sprite.width (comparaison flottante). Vérifie que texture[i].sprite.height vaut physique[i].sprite.height (comparaison flottante). |
| RenderModeTest.BasculeSansEffetRemanent (Critique) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:253 | La bascule Physique -> Texture -> Physique est sans effet remanent. | 1. Composer en Physique, puis en Texture, puis de nouveau en Physique. 2. Comparer la premiere et la troisieme liste. | Vérifie que before.size() vaut after.size(). Vérifie que after[i].texture vaut before[i].texture. Vérifie que after[i].layer vaut before[i].layer. Vérifie que after[i].sortOrder vaut before[i].sortOrder. Vérifie que after[i].sprite.x vaut before[i].sprite.x (comparaison flottante). Vérifie que after[i].sprite.u0 vaut before[i].sprite.u0 (comparaison flottante). Vérifie que after[i].sprite.v1 vaut before[i].sprite.v1 (comparaison flottante). |
| RenderModeTest.F8HorsDesTablesDeRemappage (Critique) Source/Test/Unit/HMI/Graphics/test_render_mode.cpp:292 | F8 n'apparait dans aucune table de remappage. | 1. Parcourir les touches par defaut de toutes les actions de jeu et d'edition. | Vérifie que static_cast<int>(key) diffère de VIRTUAL_KEY_F8. Vérifie que static_cast<int>(key) diffère de VIRTUAL_KEY_F8. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RhiOffscreenTest.ZoomEntierResteNetEnFiltrageNearest (Critique) Source/Test/Unit/HMI/Graphics/test_rhi_offscreen.cpp:89 | Le rendu QRhi conserve le pixel art net a zoom entier. | 1. Rendre hors ecran une texture temoin 4x4 agrandie 4 fois. 2. Relire les pixels de la cible. | Vérifie que target->create() est vrai. Vérifie que renderTarget->create() est vrai. Vérifie que rhi->beginOffscreenFrame(&commandBuffer) vaut QRhi::FrameOpSuccess. Vérifie que source.has_value() est vrai. Vérifie que rhi->endOffscreenFrame() vaut QRhi::FrameOpSuccess. Vérifie que readback.pixelSize vaut QSize(TARGET_SIZE, TARGET_SIZE). Vérifie que pixel.red() vaut red. Vérifie que pixel.green() vaut green. Vérifie que pixel.blue() vaut blue. |
| RhiOffscreenTest.TeinteMultiplieeEtEffacementConserve (Majeur) Source/Test/Unit/HMI/Graphics/test_rhi_offscreen.cpp:180 | La teinte multiplie la texture et l'effacement subsiste hors du quad. | 1. Rendre hors ecran un quad teinte couvrant un quart de la cible. 2. Relire un pixel dans le quad et un pixel hors du quad. | Vérifie que target->create() est vrai. Vérifie que renderTarget->create() est vrai. Vérifie que rhi->beginOffscreenFrame(&commandBuffer) vaut QRhi::FrameOpSuccess. Vérifie que source.has_value() est vrai. Vérifie que rhi->endOffscreenFrame() vaut QRhi::FrameOpSuccess. Vérifie que inside.red() vaut 0. Vérifie que inside.green() vaut 255. Vérifie que inside.blue() vaut 0. Vérifie que outside.red() vaut 0. Vérifie que outside.green() vaut 0. Vérifie que outside.blue() vaut 255. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RoomGridTest.NiveauPlusPetitQuUneSalleProduitUneSeuleSalle (Majeur) Source/Test/Unit/HMI/Graphics/test_room_grid.cpp:16 | Un niveau plus petit qu'une salle produit une seule salle couvrant le niveau entier. | 1. Construire un RoomGrid pour un niveau plus petit que la taille de salle sur les deux axes. 2. Vérifier columns()/rows() et le rectangle de l'unique salle. | Vérifie que grid.columns() vaut 1. Vérifie que grid.rows() vaut 1. Vérifie que bounds.column vaut 0. Vérifie que bounds.row vaut 0. Vérifie que bounds.width vaut 10. Vérifie que bounds.height vaut 6. |
| RoomGridTest.NiveauMultipleExactNeRogneAucuneSalle (Majeur) Source/Test/Unit/HMI/Graphics/test_room_grid.cpp:41 | Un niveau exactement multiple de la taille de salle ne rogne aucune salle. | 1. Construire un RoomGrid pour un niveau dont chaque dimension est un multiple exact de la taille de salle. 2. Vérifier columns()/rows() et le rectangle de chaque salle. | Vérifie que grid.columns() vaut 3. Vérifie que grid.rows() vaut 2. Vérifie que last.column vaut hmi::RoomGrid::ROOM_WIDTH_TILES * 2. Vérifie que last.row vaut hmi::RoomGrid::ROOM_HEIGHT_TILES * 1. Vérifie que last.width vaut hmi::RoomGrid::ROOM_WIDTH_TILES. Vérifie que last.height vaut hmi::RoomGrid::ROOM_HEIGHT_TILES. |
| RoomGridTest.NiveauNonMultipleRogneLaDerniereSalle (Majeur) Source/Test/Unit/HMI/Graphics/test_room_grid.cpp:68 | Un niveau non multiple de la taille de salle rogne la dernière colonne/ligne. | 1. Construire un RoomGrid pour un niveau dépassant de quelques cases un multiple de la taille de salle. 2. Vérifier le rectangle de la dernière salle sur chaque axe. | Vérifie que grid.columns() vaut 2. Vérifie que grid.rows() vaut 2. Vérifie que last.column vaut hmi::RoomGrid::ROOM_WIDTH_TILES. Vérifie que last.row vaut hmi::RoomGrid::ROOM_HEIGHT_TILES. Vérifie que last.width vaut extraWidth. Vérifie que last.height vaut extraHeight. |
| RoomGridTest.RoomIndexAtQuatreCoins (Majeur) Source/Test/Unit/HMI/Graphics/test_room_grid.cpp:97 | roomIndexAt renvoie l'indice de salle correct aux quatre coins et au centre. | 1. Construire un RoomGrid de 2x2 salles. 2. Interroger roomIndexAt à des positions choisies dans chacune des quatre salles. | Vérifie que grid.roomIndexAt(core::GridPosition{0, 0}) vaut (core::GridPosition{0, 0}). Vérifie que grid.roomIndexAt(core::GridPosition{width - 1, 0}) vaut (core::GridPosition{1, 0}). Vérifie que grid.roomIndexAt(core::GridPosition{0, height - 1}) vaut (core::GridPosition{0, 1}). Vérifie que grid.roomIndexAt(core::GridPosition{width - 1, height - 1}) vaut (core::GridPosition{1, 1}). |
| RoomGridTest.PositionHorsBornesEstBornee (Mineur) Source/Test/Unit/HMI/Graphics/test_room_grid.cpp:120 | Une position hors des bornes du niveau est bornée à la salle la plus proche. | 1. Construire un RoomGrid pour un petit niveau. 2. Interroger roomIndexAt avec des coordonnées négatives puis très supérieures aux bornes. | Vérifie que grid.roomIndexAt(core::GridPosition{-100, -100}) vaut (core::GridPosition{0, 0}). Vérifie que grid.roomIndexAt(core::GridPosition{1000, 1000}) vaut (core::GridPosition{0, 0}). |
| RoomGridTest.TailleDeSallePersonnaliseePartitionneSelonCetteTaille (Majeur) Source/Test/Unit/HMI/Graphics/test_room_grid.cpp:141 | Une taille de salle personnalisée partitionne selon cette taille. | 1. Construire un RoomGrid sans taille explicite, vérifier roomWidthTiles()/ roomHeightTiles(). 2. Construire un RoomGrid avec une taille personnalisée non multiple du niveau. 3. Vérifier le nombre de salles et la troncature de la dernière. | Vérifie que defaultSized.roomWidthTiles() vaut hmi::RoomGrid::ROOM_WIDTH_TILES. Vérifie que defaultSized.roomHeightTiles() vaut hmi::RoomGrid::ROOM_HEIGHT_TILES. Vérifie que custom.roomWidthTiles() vaut customWidth. Vérifie que custom.roomHeightTiles() vaut customHeight. Vérifie que custom.columns() vaut 3. Vérifie que custom.rows() vaut 3. Vérifie que last.column vaut customWidth * 2. Vérifie que last.row vaut customHeight * 2. Vérifie que last.width vaut 24 - customWidth * 2. Vérifie que last.height vaut 20 - customHeight * 2. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ScreenShakeTest.EtatParDefautAucunDecalage (Majeur) Source/Test/Unit/HMI/Graphics/test_screen_shake.cpp:21 | État par défaut : aucun décalage. | 1. Construire un hmi::ScreenShakeState par défaut. 2. Lire son décalage. | Vérifie que offset.x vaut 0.0f (comparaison flottante). Vérifie que offset.y vaut 0.0f (comparaison flottante). |
| ScreenShakeTest.DecroitLineairementJusquAZeroALaDureePrevue (Critique) Source/Test/Unit/HMI/Graphics/test_screen_shake.cpp:38 | Décroissance jusqu'à zéro dans la durée prévue. | 1. Déclencher une secousse (amplitude 4, durée 0,2 s). 2. Lire le décalage au déclenchement, à mi-durée, à la durée exacte, puis bien au-delà. | Vérifie que hmi::screenShakeOffset(state).y vaut 4.0f (comparaison flottante). Vérifie que hmi::screenShakeOffset(state).y vaut 2.0f (comparaison flottante). Vérifie que hmi::screenShakeOffset(state).y vaut 0.0f (comparaison flottante). Vérifie que hmi::screenShakeOffset(state).y vaut 0.0f (comparaison flottante). |
| ScreenShakeTest.DecalageArrondiAuPixelEntier (Majeur) Source/Test/Unit/HMI/Graphics/test_screen_shake.cpp:65 | Décalage arrondi au pixel entier. | 1. Déclencher une secousse (amplitude 5, durée 0,3 s). 2. Avancer d'un tiers de la durée (décalage brut 3,33). | Vérifie que hmi::screenShakeOffset(state).y vaut 3.0f (comparaison flottante). |
| ScreenShakeTest.AucunDecalageHorizontal (Mineur) Source/Test/Unit/HMI/Graphics/test_screen_shake.cpp:83 | Aucun décalage horizontal. | 1. Déclencher une secousse. 2. Lire le décalage à plusieurs instants. | Vérifie que hmi::screenShakeOffset(state).x vaut 0.0f (comparaison flottante). Vérifie que hmi::screenShakeOffset(state).x vaut 0.0f (comparaison flottante). |
| ScreenShakeTest.NeModifieNiLeCentreNiLeCadrageVisible (Critique) Source/Test/Unit/HMI/Graphics/test_screen_shake.cpp:103 | La secousse ne modifie ni le centre ni le cadrage visible. | 1. Poser un centre/zoom sur une caméra, noter center()/visibleBounds(). 2. Appliquer un décalage de secousse non nul. | Vérifie que camera.center().x vaut centerBefore.x (comparaison flottante). Vérifie que camera.center().y vaut centerBefore.y (comparaison flottante). Vérifie que camera.zoom() vaut 2.0f (comparaison flottante). Vérifie que boundsAfter.position.x vaut boundsBefore.position.x (comparaison flottante). Vérifie que boundsAfter.position.y vaut boundsBefore.position.y (comparaison flottante). Vérifie que boundsAfter.size.x vaut boundsBefore.size.x (comparaison flottante). Vérifie que boundsAfter.size.y vaut boundsBefore.size.y (comparaison flottante). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ShadowRenderTest.TuilePleineProjetteUnQuadDecaleSurShadow (Critique) Source/Test/Unit/HMI/Graphics/test_shadow_render.cpp:53 | Tuile pleine : quad d'ombre decale sur Shadow. | 1. Peupler une tuile Solid. 2. Composer les ombres en mode Texture. | Vérifie que recorder.size() vaut 1u. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Shadow) vaut 1. Vérifie que quad.sprite.x vaut 3.0f + hmi::SHADOW_OFFSET_X (comparaison flottante). Vérifie que quad.sprite.y vaut 2.0f + hmi::SHADOW_OFFSET_Y (comparaison flottante). Vérifie que quad.sprite.width vaut 1.0f (comparaison flottante). Vérifie que quad.sprite.height vaut 1.0f (comparaison flottante). Vérifie que quad.sprite.a est strictement inférieur à 1.0f. |
| ShadowRenderTest.DouzeSilhouettesMemeRegionQueRegionForTile (Critique) Source/Test/Unit/HMI/Graphics/test_shadow_render.cpp:83 | Silhouettes : ombre a la meme region d'atlas que la tuile. | 1. Peupler chacun des douze types a silhouette. 2. Composer les ombres. | Vérifie que recorder.size() vaut 1u. Vérifie que quad.sprite.u0 vaut expectedU0 (comparaison flottante). Vérifie que quad.sprite.v0 vaut expectedV0 (comparaison flottante). Vérifie que quad.sprite.u1 vaut expectedU1 (comparaison flottante). Vérifie que quad.sprite.v1 vaut expectedV1 (comparaison flottante). |
| ShadowRenderTest.BlocPoussableEnMouvementOmbreInterpolee (Majeur) Source/Test/Unit/HMI/Graphics/test_shadow_render.cpp:120 | Bloc poussable en mouvement : ombre interpolee. | 1. Peupler un Block avec une PreviousPosition distincte. 2. Composer a interpolationAlpha = 0.5. | Vérifie que recorder.size() vaut 1u. Vérifie que recorder.quads().front().sprite.x vaut 4.5f + hmi::SHADOW_OFFSET_X (comparaison flottante). Vérifie que recorder.quads().front().sprite.y vaut 5.0f + hmi::SHADOW_OFFSET_Y (comparaison flottante). |
| ShadowRenderTest.PorteSuitLEtatCourantDeLaGrilleDeCollision (Critique) Source/Test/Unit/HMI/Graphics/test_shadow_render.cpp:147 | Porte : ombre selon l'etat courant de la grille de collision. | 1. Peupler une porte. 2. Composer sans grille, puis avec une grille ou elle est fermee, puis ouverte. | Vérifie que scene.size() vaut 0u. Vérifie que scene.size() vaut 1u. Vérifie que scene.size() vaut 0u. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| SkinCatalogTest.AllerRetourDuNomDeMode (Majeur) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:85 | Le nom persiste d'un mode de skin fait l'aller-retour sans perte. | 1. Convertir chaque mode en nom, puis le nom en mode. | Vérifie que parsed.has_value() est vrai. Vérifie que *parsed vaut mode. Vérifie que hmi::skinModeFromName("").has_value() est faux. Vérifie que hmi::skinModeFromName("bitmask47").has_value() est faux. |
| SkinCatalogTest.AllerRetourLectureEcriture (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:105 | Un catalogue fait l'aller-retour lecture -> ecriture -> lecture sans perte. | 1. Lire le catalogue de reference (deux jeux). 2. Le reserialiser puis le relire. | Vérifie que reread.ok() est vrai. Vérifie que reread.catalog->setNames() vaut original.setNames(). Vérifie que reread.catalog->defaultSetName() vaut original.defaultSetName(). Vérifie que reread.catalog->assignments(setName) vaut original.assignments(setName). |
| SkinCatalogTest.ResolutionDansUnJeuExistant (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:129 | La resolution rend l'asset et le mode assignes dans le jeu demande. | 1. Resoudre Solid et Block dans le jeu « foret », puis Solid dans « grotte ». | Vérifie que solid.has_value() est vrai. Vérifie que solid->asset vaut "stone.png". Vérifie que solid->mode vaut hmi::SkinMode::Bitmask16. Vérifie que block.has_value() est vrai. Vérifie que block->asset vaut "crate.png". Vérifie que block->mode vaut hmi::SkinMode::Single. Vérifie que cave.has_value() est vrai. Vérifie que cave->asset vaut "rock.png". |
| SkinCatalogTest.JeuInexistantRetombeSurLeDefaut (Majeur) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:157 | Un jeu inexistant retombe sur le jeu par defaut plutot que de ne rien rendre. | 1. Resoudre Solid dans un jeu qui n'existe pas. 2. Resoudre Solid en demandant explicitement le defaut (nom vide). | Vérifie que missing.has_value() est vrai. Vérifie que missing->asset vaut "stone.png". Vérifie que byDefault.has_value() est vrai. Vérifie que byDefault->asset vaut "stone.png". |
| SkinCatalogTest.TypeNonSkinneNeResoudRien (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:179 | Un type de tuile sans skin assigne ne resout aucune entree. | 1. Resoudre un type absent du jeu « foret », puis un type absent de « grotte ». | Vérifie que catalog.resolve("foret", core::TileType::Danger).has_value() est faux. Vérifie que catalog.resolve("grotte", core::TileType::Block).has_value() est faux. |
| SkinCatalogTest.JsonMalformeSignale (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:197 | Un fichier de skins malforme est signale sans lever d'exception. | 1. Lire une chaine qui n'est pas du JSON, puis un JSON dont la racine est un tableau. | Vérifie que broken.ok() est faux. Vérifie que broken.errorCode vaut hmi::SkinCatalogError::ParseError. Vérifie que broken.error.empty() est faux. Vérifie que notObject.ok() est faux. Vérifie que notObject.errorCode vaut hmi::SkinCatalogError::ParseError. |
| SkinCatalogTest.VersionInconnueRefusee (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:217 | Une version de format superieure a celle geree est refusee explicitement. | 1. Lire un catalogue dont la version vaut celle geree, puis une superieure. | Vérifie que current.ok() est vrai. Vérifie que future.ok() est faux. Vérifie que future.errorCode vaut hmi::SkinCatalogError::UnsupportedVersion. |
| SkinCatalogTest.TypeOuModeInconnuSignale (Majeur) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:239 | Un type de tuile ou un mode de skin inconnu est signale a la lecture. | 1. Lire un catalogue citant un type de tuile inexistant. 2. Lire un catalogue citant un mode inexistant, puis une entree sans asset. | Vérifie que badType.ok() est faux. Vérifie que badType.errorCode vaut hmi::SkinCatalogError::MalformedStructure. Vérifie que badMode.ok() est faux. Vérifie que badMode.errorCode vaut hmi::SkinCatalogError::MalformedStructure. Vérifie que noAsset.ok() est faux. Vérifie que noAsset.errorCode vaut hmi::SkinCatalogError::MalformedStructure. |
| SkinCatalogTest.DefautInexistantSignale (Majeur) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:266 | Un jeu par defaut qui ne designe aucun jeu existant est signale. | 1. Lire un catalogue dont le champ « defaut » cite un jeu absent de « jeux ». | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::SkinCatalogError::MalformedStructure. |
| SkinCatalogTest.ModeAbsentVautSingle (Mineur) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:283 | Une entree sans champ « mode » est lue en mode image unique. | 1. Lire une entree ne portant que le champ « asset ». | Vérifie que result.ok() est vrai. Vérifie que entry.has_value() est vrai. Vérifie que entry->mode vaut hmi::SkinMode::Single. |
| SkinCatalogTest.FichierAbsentSignale (Majeur) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:303 | Un fichier de skins absent est signale par un code dedie, sans exception. | 1. Lire un chemin qui n'existe pas. | Vérifie que result.ok() est faux. Vérifie que result.errorCode vaut hmi::SkinCatalogError::FileNotFound. |
| SkinCatalogTest.EcritureSurDisqueRelisible (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:320 | Le catalogue ecrit sur disque est relu a l'identique. | 1. Ecrire le catalogue de reference dans un fichier temporaire. 2. Le relire depuis ce fichier. | Vérifie que catalog.saveToFile(path) est vrai. Vérifie que reread.ok() est vrai. Vérifie que reread.catalog->assignments("foret") vaut catalog.assignments("foret"). Vérifie que reread.catalog->defaultSetName() vaut catalog.defaultSetName(). |
| SkinCatalogTest.AssignationPuisRetrait (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:345 | Assigner puis retirer un skin change la resolution du type concerne. | 1. Assigner un asset a Danger dans un catalogue vide, puis resoudre. 2. Retirer l'assignation, puis resoudre a nouveau. | Vérifie que catalog.defaultSetName() vaut "foret". Vérifie que assigned.has_value() est vrai. Vérifie que assigned->asset vaut "spikes.png". Vérifie que catalog.resolve("foret", core::TileType::Danger).has_value() est faux. |
| SkinCatalogTest.OrdreDesJeuxStable (Mineur) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:372 | Les noms de jeux sont rendus dans un ordre alphabetique stable. | 1. Creer trois jeux dans un ordre quelconque. | Vérifie que catalog.setNames() vaut expected. |
| SkinCatalogTest.CatalogueLivreValide (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:393 | Le fichier de skins livre avec le jeu se lit sans erreur. | 1. Lire Source/Elements/Assets/skins.json depuis les sources. | Vérifie que std::filesystem::exists(path) est vrai. Vérifie que result.ok() est vrai. Vérifie que sets.empty() est faux. Vérifie que std::find(sets.begin(), sets.end(), result.catalog->defaultSetName()) diffère de sets.end(). |
| SkinCatalogTest.AssetsDuCatalogueLivreConformes (Critique) Source/Test/Unit/HMI/Graphics/test_skin_catalog.cpp:415 | Chaque asset reference par le catalogue livre existe aux bonnes dimensions. | 1. Lire le catalogue livre et parcourir toutes les assignations de tous les jeux. 2. Pour chaque asset, verifier sa presence dans Assets/Skins puis ses dimensions. | Vérifie que result.ok() est vrai. Vérifie que std::filesystem::exists(path) est vrai. Vérifie que size.has_value() est vrai. Vérifie que size->first vaut TILE * hmi::AUTOTILE_SHEET_SIDE. Vérifie que size->second vaut TILE * hmi::AUTOTILE_SHEET_SIDE. Vérifie que size->second vaut TILE. Vérifie que size->first est strictement supérieur à 0. Vérifie que size->first % TILE vaut 0. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TextRendererTest.ChaineVideNeProduitAucunQuad (Majeur) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:44 | Une chaîne vide ne produit aucun quad. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que scene.size() vaut 0u. |
| TextRendererTest.ChaineDeuxCaracteresProduitDeuxQuadsAuxPositionsAttendues (Critique) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:62 | Une chaîne de N caractères produit N quads, aux positions attendues. | 1. Composer « AB » en ancrage haut-gauche. 2. Capturer la scène. | Vérifie que recorder.size() vaut 2u. Vérifie que recorder.containsSpriteAt(0.0f, 0.0f) est vrai. Vérifie que recorder.containsSpriteAt(6.0f, 0.0f) est vrai. |
| TextRendererTest.EspaceNEmetAucunQuadMaisAvanceLeStylo (Majeur) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:84 | L'espace n'émet aucun quad mais fait avancer le stylo. | 1. Composer « A B » (A, espace, B). 2. Capturer la scène. | Vérifie que recorder.size() vaut 2u. Vérifie que recorder.containsSpriteAt(0.0f, 0.0f) est vrai. Vérifie que recorder.containsSpriteAt(12.0f, 0.0f) est vrai. |
| TextRendererTest.ChaineAccentueeCompteLesPointsDeCode (Critique) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:107 | Une chaîne accentuée produit un quad par point de code, pas par octet. | 1. Composer « É » (deux octets UTF-8, un point de code). 2. Capturer la scène. | Vérifie que scene.size() vaut 1u. |
| TextRendererTest.AncrageCentreDecaleLaBoiteDeSaMoitie (Majeur) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:125 | L'ancrage centré décale la boîte du texte de sa moitié. | 1. Composer « AB » avec un ancrage centré aux deux axes. 2. Capturer la scène. | Vérifie que recorder.size() vaut 2u. Vérifie que recorder.containsSpriteAt(-6.0f, -5.0f) est vrai. |
| TextRendererTest.AncrageDroiteBasPositionneLaFinDeLaBoite (Majeur) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:147 | L'ancrage droite/bas positionne la fin de la boîte sur le point d'ancrage. | 1. Composer « AB » avec un ancrage droite/bas à (100, 100). 2. Capturer la scène. | Vérifie que recorder.size() vaut 2u. Vérifie que recorder.containsSpriteAt(88.0f, 90.0f) est vrai. |
| TextRendererTest.PrimitivesSurLeCalqueUi (Critique) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:169 | Toutes les primitives composées le sont sur le calque UI. | 1. Composer un texte de plusieurs caractères. 2. Capturer la scène. | Vérifie que recorder.countOnLayer(hmi::RenderLayer::UI) vaut 2. Vérifie que recorder.countOnLayer(hmi::RenderLayer::Tile) vaut 0. |
| TextRendererTest.CaractereAbsentEstSubstitueEtComposeUnQuad (Majeur) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:191 | Un point de code non couvert est substitué par le glyphe de remplacement. | 1. Composer un caractère absent de testMetrics() ('#'). 2. Capturer la scène. | Vérifie que scene.size() vaut 1u. |
| TextRendererTest.TexteNestJamaisCulle (Majeur) Source/Test/Unit/HMI/Graphics/test_text_renderer.cpp:210 | Le texte n'est jamais soumis au culling par cadrage. | 1. Composer un texte à une position écran éloignée (10000, 10000), sans cadrage actif sur la scène. 2. Vérifier la scène. | Vérifie que scene.isCullingEnabled() est faux. Vérifie que scene.size() vaut 1u. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TextureAtlasTest.TileRenvoieLeRectangleAttendu (Critique) Source/Test/Unit/HMI/Graphics/test_texture_atlas.cpp:19 | tile(colonne, ligne) renvoie un rectangle de 16x16 pixels à l'origine attendue. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que origin.x vaut 0. Vérifie que origin.y vaut 0. Vérifie que origin.width vaut hmi::TextureAtlas::TILE_SIZE. Vérifie que origin.height vaut hmi::TextureAtlas::TILE_SIZE. Vérifie que secondRow.x vaut 2 * hmi::TextureAtlas::TILE_SIZE. Vérifie que secondRow.y vaut 1 * hmi::TextureAtlas::TILE_SIZE. Vérifie que secondRow.width vaut hmi::TextureAtlas::TILE_SIZE. Vérifie que secondRow.height vaut hmi::TextureAtlas::TILE_SIZE. |
| TextureAtlasTest.PlayerFrameRegionSousLaGrilleDeTuiles (Critique) Source/Test/Unit/HMI/Graphics/test_texture_atlas.cpp:45 | playerFrameRegion place les images du personnage sous la grille de tuiles, dans l'ordre Idle, Run, Jump. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que idleFirst.x vaut 0. Vérifie que idleFirst.y vaut gridSide. Vérifie que idleFirst.width vaut hmi::TextureAtlas::PLAYER_FRAME_SIZE. Vérifie que idleFirst.height vaut hmi::TextureAtlas::PLAYER_FRAME_SIZE. Vérifie que runFirst.x vaut (runFlatIndex % hmi::TextureAtlas::PLAYER_FRAME_COLUMNS) * hmi::TextureAtlas::PLAYER_FRAME_SIZE. Vérifie que runFirst.y vaut gridSide + (runFlatIndex / hmi::TextureAtlas::PLAYER_FRAME_COLUMNS) * hmi::TextureAtlas::PLAYER_FRAME_SIZE. Vérifie que jump.x vaut (jumpFlatIndex % hmi::TextureAtlas::PLAYER_FRAME_COLUMNS) * hmi::TextureAtlas::PLAYER_FRAME_SIZE. Vérifie que jump.y vaut gridSide + (jumpFlatIndex / hmi::TextureAtlas::PLAYER_FRAME_COLUMNS) * hmi::TextureAtlas::PLAYER_FRAME_SIZE. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TextureResolutionTest.SurchargeChargeePrioritaireSurLeSkin (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:67 | Une surcharge chargée est prioritaire sur le skin du type. | 1. Résoudre une tuile Solid (skinnée) portant une surcharge chargée, en mode Texture. | Vérifie que appearance.source vaut hmi::AppearanceSource::Override. Vérifie que appearance.region.width vaut TILE. Vérifie que appearance.region.height vaut TILE. Vérifie que textures.textureFor(appearance) vaut &doorRedStorage. |
| TextureResolutionTest.SurchargeIntrouvableRetombeSurLeDamierPasSurLeSkin (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:93 | Une surcharge introuvable retombe sur le damier, pas sur le skin. | 1. Résoudre une tuile Solid skinnée portant une surcharge dont l'asset n'est pas chargé. | Vérifie que appearance.source vaut hmi::AppearanceSource::MissingTexture. Vérifie que textures.textureFor(appearance) vaut &missingStorage. |
| TextureResolutionTest.SansSurchargeLeSkinSAppliqueNormalement (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:117 | Sans surcharge, le skin du type s'applique normalement. | 1. Résoudre une tuile Solid skinnée, sans surcharge. | Vérifie que appearance.source vaut hmi::AppearanceSource::Skin. Vérifie que textures.textureFor(appearance) vaut &stoneStorage. |
| TextureResolutionTest.SurchargeSAppliqueMemeSansSkinDuType (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:141 | Une surcharge s'affiche même sur un type sans skin. | 1. Résoudre une tuile Danger (non skinnée) portant une surcharge chargée. | Vérifie que appearance.source vaut hmi::AppearanceSource::Override. |
| TextureResolutionTest.SurchargeSAppliqueMemeSansCatalogue (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:163 | Une surcharge s'affiche même sans catalogue de skins. | 1. Résoudre une tuile portant une surcharge, catalogue absent. | Vérifie que appearance.source vaut hmi::AppearanceSource::Override. Vérifie que textures.textureFor(appearance) vaut &doorRedStorage. |
| TextureResolutionTest.ModePhysiqueIgnoreLesSurcharges (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:187 | Le mode Physique ignore les surcharges. | 1. Résoudre une tuile portant une surcharge, en mode Physique. | Vérifie que appearance.source vaut hmi::AppearanceSource::Atlas. Vérifie que appearance.region.x vaut physical.x. |
| TextureResolutionTest.IndexDObjetInvalideBorne (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:209 | Un index d'objet invalide retombe sur le damier sans lecture hors bornes. | 1. Interroger les textures avec une apparence Override portant un index hors bornes. | Vérifie que textures.textureFor(broken) vaut &missingStorage. Vérifie que textures.widthFor(broken) vaut hmi::MISSING_TEXTURE_SIZE. Vérifie que textures.heightFor(broken) vaut hmi::MISSING_TEXTURE_SIZE. |
| TextureResolutionTest.ObjetsSeulsSurchargeChargeeSAffiche (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:231 | Objets interactifs seuls : une surcharge chargee s'affiche normalement. | 1. Résoudre une tuile Solid skinnée portant une surcharge chargée, axe skin masqué. | Vérifie que appearance.has_value() est vrai. Vérifie que appearance->source vaut hmi::AppearanceSource::Override. |
| TextureResolutionTest.ObjetsSeulsSansSurchargeNAfficheRien (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:254 | Objets interactifs seuls : une case sans surcharge n'affiche rien. | 1. Résoudre une tuile Solid skinnée sans surcharge, axe skin masqué. | Vérifie que appearance.has_value() est faux. |
| TextureResolutionTest.ObjetsSeulsSansSurchargeNiSkinNAfficheRien (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:276 | Objets interactifs seuls : une case sans surcharge ni skin n'affiche pas le damier. | 1. Résoudre une tuile Danger (non skinnée) sans surcharge, axe skin masqué. | Vérifie que appearance.has_value() est faux. |
| TextureResolutionTest.SkinSeulTypeSkinneSAfficheNormalement (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:299 | Skin des tuiles seul : un type skinne s'affiche normalement. | 1. Résoudre une tuile Solid skinnée sans surcharge, axe surcharge masqué. | Vérifie que appearance.has_value() est vrai. Vérifie que appearance->source vaut hmi::AppearanceSource::Skin. |
| TextureResolutionTest.SkinSeulTypeNonSkinneNAfficheRien (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:322 | Skin des tuiles seul : un type non skinne n'affiche rien. | 1. Résoudre une tuile Danger (non skinnée) sans surcharge, axe surcharge masqué. | Vérifie que appearance.has_value() est faux. |
| TextureResolutionTest.SkinSeulCaseAvecSurchargeNAfficheRien (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:344 | Skin des tuiles seul : une case avec surcharge n'affiche rien. | 1. Résoudre une tuile Solid portant une surcharge chargée, axe surcharge masqué. | Vérifie que appearance.has_value() est faux. |
| TextureResolutionTest.DeuxAxesMasquesNAfficheJamaisRien (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:366 | Les deux axes masques n'affichent jamais rien. | 1. Résoudre une tuile Solid skinnée avec surcharge, les deux axes masqués. | Vérifie que appearance.has_value() est faux. |
| TextureResolutionTest.ModeComposeSurchargeIntrouvableRetombeSurLeDamier (Critique) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:389 | Mode compose : une surcharge introuvable retombe toujours sur le damier. | 1. Résoudre une tuile Solid skinnée portant une surcharge introuvable, les deux axes visibles (valeurs par défaut). | Vérifie que appearance.has_value() est vrai. Vérifie que appearance->source vaut hmi::AppearanceSource::MissingTexture. |
| TextureResolutionTest.TextureOverrideAtTrouveLaSurchargeDeLaBonneCase (Majeur) Source/Test/Unit/HMI/Graphics/test_texture_resolution.cpp:412 | textureOverrideAt trouve la surcharge d'une case precise. | 1. Chercher une position avec et sans surcharge dans une liste de surcharges. | Vérifie que found.has_value() est vrai. Vérifie que *found vaut "door_red.png". Vérifie que hmi::textureOverrideAt(overrides, core::GridPosition{0, 0}).has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TileAutotileTest.SeizeConfigurationsSeizeCasesDistinctes (Critique) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:31 | Les seize configurations de voisinage donnent seize cases distinctes. | 1. Calculer la case de chacun des seize masques possibles. | Vérifie que cell.column est supérieur ou égal à 0. Vérifie que cell.column est strictement inférieur à hmi::AUTOTILE_SHEET_SIDE. Vérifie que cell.row est supérieur ou égal à 0. Vérifie que cell.row est strictement inférieur à hmi::AUTOTILE_SHEET_SIDE. Vérifie que cells.size() vaut static_cast<std::size_t>(hmi::AUTOTILE_CONFIGURATION_COUNT). |
| TileAutotileTest.TableDeCorrespondanceExhaustive (Critique) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:57 | Chaque masque de voisinage designe la case attendue de la planche. | 1. Verifier la case des seize masques, un a un. | Vérifie que cell.column vaut expected.column. Vérifie que cell.row vaut expected.row. |
| TileAutotileTest.ExterieurDeLaGrilleCompteSolide (Critique) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:99 | L'exterieur de la grille compte comme solide. | 1. Placer un solide isole dans le coin haut-gauche d'une grille vide. | Vérifie que (mask & hmi::NEIGHBOR_UP) != 0 est vrai. Vérifie que (mask & hmi::NEIGHBOR_LEFT) != 0 est vrai. Vérifie que (mask & hmi::NEIGHBOR_RIGHT) != 0 est faux. Vérifie que (mask & hmi::NEIGHBOR_DOWN) != 0 est faux. |
| TileAutotileTest.TuileIsoleeAuCentre (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:121 | Une tuile solide entouree de vide donne la configuration isolee. | 1. Placer un solide au centre d'une grille vide, loin des bords. | Vérifie que hmi::solidNeighborMask(tiles, 2, 2) vaut 0. Vérifie que hmi::autotileCell(0) vaut (hmi::AutotileCell{0, 0}). |
| TileAutotileTest.DessusDePlateformeDistinctDeLInterieur (Critique) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:138 | Le dessus d'une plateforme pleine differe de son interieur. | 1. Remplir de solide les lignes 2 a 4 d'une grille vide. 2. Comparer la case de la ligne de surface et celle d'une case enfouie. | Vérifie que surface vaut (hmi::AutotileCell{2, 3}). Vérifie que inside vaut (hmi::AutotileCell{3, 3}). Vérifie que surface == inside est faux. |
| TileAutotileTest.RaccordEntreTypesSolidesDifferents (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:166 | Le voisinage est celui de la solidite, pas du type de tuile. | 1. Placer un solide et, a sa droite, un bloc poussable. | Vérifie que (hmi::solidNeighborMask(tiles, 2, 2) & hmi::NEIGHBOR_RIGHT) != 0 est vrai. |
| TileAutotileTest.CaseRepresentativeEstLInterieurPlein (Mineur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:185 | La case representative d'une planche est son interieur plein. | 1. Demander la case representative de la planche. | Vérifie que hmi::autotileRepresentativeCell() vaut full. Vérifie que hmi::autotileRepresentativeCell() == (hmi::AutotileCell{0, 0}) est faux. |
| TileAutotileTest.BitsParasitesIgnores (Mineur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:202 | Un masque portant des bits parasites reste dans la planche. | 1. Demander la case d'un masque dont les bits de poids fort sont a 1. | Vérifie que hmi::autotileCell(noisy) vaut hmi::autotileCell(hmi::NEIGHBOR_UP). |
| TileAutotileTest.SeizeMasquesProduisentSeizeClesDeLibelleDistinctes (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:218 | Les seize masques produisent seize cles de libelle distinctes. | 1. Produire la cle de libelle de chacun des seize masques. | Vérifie que keys.size() vaut static_cast<std::size_t>(hmi::AUTOTILE_CONFIGURATION_COUNT). |
| TileAutotileTest.LibelleIgnoreLesBitsParasites (Mineur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:235 | Un masque de libelle portant des bits parasites reste dans la table. | 1. Demander le libelle d'un masque dont les bits de poids fort sont a 1. | Vérifie que hmi::autotileConfigurationLabelKey(noisy) vaut hmi::autotileConfigurationLabelKey(hmi::NEIGHBOR_UP). |
| TileAutotileTest.AssemblageTroisParTroisPlaceLInterieurPleinAuCentre (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:252 | L'assemblage 3x3 place l'interieur plein au centre. | 1. Produire les neuf masques de l'assemblage. 2. Verifier la case centrale et la diversite des masques. | Vérifie que masks[4] vaut fullMask. Vérifie que distinctMasks.size() est strictement supérieur à 1U. |
| TileAutotileTest.AssemblageResoutDesCasesValidesViaLaTableCanonique (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_autotile.cpp:275 | Chaque masque de l'assemblage resout une case valide de la planche. | 1. Resoudre la case de chacun des neuf masques via autotileCell. | Vérifie que cell.column est supérieur ou égal à 0. Vérifie que cell.column est strictement inférieur à hmi::AUTOTILE_SHEET_SIDE. Vérifie que cell.row est supérieur ou égal à 0. Vérifie que cell.row est strictement inférieur à hmi::AUTOTILE_SHEET_SIDE. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| TileSkinResolutionTest.ModePhysiqueIgnoreLesSkins (Critique) Source/Test/Unit/HMI/Graphics/test_tile_skin_resolution.cpp:67 | Le mode Physique rend la region d'atlas meme quand un skin est assigne. | 1. Resoudre une tuile Solid skinnee, en mode Physique. | Vérifie que appearance.source vaut hmi::AppearanceSource::Atlas. Vérifie que appearance.region.x vaut physical.x. Vérifie que appearance.region.y vaut physical.y. |
| TileSkinResolutionTest.SkinSingleRendLImageEntiere (Critique) Source/Test/Unit/HMI/Graphics/test_tile_skin_resolution.cpp:92 | Un skin en mode image unique rend l'image entiere. | 1. Resoudre une tuile Block, assignee a un skin en mode single, en mode Texture. | Vérifie que appearance.source vaut hmi::AppearanceSource::Skin. Vérifie que appearance.region.x vaut 0. Vérifie que appearance.region.y vaut 0. Vérifie que appearance.region.width vaut TILE. Vérifie que appearance.region.height vaut TILE. Vérifie que textures.textureFor(appearance) vaut &crateStorage. |
| TileSkinResolutionTest.SkinBitmaskChoisitSaCase (Critique) Source/Test/Unit/HMI/Graphics/test_tile_skin_resolution.cpp:121 | Un skin a raccords choisit sa case selon le voisinage solide. | 1. Resoudre une tuile Solid entouree de solide, puis la meme isolee. | Vérifie que insideAppearance.source vaut hmi::AppearanceSource::Skin. Vérifie que aloneAppearance.source vaut hmi::AppearanceSource::Skin. Vérifie que textures.textureFor(insideAppearance) vaut &stoneStorage. Vérifie que insideAppearance.region.x vaut fullCell.column * TILE. Vérifie que insideAppearance.region.y vaut fullCell.row * TILE. Vérifie que aloneAppearance.region.x vaut 0. Vérifie que aloneAppearance.region.y vaut 0. Vérifie que insideAppearance.region.x diffère de aloneAppearance.region.x. |
| TileSkinResolutionTest.TypeNonSkinneRetombeSurLeDamier (Critique) Source/Test/Unit/HMI/Graphics/test_tile_skin_resolution.cpp:163 | Un type de tuile sans skin assigne retombe sur le damier. | 1. Resoudre une tuile Danger, absente du catalogue, en mode Texture. | Vérifie que appearance.source vaut hmi::AppearanceSource::MissingTexture. Vérifie que appearance.region.width vaut hmi::MISSING_TEXTURE_SIZE. Vérifie que textures.textureFor(appearance) vaut &missingStorage. |
| TileSkinResolutionTest.SkinNonChargeRetombeSurLeDamier (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_skin_resolution.cpp:189 | Un skin assigne dont la texture n'est pas chargee retombe sur le damier. | 1. Assigner un asset absent des textures chargees, puis resoudre en mode Texture. | Vérifie que appearance.source vaut hmi::AppearanceSource::MissingTexture. |
| TileSkinResolutionTest.SansCatalogueToutRetombeSurLeDamier (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_skin_resolution.cpp:215 | En l'absence de catalogue de skins, tout retombe sur le damier. | 1. Resoudre une tuile Solid avec des textures sans catalogue. | Vérifie que appearance.source vaut hmi::AppearanceSource::MissingTexture. |
| TileSkinResolutionTest.IndexDeSkinInvalideBorne (Majeur) Source/Test/Unit/HMI/Graphics/test_tile_skin_resolution.cpp:238 | Un index de skin invalide retombe sur le damier sans lecture hors bornes. | 1. Interroger les textures avec une apparence portant un index hors bornes. | Vérifie que textures.textureFor(broken) vaut &missingStorage. Vérifie que textures.widthFor(broken) vaut hmi::MISSING_TEXTURE_SIZE. Vérifie que textures.heightFor(broken) vaut hmi::MISSING_TEXTURE_SIZE. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EditorKeyBindingsTest.ValeursParDefautALaConstruction (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:19 | Les dix actions ont leurs valeurs par défaut (S/Z/Y/C/V/P/F10/F1/F2/T) à la construction. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::EditorAction::Save) vaut hmi::Key::S. Vérifie que bindings.key(hmi::EditorAction::Undo) vaut hmi::Key::Z. Vérifie que bindings.key(hmi::EditorAction::Redo) vaut hmi::Key::Y. Vérifie que bindings.key(hmi::EditorAction::Copy) vaut hmi::Key::C. Vérifie que bindings.key(hmi::EditorAction::Paste) vaut hmi::Key::V. Vérifie que bindings.key(hmi::EditorAction::Playtest) vaut hmi::Key::P. Vérifie que bindings.key(hmi::EditorAction::ToggleGrid) vaut hmi::Key::F10. Vérifie que bindings.key(hmi::EditorAction::ToggleHelp) vaut hmi::Key::F1. Vérifie que bindings.key(hmi::EditorAction::Rename) vaut hmi::Key::F2. Vérifie que bindings.key(hmi::EditorAction::TextureAssignTool) vaut hmi::Key::T. |
| EditorKeyBindingsTest.SetKeyEchangeSurConflit (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:45 | setKey sur une touche déjà liée à une autre action échange les deux touches. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::EditorAction::Rename) vaut hmi::Key::S. Vérifie que bindings.key(hmi::EditorAction::Save) vaut hmi::Key::F2. |
| EditorKeyBindingsTest.SetKeyEchangeAvecTextureAssignTool (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:64 | setKey echange correctement quand TextureAssignTool est impliquee. | 1. Remapper TextureAssignTool sur la touche par defaut de Playtest. 2. Verifier l'echange. | Vérifie que bindings.key(hmi::EditorAction::TextureAssignTool) vaut hmi::Key::P. Vérifie que bindings.key(hmi::EditorAction::Playtest) vaut hmi::Key::T. |
| EditorKeyBindingsTest.ResetToDefaultsRestaureLesDefauts (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:81 | resetToDefaults restaure les valeurs par défaut après un ou plusieurs remaps. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::EditorAction::Playtest) vaut hmi::Key::P. |
| EditorKeyBindingsTest.SaveEtLoadAllerRetour (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:99 | Sauvegarder puis recharger préserve un jeu de bindings personnalisé (aller-retour JSON). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que original.save(path) est vrai. Vérifie que reloaded.key(hmi::EditorAction::Playtest) vaut hmi::Key::F1. Vérifie que reloaded.key(hmi::EditorAction::Save) vaut hmi::Key::S. |
| EditorKeyBindingsTest.LoadFichierAbsentRenvoieLesDefauts (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:127 | Charger depuis un fichier absent renvoie les valeurs par défaut, sans erreur. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::EditorAction::Save) vaut hmi::Key::S. |
| EditorKeyBindingsTest.SavePreserveLaSectionJeu (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:147 | Sauvegarder les touches d'éditeur préserve une section « jeu » déjà présente. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.save(path) est vrai. Vérifie que content.find("\\"jeu\\\\"\")</tt> diffère de <tt>std::string::npos</tt>.<br/>Vérifie que <tt>content.find(\"sauter\") diffère de std::string::npos. |
| EditorKeyBindingsTest.SavePreserveLaSectionManette (Majeur) Source/Test/Unit/HMI/Input/test_editor_key_bindings.cpp:181 | Sauvegarder les touches d'editeur preserve une section manette deja presente. | 1. Ecrire un fichier avec une section manette. 2. Sauvegarder des touches d'editeur dessus. 3. Relire le fichier. | Vérifie que bindings.save(path) est vrai. Vérifie que content.find("\\"manette\\\\"\")</tt> diffère de <tt>std::string::npos</tt>.<br/>Vérifie que <tt>content.find(\"sauter\") diffère de std::string::npos. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| GameKeyBindingsTest.ValeursParDefautALaConstruction (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:18 | Les sept actions ont leurs valeurs par défaut (flèches/Espace/Maj/E) à la construction. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::MoveLeft) vaut hmi::Key::Left. Vérifie que bindings.key(hmi::GameAction::MoveRight) vaut hmi::Key::Right. Vérifie que bindings.key(hmi::GameAction::AimUp) vaut hmi::Key::Up. Vérifie que bindings.key(hmi::GameAction::AimDown) vaut hmi::Key::Down. Vérifie que bindings.key(hmi::GameAction::Jump) vaut hmi::Key::Space. Vérifie que bindings.key(hmi::GameAction::Dash) vaut hmi::Key::Shift. Vérifie que bindings.key(hmi::GameAction::Interact) vaut hmi::Key::E. |
| GameKeyBindingsTest.SetKeySurToucheLibre (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:41 | setKey sur une touche libre lie l'action sans toucher aux autres. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::Jump) vaut hmi::Key::F1. Vérifie que bindings.key(hmi::GameAction::MoveLeft) vaut hmi::Key::Left. |
| GameKeyBindingsTest.SetKeyEchangeSurConflit (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:58 | setKey sur une touche déjà liée à une autre action échange les deux touches. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::Jump) vaut hmi::Key::Left. Vérifie que bindings.key(hmi::GameAction::MoveLeft) vaut hmi::Key::Space. |
| GameKeyBindingsTest.ResetToDefaultsRestaureLesDefauts (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:77 | resetToDefaults restaure les valeurs par défaut après un ou plusieurs remaps. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::Jump) vaut hmi::Key::Space. Vérifie que bindings.key(hmi::GameAction::Dash) vaut hmi::Key::Shift. |
| GameKeyBindingsTest.SaveEtLoadAllerRetour (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:97 | Sauvegarder puis recharger préserve un jeu de bindings personnalisé (aller-retour JSON). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que original.save(path) est vrai. Vérifie que reloaded.key(hmi::GameAction::Jump) vaut hmi::Key::F1. Vérifie que reloaded.key(hmi::GameAction::Dash) vaut hmi::Key::F2. Vérifie que reloaded.key(hmi::GameAction::MoveLeft) vaut hmi::Key::Left. |
| GameKeyBindingsTest.LoadFichierAbsentRenvoieLesDefauts (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:127 | Charger depuis un fichier absent renvoie les valeurs par défaut, sans erreur. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::MoveLeft) vaut hmi::Key::Left. Vérifie que bindings.key(hmi::GameAction::Jump) vaut hmi::Key::Space. |
| GameKeyBindingsTest.LoadJsonCorrompuRenvoieLesDefauts (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:148 | Charger un fichier JSON corrompu renvoie les valeurs par défaut, sans exception. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::MoveLeft) vaut hmi::Key::Left. |
| GameKeyBindingsTest.LoadValeurHorsBornesIgnoree (Mineur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:173 | Une valeur hors bornes dans le fichier est ignorée : l'action garde sa valeur par défaut. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::Jump) vaut hmi::Key::Space. |
| GameKeyBindingsTest.LoadFichierAnterieurSansInteragirPrendLaValeurParDefaut (Bloquant) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:200 | Un fichier écrit avant ce lot (sans « interagir ») se relit sans erreur, l'action prenant sa valeur par défaut. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.key(hmi::GameAction::Interact) vaut hmi::Key::E. Vérifie que bindings.key(hmi::GameAction::Jump) vaut hmi::Key::Space. |
| GameKeyBindingsTest.SavePreserveLaSectionEditeur (Majeur) Source/Test/Unit/HMI/Input/test_game_key_bindings.cpp:229 | Sauvegarder les touches de jeu préserve une section « editeur » déjà présente. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.save(path) est vrai. Vérifie que content.find("editeur") diffère de std::string::npos. Vérifie que content.find("sauvegarder") diffère de std::string::npos. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| GamepadBindingsTest.ValeursParDefautALaConstruction (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:19 | Les sept actions ont leurs boutons par défaut à la construction. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.button(hmi::GameAction::MoveLeft) vaut hmi::GamepadButton::Left. Vérifie que bindings.button(hmi::GameAction::MoveRight) vaut hmi::GamepadButton::Right. Vérifie que bindings.button(hmi::GameAction::AimUp) vaut hmi::GamepadButton::Up. Vérifie que bindings.button(hmi::GameAction::AimDown) vaut hmi::GamepadButton::Down. Vérifie que bindings.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::A. Vérifie que bindings.button(hmi::GameAction::Dash) vaut hmi::GamepadButton::RightShoulder. Vérifie que bindings.button(hmi::GameAction::Interact) vaut hmi::GamepadButton::X. |
| GamepadBindingsTest.SetKeySurBoutonLibre (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:40 | setKey sur un bouton libre lie l'action sans toucher aux autres. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::X. Vérifie que bindings.button(hmi::GameAction::MoveLeft) vaut hmi::GamepadButton::Left. |
| GamepadBindingsTest.SetKeyEchangeSurConflit (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:57 | setKey sur un bouton déjà lié à une autre action échange les deux boutons. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::RightShoulder. Vérifie que bindings.button(hmi::GameAction::Dash) vaut hmi::GamepadButton::A. |
| GamepadBindingsTest.ResetToDefaultsRestaureLesDefauts (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:75 | resetToDefaults restaure les valeurs par défaut après un ou plusieurs remaps. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::A. Vérifie que bindings.button(hmi::GameAction::Dash) vaut hmi::GamepadButton::RightShoulder. |
| GamepadBindingsTest.SaveEtLoadAllerRetour (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:95 | Sauvegarder puis recharger préserve un jeu de bindings personnalisé (aller-retour JSON). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que original.save(path) est vrai. Vérifie que reloaded.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::X. Vérifie que reloaded.button(hmi::GameAction::Dash) vaut hmi::GamepadButton::Y. Vérifie que reloaded.button(hmi::GameAction::MoveLeft) vaut hmi::GamepadButton::Left. |
| GamepadBindingsTest.LoadFichierAbsentRenvoieLesDefauts (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:125 | Charger depuis un fichier absent renvoie les valeurs par défaut, sans erreur. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::A. |
| GamepadBindingsTest.LoadNomBoutonInconnuIgnore (Mineur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:146 | Un nom de bouton inconnu est ignoré : l'action garde sa valeur par défaut. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::A. |
| GamepadBindingsTest.LoadFichierAnterieurSansInteragirPrendLaValeurParDefaut (Bloquant) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:171 | Un fichier écrit avant ce lot (sans « interagir ») se relit sans erreur, l'action prenant son bouton par défaut. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.button(hmi::GameAction::Interact) vaut hmi::GamepadButton::X. Vérifie que bindings.button(hmi::GameAction::Jump) vaut hmi::GamepadButton::A. |
| GamepadBindingsTest.SavePreserveLesAutresSections (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_bindings.cpp:201 | Sauvegarder les bindings manette préserve les sections « jeu »/« editeur » déjà présentes. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que bindings.save(path) est vrai. Vérifie que content.find("\\"jeu\\\\"\")</tt> diffère de <tt>std::string::npos</tt>.<br/>Vérifie que <tt>content.find(\"\\\\"editeur\\\\"\")</tt> diffère de <tt>std::string::npos</tt>.<br/>Vérifie que <tt>content.find(\"\\\\"manette\\\\"\") diffère de std::string::npos. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| GamepadButtonNameTest.ChaqueBoutonALibelleDedie (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_button_name.cpp:17 | Chaque bouton manette a un libellé lisible dédié. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::gamepadButtonDisplayName(hmi::GamepadButton::A) vaut "A". Vérifie que hmi::gamepadButtonDisplayName(hmi::GamepadButton::Left) vaut "Gauche". Vérifie que hmi::gamepadButtonDisplayName(hmi::GamepadButton::RightShoulder) vaut "Epaule droite". |
| GamepadButtonNameTest.CapturedGamepadButtonRenvoieLeBoutonEnfonce (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_button_name.cpp:33 | capturedGamepadButton renvoie le bouton pressé à la frame courante. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que captured.has_value() est vrai. Vérifie que *captured vaut hmi::GamepadButton::X. |
| GamepadButtonNameTest.CapturedGamepadButtonVideSansBouton (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_button_name.cpp:51 | capturedGamepadButton renvoie vide quand aucun bouton n'est pressé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::capturedGamepadButton(input).has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| GamepadProbeTest.ManetteConnecteeSondeeAChaqueAppel (Critique) Source/Test/Unit/HMI/Input/test_gamepad_probe.cpp:19 | Une manette connectee est sondee a chaque appel. | 1. Demander la decision avec une manette connectee et un delai nul. | Vérifie que hmi::gamepadProbeDue(/*wasConnected=*/true, 0ms) est vrai. Vérifie que hmi::gamepadProbeDue(/*wasConnected=*/true, 1ms) est vrai. |
| GamepadProbeTest.ManetteAbsenteReSondeeApresLeDelai (Critique) Source/Test/Unit/HMI/Input/test_gamepad_probe.cpp:34 | Une manette absente n'est re-sondee qu'apres le delai d'anti-saccade. | 1. Demander la decision juste avant le delai, puis juste apres. | Vérifie que hmi::gamepadProbeDue(/*wasConnected=*/false, 0ms) est faux. Vérifie que hmi::gamepadProbeDue(/*wasConnected=*/false, hmi::GAMEPAD_DISCONNECTED_PROBE_PERIOD - 1ms) est faux. Vérifie que hmi::gamepadProbeDue(/*wasConnected=*/false, hmi::GAMEPAD_DISCONNECTED_PROBE_PERIOD) est vrai. |
| GamepadProbeTest.DelaiIndependantDeLaCadenceDAppel (Majeur) Source/Test/Unit/HMI/Input/test_gamepad_probe.cpp:53 | Le delai de detection ne depend pas de la cadence de l'appelant. | 1. Simuler des appels espaces de 500 ms et compter ceux qui precedent le premier sondage du. 2. Recommencer avec des appels espaces de 16 ms (cadence de rendu). | Vérifie que firstDueAfter(500ms) est inférieur ou égal à hmi::GAMEPAD_DISCONNECTED_PROBE_PERIOD + 500ms. Vérifie que firstDueAfter(16ms) est inférieur ou égal à hmi::GAMEPAD_DISCONNECTED_PROBE_PERIOD + 16ms. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| InputStateTest.FrontMontantClavier (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:15 | Une touche passée d'« absente » à « présente » est « pressée » exactement une frame. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyDown(hmi::Key::Enter) est vrai. Vérifie que input.keyPressed(hmi::Key::Enter) est vrai. Vérifie que input.keyReleased(hmi::Key::Enter) est faux. Vérifie que input.keyDown(hmi::Key::Enter) est vrai. Vérifie que input.keyPressed(hmi::Key::Enter) est faux. |
| InputStateTest.MaintienClavier (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:41 | Une touche restée enfoncée n'est « pressée » qu'à la première frame. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyPressed(hmi::Key::Down) est vrai. Vérifie que input.keyDown(hmi::Key::Down) est vrai. Vérifie que input.keyPressed(hmi::Key::Down) est faux. Vérifie que input.keyReleased(hmi::Key::Down) est faux. |
| InputStateTest.FrontDescendantClavier (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:66 | Le relâchement d'une touche est détecté « relâchée » pendant exactement une frame. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyDown(hmi::Key::Space) est faux. Vérifie que input.keyReleased(hmi::Key::Space) est vrai. Vérifie que input.keyReleased(hmi::Key::Space) est faux. |
| InputStateTest.TouchesIndependantes (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:93 | Les touches sont indépendantes : un front sur l'une n'affecte pas les autres. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyPressed(hmi::Key::Up) est vrai. Vérifie que input.keyDown(hmi::Key::Down) est faux. Vérifie que input.keyPressed(hmi::Key::Down) est faux. |
| InputStateTest.BoutonSouris (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:114 | Un bouton de souris suit la même logique pressé/cliqué/relâché que les touches. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.mouseButtonDown(hmi::MouseButton::Left) est vrai. Vérifie que input.mouseButtonPressed(hmi::MouseButton::Left) est vrai. Vérifie que input.mouseButtonDown(hmi::MouseButton::Left) est vrai. Vérifie que input.mouseButtonPressed(hmi::MouseButton::Left) est faux. Vérifie que input.mouseButtonDown(hmi::MouseButton::Left) est faux. Vérifie que input.mouseButtonReleased(hmi::MouseButton::Left) est vrai. |
| InputStateTest.PositionSouris (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:143 | La position de la souris reflète le dernier déplacement injecté. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.mouseX() vaut 42. Vérifie que input.mouseY() vaut 99. Vérifie que input.mouseX() vaut -3. Vérifie que input.mouseY() vaut 7. |
| InputStateTest.MoletteAccumuleEtSeReinitialise (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:165 | Les incréments de molette d'une frame s'additionnent et repartent de zéro ensuite. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.wheelDelta() vaut 0. Vérifie que input.wheelDelta() vaut 80. Vérifie que input.wheelDelta() vaut 0. |
| InputStateTest.CaracteresTapesAccumulesEtVides (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:189 | Les caractères tapés s'accumulent dans l'ordre puis sont vidés à la frame suivante. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.typedCharacters().empty() est vrai. Vérifie que input.typedCharacters().size() vaut 3u. Vérifie que input.typedCharacters()[0] vaut L'N'. Vérifie que input.typedCharacters()[1] vaut L'1'. Vérifie que input.typedCharacters()[2] vaut L'\\xE9'. Vérifie que input.typedCharacters().empty() est vrai. |
| InputStateTest.ManetteSeuleActiveLaTouche (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:218 | Un bouton manette seul rend keyDown/keyPressed vrais, comme au clavier. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyDown(hmi::Key::Enter) est vrai. Vérifie que input.keyPressed(hmi::Key::Enter) est vrai. Vérifie que input.keyDown(hmi::Key::Enter) est vrai. Vérifie que input.keyPressed(hmi::Key::Enter) est faux. Vérifie que input.keyDown(hmi::Key::Enter) est faux. Vérifie que input.keyReleased(hmi::Key::Enter) est vrai. |
| InputStateTest.ClavierEtManetteMemeToucheUnSeulFront (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:246 | Clavier et manette combinés sur la même touche ne produisent pas de double front. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyPressed(hmi::Key::Space) est vrai. Vérifie que input.keyPressed(hmi::Key::Space) est faux. Vérifie que input.keyDown(hmi::Key::Space) est vrai. Vérifie que input.keyReleased(hmi::Key::Space) est faux. Vérifie que input.keyDown(hmi::Key::Space) est faux. Vérifie que input.keyReleased(hmi::Key::Space) est vrai. |
| InputStateTest.ManetteRelacheeNeMasquePasLeClavier (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:283 | La manette relâchée ne masque jamais une touche clavier réellement maintenue. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyDown(hmi::Key::Left) est vrai. Vérifie que input.keyDown(hmi::Key::Left) est vrai. Vérifie que input.keyReleased(hmi::Key::Left) est faux. |
| InputStateTest.GamepadConnecteReecrasable (Mineur) Source/Test/Unit/HMI/Input/test_input_state.cpp:311 | gamepadConnected reflète le dernier setGamepadConnected appelé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.gamepadConnected() est faux. Vérifie que input.gamepadConnected() est vrai. Vérifie que input.gamepadConnected() est faux. |
| InputStateTest.FrontMontantBoutonManetteBrut (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:333 | Un bouton manette (piste brute) est « pressé » exactement une frame. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.gamepadButtonDown(hmi::GamepadButton::A) est vrai. Vérifie que input.gamepadButtonPressed(hmi::GamepadButton::A) est vrai. Vérifie que input.gamepadButtonDown(hmi::GamepadButton::A) est vrai. Vérifie que input.gamepadButtonPressed(hmi::GamepadButton::A) est faux. Vérifie que input.gamepadButtonDown(hmi::GamepadButton::A) est faux. |
| InputStateTest.FrontDescendantBoutonManetteBrut (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:360 | Un bouton manette (piste brute) est « relâché » exactement une frame. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.gamepadButtonReleased(hmi::GamepadButton::X) est faux. Vérifie que input.gamepadButtonReleased(hmi::GamepadButton::X) est vrai. Vérifie que input.gamepadButtonReleased(hmi::GamepadButton::X) est faux. |
| InputStateTest.PisteBrutIndependanteDeLaFusionKey (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:386 | La piste manette brute est indépendante de la fusion clavier/manette sur Key. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.keyDown(hmi::Key::Enter) est faux. Vérifie que input.gamepadButtonDown(hmi::GamepadButton::B) est faux. |
| InputStateTest.RelacheToutSansFront (Majeur) Source/Test/Unit/HMI/Input/test_input_state.cpp:409 | releaseAll relâche tout sans produire de front « relâchée ». | 1. Maintenir des entrées clavier/manette/souris. 2. Appeler releaseAll et verifier qu'aucune n'est plus enfoncee ni signalee « relâchée ». | Vérifie que input.keyDown(hmi::Key::Right) est faux. Vérifie que input.keyReleased(hmi::Key::Right) est faux. Vérifie que input.keyDown(hmi::Key::Space) est faux. Vérifie que input.keyReleased(hmi::Key::Space) est faux. Vérifie que input.gamepadButtonDown(hmi::GamepadButton::A) est faux. Vérifie que input.mouseButtonDown(hmi::MouseButton::Left) est faux. Vérifie que input.mouseButtonReleased(hmi::MouseButton::Left) est faux. Vérifie que input.keyReleased(hmi::Key::Right) est faux. Vérifie que input.keyPressed(hmi::Key::Right) est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| KeyNameTest.ToucheNommeeLibelleDedie (Majeur) Source/Test/Unit/HMI/Input/test_key_name.cpp:16 | Une touche nommée de l'énumération a un libellé lisible dédié. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::keyDisplayName(hmi::Key::Left) vaut "Fleche gauche". Vérifie que hmi::keyDisplayName(hmi::Key::Space) vaut "Espace". Vérifie que hmi::keyDisplayName(hmi::Key::Shift) vaut "Maj". Vérifie que hmi::keyDisplayName(hmi::Key::F10) vaut "F10". |
| KeyNameTest.LettreNonNommeeAfficheSonCaractere (Mineur) Source/Test/Unit/HMI/Input/test_key_name.cpp:33 | Une lettre ou un chiffre non nommé explicitement s'affiche par son propre caractère. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::keyDisplayName(static_cast<hmi::Key>('B')) vaut "B". Vérifie que hmi::keyDisplayName(static_cast<hmi::Key>('5')) vaut "5". |
| KeyNameTest.ToucheInconnueRepliHexadecimal (Mineur) Source/Test/Unit/HMI/Input/test_key_name.cpp:50 | Une touche totalement inconnue s'affiche via un repli hexadécimal. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::keyDisplayName(static_cast<hmi::Key>(0x12)) vaut "Touche 0x12". |
| KeyNameTest.CapturedKeyRenvoieLaToucheEnfoncee (Majeur) Source/Test/Unit/HMI/Input/test_key_name.cpp:64 | capturedKey renvoie la touche pressée à la frame courante. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que captured.has_value() est vrai. Vérifie que *captured vaut hmi::Key::F1. |
| KeyNameTest.CapturedKeyVideSansTouche (Majeur) Source/Test/Unit/HMI/Input/test_key_name.cpp:82 | capturedKey renvoie vide quand aucune touche n'est pressée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::capturedKey(input).has_value() est faux. |
| KeyNameTest.EchapEtEntreeReserveesNonCapturees (Majeur) Source/Test/Unit/HMI/Input/test_key_name.cpp:97 | Échap et Entrée sont réservées : leur pression seule ne capture rien. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::capturedKey(escapeOnly).has_value() est faux. Vérifie que hmi::capturedKey(enterOnly).has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| PlayerInputMapperTest.FlecheGauche (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:46 | Flèche gauche seule → intention vers la gauche (-1). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapWithDefaults(withKeys({hmi::Key::Left})).moveX vaut -1.0f (comparaison flottante). |
| PlayerInputMapperTest.FlecheDroite (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:60 | Flèche droite seule → intention vers la droite (+1). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapWithDefaults(withKeys({hmi::Key::Right})).moveX vaut 1.0f (comparaison flottante). |
| PlayerInputMapperTest.SansRemapQDWNeDeclenchentRien (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:74 | Sans remap, Q/D/W ne déclenchent rien (aucun alias fixe). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapWithDefaults(withKeys({hmi::Key::Q})).moveX vaut 0.0f (comparaison flottante). Vérifie que mapWithDefaults(withKeys({hmi::Key::D})).moveX vaut 0.0f (comparaison flottante). Vérifie que mapWithDefaults(withKeys({hmi::Key::W})).jumpPressed est faux. |
| PlayerInputMapperTest.AucuneTouche (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:90 | Aucune touche → intention nulle (immobile). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapWithDefaults(hmi::InputState{}).moveX vaut 0.0f (comparaison flottante). |
| PlayerInputMapperTest.GaucheEtDroiteSeNeutralisent (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:104 | Gauche et droite simultanées → neutralisation (0). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapWithDefaults(withKeys({hmi::Key::Left, hmi::Key::Right})).moveX vaut 0.0f (comparaison flottante). |
| PlayerInputMapperTest.EspacePresseeDeclencheLeSaut (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:118 | Espace fraîchement enfoncée → saut pressé (front) et maintenu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.jumpPressed est vrai. Vérifie que input.jumpHeld est vrai. |
| PlayerInputMapperTest.SautMaintenuN_estPasUnFront (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:134 | Saut maintenu sans nouveau front → jumpHeld vrai mais jumpPressed faux. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapped.jumpPressed est faux. Vérifie que mapped.jumpHeld est vrai. |
| PlayerInputMapperTest.PasDeSaut (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:156 | Aucune touche de saut → ni pressé ni maintenu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.jumpPressed est faux. Vérifie que input.jumpHeld est faux. |
| PlayerInputMapperTest.DeplacementEtSautIndependants (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:172 | Déplacement et saut sont indépendants (axes distincts). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.moveX vaut 1.0f (comparaison flottante). Vérifie que input.jumpPressed est vrai. |
| PlayerInputMapperTest.MajDeclencheLeDash (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:188 | Maj fraîchement enfoncée → dash pressé (front). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapWithDefaults(withKeys({hmi::Key::Shift})).dashPressed est vrai. Vérifie que mapWithDefaults(hmi::InputState{}).dashPressed est faux. |
| PlayerInputMapperTest.ViseeVerticale (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:203 | Visée verticale (y vers le bas) : Bas → +1, Haut → -1, les deux → 0. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapWithDefaults(withKeys({hmi::Key::Down})).moveY vaut 1.0f (comparaison flottante). Vérifie que mapWithDefaults(withKeys({hmi::Key::Up})).moveY vaut -1.0f (comparaison flottante). Vérifie que mapWithDefaults(withKeys({hmi::Key::Up, hmi::Key::Down})).moveY vaut 0.0f (comparaison flottante). |
| PlayerInputMapperTest.RemapperUneActionClavierUtiliseLaNouvelleTouche (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:219 | Une action remappée au clavier réagit à sa nouvelle touche. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::toPlayerInput(withKeys({hmi::Key::F1}), gameKeyBindings, hmi::GamepadBindings{}) .dashPressed est vrai. |
| PlayerInputMapperTest.RemapperGaucheEtDroiteSurDesTouchesDistinctesNeLesAnnulePas (Bloquant) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:239 | Remapper Gauche et Droite sur des touches distinctes ne les neutralise pas l'une l'autre. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::toPlayerInput(withKeys({hmi::Key::D}), bindings, gamepadBindings).moveX vaut -1.0f (comparaison flottante). Vérifie que hmi::toPlayerInput(withKeys({hmi::Key::Q}), bindings, gamepadBindings).moveX vaut 1.0f (comparaison flottante). |
| PlayerInputMapperTest.ActionDeclencheeParSonBoutonManetteParDefaut (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:266 | Une action est déclenchée par son bouton manette lié. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.jumpPressed est vrai. |
| PlayerInputMapperTest.RemapperUneActionManetteUtiliseLeNouveauBouton (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:282 | Une action remappée manette réagit à son nouveau bouton, le clavier reste indépendant. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::toPlayerInput(withGamepadButton(hmi::GamepadButton::X), hmi::GameKeyBindings{}, gamepadBindings) .jumpPressed est vrai. Vérifie que mapWithDefaults(withKeys({hmi::Key::Space})).jumpPressed est vrai. |
| PlayerInputMapperTest.RemapperGaucheEtDroiteManetteSurDesBoutonsDistinctsNeLesAnnulePas (Bloquant) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:307 | Remapper deux actions manette sur des boutons distincts ne les neutralise pas l'une l'autre. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::toPlayerInput(withGamepadButton(hmi::GamepadButton::X), gameKeyBindings, gamepadBindings) .moveX vaut -1.0f (comparaison flottante). Vérifie que hmi::toPlayerInput(withGamepadButton(hmi::GamepadButton::Y), gameKeyBindings, gamepadBindings) .moveX vaut 1.0f (comparaison flottante). |
| PlayerInputMapperTest.EPresseeDeclencheInteragir (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:335 | E fraîchement enfoncée → Interagir pressé (front) et maintenu. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que pressed.interactPressed est vrai. Vérifie que pressed.interactHeld est vrai. Vérifie que pressed.interactReleased est faux. Vérifie que none.interactPressed est faux. Vérifie que none.interactHeld est faux. |
| PlayerInputMapperTest.InteragirMaintenuN_estPasUnFront (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:357 | Interagir maintenu sans nouveau front → interactHeld vrai mais interactPressed faux. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que mapped.interactPressed est faux. Vérifie que mapped.interactHeld est vrai. |
| PlayerInputMapperTest.RelacherEDeclencheInteragirRelache (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:380 | Relâcher E produit le front interactReleased, une frame seulement. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que released.interactReleased est vrai. Vérifie que released.interactHeld est faux. Vérifie que settled.interactReleased est faux. |
| PlayerInputMapperTest.BoutonXManetteDeclencheInteragir (Majeur) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:407 | Interagir se déclenche via son bouton manette par défaut (X). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que input.interactPressed est vrai. |
| PlayerInputMapperTest.RemapperInteragirUtiliseLaNouvelleSource (Bloquant) Source/Test/Unit/HMI/Input/test_player_input_mapper.cpp:425 | Remapper Interagir réagit à la nouvelle touche/bouton. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que hmi::toPlayerInput(withKeys({hmi::Key::F1}), gameKeyBindings, hmi::GamepadBindings{}) .interactPressed est vrai. Vérifie que hmi::toPlayerInput(withGamepadButton(hmi::GamepadButton::Y), hmi::GameKeyBindings{}, gamepadBindings) .interactPressed est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| QtKeyMapTest.AllerRetourExactSurToutesLesTouches (Bloquant) Source/Test/Unit/HMI/Input/test_qt_key_map.cpp:45 | Aller-retour hmi::Key -> Qt -> hmi::Key exact sur toutes les touches nommées. | 1. Pour chaque touche de hmi::Key, appliquer hmiKeyToQtKey puis qtKeyToHmiKey. | Vérifie que roundTrip.has_value() est vrai. Vérifie que *roundTrip vaut key. |
| QtKeyMapTest.TouchesSpecialesTraduitesExplicitement (Majeur) Source/Test/Unit/HMI/Input/test_qt_key_map.cpp:65 | Touches spéciales traduites explicitement. | 1. Traduire Échap, Espace, les quatre flèches et F10 dans les deux sens. | Vérifie que hmi::hmiKeyToQtKey(hmi::Key::Escape) vaut static_cast<int>(Qt::Key_Escape). Vérifie que hmi::hmiKeyToQtKey(hmi::Key::Space) vaut static_cast<int>(Qt::Key_Space). Vérifie que hmi::hmiKeyToQtKey(hmi::Key::Left) vaut static_cast<int>(Qt::Key_Left). Vérifie que hmi::hmiKeyToQtKey(hmi::Key::Down) vaut static_cast<int>(Qt::Key_Down). Vérifie que hmi::hmiKeyToQtKey(hmi::Key::F10) vaut static_cast<int>(Qt::Key_F10). Vérifie que hmi::qtKeyToHmiKey(Qt::Key_Escape) vaut std::optional<hmi::Key>(hmi::Key::Escape). Vérifie que hmi::qtKeyToHmiKey(Qt::Key_Up) vaut std::optional<hmi::Key>(hmi::Key::Up). Vérifie que hmi::qtKeyToHmiKey(Qt::Key_F1) vaut std::optional<hmi::Key>(hmi::Key::F1). |
| QtKeyMapTest.LettresEtChiffresConvertisDirectement (Majeur) Source/Test/Unit/HMI/Input/test_qt_key_map.cpp:86 | Lettres et chiffres : conversion directe Qt <-> Win32. | 1. Traduire Qt::Key_A, Qt::Key_Z, Qt::Key_0 et Qt::Key_9. | Vérifie que hmi::qtKeyToHmiKey(Qt::Key_A) vaut std::optional<hmi::Key>(hmi::Key::A). Vérifie que hmi::qtKeyToHmiKey(Qt::Key_Z) vaut std::optional<hmi::Key>(hmi::Key::Z). Vérifie que hmi::qtKeyToHmiKey(Qt::Key_0) vaut std::optional<hmi::Key>(hmi::Key::D0). Vérifie que nine.has_value() est vrai. Vérifie que static_cast<int>(*nine) vaut static_cast<int>(Qt::Key_9). |
| QtKeyMapTest.SynonymesRejoignentLaFormeCanonique (Mineur) Source/Test/Unit/HMI/Input/test_qt_key_map.cpp:110 | Backtab et Enter du pavé rejoignent la forme canonique. | 1. Traduire Qt::Key_Backtab et Qt::Key_Enter. 2. Retraduire le résultat. | Vérifie que hmi::qtKeyToHmiKey(Qt::Key_Backtab) vaut std::optional<hmi::Key>(hmi::Key::Tab). Vérifie que hmi::qtKeyToHmiKey(Qt::Key_Enter) vaut std::optional<hmi::Key>(hmi::Key::Enter). Vérifie que hmi::hmiKeyToQtKey(hmi::Key::Tab) vaut static_cast<int>(Qt::Key_Tab). Vérifie que hmi::hmiKeyToQtKey(hmi::Key::Enter) vaut static_cast<int>(Qt::Key_Return). |
| QtKeyMapTest.ToucheNonSuivieRendNullopt (Majeur) Source/Test/Unit/HMI/Input/test_qt_key_map.cpp:126 | Touche non suivie -> nullopt. | 1. Traduire Qt::Key_F5, Qt::Key_Alt, Qt::Key_Home et une valeur hors intervalle. | Vérifie que hmi::qtKeyToHmiKey(Qt::Key_F5).has_value() est faux. Vérifie que hmi::qtKeyToHmiKey(Qt::Key_Alt).has_value() est faux. Vérifie que hmi::qtKeyToHmiKey(Qt::Key_Home).has_value() est faux. Vérifie que hmi::qtKeyToHmiKey(-1).has_value() est faux. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ApplicationThemeTest.SubstitutionRemplaceTousLesMarqueurs (Critique) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:54 | La substitution remplace tous les marqueurs du modele. | 1. Substituer un modele avec deux marqueurs connus. | Vérifie que result.ok est vrai. Vérifie que result.text vaut "x: 1; y: 2;". |
| ApplicationThemeTest.MarqueurInconnuEstSignale (Critique) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:72 | Un marqueur inconnu est signale plutot que produit avec un trou. | 1. Substituer un modele dont un marqueur n'a pas de valeur. | Vérifie que result.ok est faux. Vérifie que result.error.find("inconnu") diffère de std::string::npos. |
| ApplicationThemeTest.AucuneCouleurLitteraleDansLeModeleReel (Majeur) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:89 | Le modele de theme livre ne contient aucune couleur litterale. | 1. Lire les feuilles de theme livrees. 2. Chercher un motif de couleur hexadecimale. | Vérifie que themeText.empty() est faux. Vérifie que std::regex_search(withoutComments, hexColorPattern) est faux. |
| ApplicationThemeTest.EtancheiteDesPortees (Critique) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:115 | Les regles d'identite sont etanches au theme de l'editeur. | 1. Substituer le modele reel avec deux jeux de jetons d'editeur de couleurs differentes, les valeurs derivant de buildStyleSheetValues. 2. Extraire les blocs #MainMenu/#OptionsPage des deux resultats. | Vérifie que themeText.empty() est faux. Vérifie que dark.ok est vrai. Vérifie que light.ok est vrai. Vérifie que dark.text vaut light.text. |
| ApplicationThemeTest.ResolutionDePoliceSansNomDeRepliCodeEnDur (Critique) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:165 | La resolution de police retombe sur une famille generique sans nom code en dur. | 1. Resoudre la police embarquee enregistree, puis non enregistree. | Vérifie que registered.useEmbeddedFamily est vrai. Vérifie que registered.embeddedFamily vaut "Inter". Vérifie que missing.useEmbeddedFamily est faux. Vérifie que missing.embeddedFamily.empty() est vrai. |
| ApplicationThemeTest.EchelleTypographiquePositiveEtOrdonnee (Majeur) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:185 | L'echelle typographique est positive et ordonnee du plus grand au plus petit. | 1. Lire les tailles de l'echelle typographique des jetons. | Vérifie que typography.screenTitle.pointSize est strictement supérieur à 0. Vérifie que typography.sectionTitle.pointSize est strictement supérieur à 0. Vérifie que typography.body.pointSize est strictement supérieur à 0. Vérifie que typography.caption.pointSize est strictement supérieur à 0. Vérifie que typography.monospaceBody.pointSize est strictement supérieur à 0. Vérifie que typography.screenTitle.pointSize est strictement supérieur à typography.sectionTitle.pointSize. Vérifie que typography.sectionTitle.pointSize est strictement supérieur à typography.body.pointSize. Vérifie que typography.body.pointSize est strictement supérieur à typography.caption.pointSize. |
| ApplicationThemeTest.AucuneTailleDePoliceResiduelleDansLesFichiersUi (Majeur) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:208 | Aucune taille de police ni marge figee ne subsiste dans les fichiers .ui. | 1. Lire MainMenu.ui et OptionsPage.ui. 2. Chercher une propriete font/margin figee au niveau du widget racine. | Vérifie que text.empty() est faux. Vérifie que text.find("<property name=\\"font\\\\"\>\")</tt> vaut <tt>std::string::npos</tt>.<br/>Vérifie que <tt>text.find(\"Margin\") vaut std::string::npos. |
| ApplicationThemeTest.ResolutionDuThemeEffectifSuitLeReglageEtLeSysteme (Critique) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:233 | La resolution du theme effectif suit le reglage et, si Systeme, le systeme. | 1. Resoudre les quatre combinaisons reglage/systeme. | Vérifie que hmi::resolveEffectiveEditorTheme(EditorThemeSetting::System, /*systemPrefersDark=*/true) vaut EditorThemeMode::Dark. Vérifie que hmi::resolveEffectiveEditorTheme(EditorThemeSetting::System, /*systemPrefersDark=*/false) vaut EditorThemeMode::Light. Vérifie que hmi::resolveEffectiveEditorTheme(EditorThemeSetting::Light, /*systemPrefersDark=*/true) vaut EditorThemeMode::Light. Vérifie que hmi::resolveEffectiveEditorTheme(EditorThemeSetting::Dark, /*systemPrefersDark=*/false) vaut EditorThemeMode::Dark. |
| ApplicationThemeTest.EtancheiteDesPorteesAvecLesVraisThemes (Critique) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:263 | L'etancheite des portees tient avec les vrais themes sombre et clair. | 1. Produire la feuille de style avec editorDarkTokens() puis editorLightTokens(). 2. Comparer les blocs #MainMenu/#OptionsPage des deux resultats. | Vérifie que identityText.empty() est faux. Vérifie que editorText.empty() est faux. Vérifie que identityDark.ok est vrai. Vérifie que identityLight.ok est vrai. Vérifie que editorDark.ok est vrai. Vérifie que editorLight.ok est vrai. Vérifie que identityDark.text vaut identityLight.text. Vérifie que editorDark.text diffère de editorLight.text. |
| ApplicationThemeTest.LesDeuxPorteesSontDansDeuxFichiersDisjoints (Bloquant) Source/Test/Unit/HMI/Interface/test_application_theme.cpp:308 | Les deux portees de theme sont disjointes, marqueur par marqueur. | 1. Lire les deux feuilles livrees, commentaires retires. 2. Chercher un marqueur du prefixe de l'autre portee dans chacune. | Vérifie que identityRules.empty() est faux. Vérifie que editorRules.empty() est faux. Vérifie que identityRules.find("editor.color.") vaut std::string::npos. Vérifie que editorRules.find("identity.") vaut std::string::npos. |
test_character_sheet_values.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CharacterSheetValuesTest.LesModificateursSAffichentAvecLeurSigne (Majeur) Source/Test/Unit/HMI/Interface/test_character_sheet_values.cpp:104 | Les modificateurs s'affichent signes, les caracteristiques avec leur modificateur. | 1. Produire les valeurs d'une fiche de Force 16 et de Charisme 8. 2. Lire les deux lignes de caracteristique. | Vérifie que valeurs.at("sheet.ability.strength") vaut "16 (+3)". Vérifie que valeurs.at("sheet.ability.charisma") vaut "8 (-1)". Vérifie que valeurs.at("sheet.initiative") vaut "+1". |
| CharacterSheetValuesTest.LeJetDeSauvegardeMaitriseComptteLaMaitrise (Critique) Source/Test/Unit/HMI/Interface/test_character_sheet_values.cpp:127 | Un jet de sauvegarde maitrise porte le bonus de maitrise. | 1. Produire les valeurs d'une fiche maitrisant la sauvegarde de Force. 2. Comparer les lignes de Force et de Dexterite. | Vérifie que valeurs.at("sheet.proficiency_bonus") vaut "+2". Vérifie que valeurs.at("sheet.save.strength") vaut "+5". Vérifie que valeurs.at("sheet.save.dexterity") vaut "+1". |
| CharacterSheetValuesTest.LaCompetenceMaitriseeSeSignaleEtLaPerceptionPassiveEnDerive (Majeur) Source/Test/Unit/HMI/Interface/test_character_sheet_values.cpp:149 | Une competence maitrisee se signale, et la Perception passive en derive. | 1. Produire les valeurs d'une fiche maitrisant l'Athletisme. 2. Lire Athletisme, Discretion et la Perception passive. | Vérifie que valeurs.at("sheet.skill.athletics") vaut "+5 •". Vérifie que valeurs.at("sheet.skill.stealth") vaut "+1". Vérifie que valeurs.at("sheet.passive_perception") vaut "11". |
| CharacterSheetValuesTest.LesPointsDeVieSeLisentContreLeurMaximum (Mineur) Source/Test/Unit/HMI/Interface/test_character_sheet_values.cpp:172 | Les points de vie se lisent contre leur maximum. | 1. Produire les valeurs d'une fiche a 25 points de vie sur 30. | Vérifie que valeurs.at("sheet.hit_points") vaut "25 / 30". Vérifie que valeurs.at("sheet.hit_points_max") vaut "30". Vérifie que valeurs.at("sheet.speed") vaut "9 m". |
| CharacterSheetValuesTest.SansFicheAucuneValeurNEstProduite (Majeur) Source/Test/Unit/HMI/Interface/test_character_sheet_values.cpp:194 | Sans fiche, aucune valeur n'est produite. | 1. Produire les valeurs d'un contexte sans fiche. | Vérifie que hmi::characterSheetValues({}).empty() est vrai. |
| CharacterSheetValuesTest.ChaqueChampDeLaFicheEstAlimente (?) Source/Test/Unit/HMI/Interface/test_character_sheet_values.cpp:213 | Chaque champ de la fiche declarant une source est rempli. cat Unitaire · Fiche de personnage crit Critique etapes 1. Lire les identifiants de valeur declares par l'ossature de la fiche. 2. Produire les valeurs d'une fiche complete. 3. Verifier que chaque identifiant declare est produit. attendu Aucun champ de la fiche ne reste sans source. | Vérifie que valeurs.count(champ.valueId) > 0 est vrai. Vérifie que declares est strictement supérieur à 10. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| DesignTokensTest.ConversionHexadecimaleStableEtBienFormee (Majeur) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:20 | La conversion en couleur CSS hexadecimale est stable et bien formee. | 1. Convertir une couleur connue en chaine hexadecimale. 2. Reconvertir la meme couleur. | Vérifie que first vaut second. Vérifie que first.size() vaut 7u. Vérifie que first vaut "#1a2b3c". |
| DesignTokensTest.ConversionRgbaPorteLesQuatreComposantes (Mineur) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:41 | La conversion en couleur CSS rgba() porte les quatre composantes. | 1. Convertir une couleur avec alpha partiel. | Vérifie que hmi::toCssRgba(color) vaut "rgba(0, 128, 255, 64)". |
| DesignTokensTest.CouleurViewportSuitLaPorteeDuMode (Critique) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:57 | La couleur d'effacement du viewport suit le jeton de fond de la bonne portee. | 1. Demander la couleur d'effacement en mode edition, puis en mode jeu. | Vérifie que hmi::viewportClearColor(/*editorMode=*/true, hmi::editorDarkTokens()) vaut hmi::editorDarkTokens().color.background. Vérifie que hmi::viewportClearColor(/*editorMode=*/true, hmi::editorLightTokens()) vaut hmi::editorLightTokens().color.background. Vérifie que hmi::viewportClearColor(/*editorMode=*/false, hmi::editorDarkTokens()) vaut hmi::identityTokens().color.background. |
| DesignTokensTest.LesDeuxPorteesPartagentLesMemesEchelles (Critique) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:76 | Les deux portees partagent les memes echelles et tailles. | 1. Comparer espacement, niveaux typographiques et tailles des deux portees. | Vérifie que hmi::identityTokens().spacing vaut hmi::editorDarkTokens().spacing. Vérifie que hmi::identityTokens().size vaut hmi::editorDarkTokens().size. Vérifie que hmi::identityTokens().typography.screenTitle vaut hmi::editorDarkTokens().typography.screenTitle. Vérifie que hmi::identityTokens().typography.sectionTitle vaut hmi::editorDarkTokens().typography.sectionTitle. Vérifie que hmi::identityTokens().typography.body vaut hmi::editorDarkTokens().typography.body. Vérifie que hmi::identityTokens().typography.caption vaut hmi::editorDarkTokens().typography.caption. Vérifie que hmi::identityTokens().typography.monospaceBody vaut hmi::editorDarkTokens().typography.monospaceBody. Vérifie que hmi::editorDarkTokens().spacing vaut hmi::editorLightTokens().spacing. Vérifie que hmi::editorDarkTokens().typography vaut hmi::editorLightTokens().typography. Vérifie que hmi::editorDarkTokens().size vaut hmi::editorLightTokens().size. |
| DesignTokensTest.ChaquePorteeDesigneSaPropreFamille (Majeur) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:110 | Chaque portee designe sa propre famille de police. | 1. Lire le role de famille des jetons d'identite et des deux themes d'editeur. | Vérifie que hmi::identityTokens().typography.family vaut hmi::FontRole::Identity. Vérifie que hmi::editorDarkTokens().typography.family vaut hmi::FontRole::Ui. Vérifie que hmi::editorLightTokens().typography.family vaut hmi::FontRole::Ui. |
| DesignTokensTest.LesRolesDuCadreSontDistinctsDansChaquePortee (Majeur) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:127 | Les trois roles du cadre pixel art sont distincts dans chaque portee. | 1. Pour chaque jeu de jetons, comparer contour, biseau clair et biseau sombre entre eux et a la surface. | Vérifie que color.frameEdge == color.frameOrnament est faux. Vérifie que color.frameEdge == color.frameShadow est faux. Vérifie que color.frameOrnament == color.frameShadow est faux. Vérifie que hmi::relativeLuminance(color.frameEdge) est strictement inférieur à hmi::relativeLuminance(color.surface). Vérifie que hmi::relativeLuminance(color.frameOrnament) est strictement supérieur à hmi::relativeLuminance(color.frameShadow). |
| DesignTokensTest.CouleursDesDeuxPorteesDistinctesEtCoherentes (Mineur) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:154 | Les couleurs des deux portees sont definies et distinctes. | 1. Comparer le fond des deux portees. 2. Verifier que le texte contraste avec le fond dans chaque portee. | Vérifie que hmi::identityTokens().color.background == hmi::editorDarkTokens().color.background est faux. Vérifie que hmi::identityTokens().color.text == hmi::identityTokens().color.background est faux. Vérifie que hmi::editorDarkTokens().color.text == hmi::editorDarkTokens().color.background est faux. |
| DesignTokensTest.AucunDoublonDeLargeurMinimale (Mineur) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:172 | Une seule grandeur de largeur minimale existe pour les deux widgets de remappage. | 1. Lire controlMinWidth dans les jetons du chassis d'edition. | Vérifie que hmi::editorDarkTokens().size.controlMinWidth est strictement supérieur à 0. |
| DesignTokensTest.ChaqueThemeSatisfaitLeSeuilDeContraste (Critique) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:187 | Chaque jeu de jetons satisfait un seuil de contraste texte/fond. | 1. Calculer le contraste texte/fond et texte-attenue/fond pour les deux themes d'editeur, puis pour l'identite. | Vérifie que hmi::contrastRatio(tokens->color.text, tokens->color.background) est supérieur ou égal à MIN_TEXT_CONTRAST. Vérifie que hmi::contrastRatio(tokens->color.textMuted, tokens->color.background) est supérieur ou égal à MIN_MUTED_TEXT_CONTRAST. |
| DesignTokensTest.ContrasteSymetriqueEtUnitairePourUneMemeCouleur (Mineur) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:213 | Le rapport de contraste est symetrique et vaut 1 sans difference de couleur. | 1. Calculer le contraste d'une couleur avec elle-meme, puis dans les deux sens entre deux couleurs distinctes. | Vérifie que hmi::contrastRatio(color, color) vaut 1.0, à 1e-9 près. Vérifie que hmi::contrastRatio(hmi::DesignColor{0, 0, 0}, hmi::DesignColor{255, 255, 255}) vaut hmi::contrastRatio(hmi::DesignColor{255, 255, 255}, hmi::DesignColor{0, 0, 0}), à 1e-9 près. |
| DesignTokensTest.SeulesLesGrandeursDIdentiteSuiventLeFacteur (Critique) Source/Test/Unit/HMI/Interface/test_design_tokens.cpp:234 | Seules les grandeurs d identite suivent le facteur d agrandissement. | 1. Produire les valeurs de feuille de style aux facteurs 1, 2 et 3. 2. Comparer les marqueurs identity.size.* et tokens.spacing.* entre eux. | Vérifie que values.at("identity.size.screenTitle") vaut std::to_string(base.screenTitle * scale). Vérifie que values.at("identity.size.sectionTitle") vaut std::to_string(base.sectionTitle * scale). Vérifie que values.at("identity.size.body") vaut std::to_string(base.body * scale). Vérifie que values.at("identity.frame.thickness") vaut std::to_string(base.frameThickness * scale). Vérifie que values.at("tokens.spacing.small") vaut std::to_string(hmi::editorDarkTokens().spacing.small). Vérifie que values.at("tokens.typography.screenTitle.pointSize") vaut std::to_string(hmi::editorDarkTokens().typography.screenTitle.pointSize). Vérifie que hmi::buildStyleSheetValues(hmi::editorDarkTokens(), 0).at("identity.size.body") vaut std::to_string(base.body). Vérifie que hmi::buildStyleSheetValues(hmi::editorDarkTokens(), -4).at("identity.size.body") vaut std::to_string(base.body). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EditorActionsTest.LesOutilsDuCatalogueFormentUneBijectionAvecEditorTool (Critique) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:46 | Les outils du catalogue forment une bijection avec EditorTool. | 1. Parcourir les actions du groupe LevelTools du catalogue. 2. Convertir chacune en outil puis reconvertir vers l'action. | Vérifie que tool.has_value() est vrai. Vérifie que seenTools.insert(*tool).second est vrai. Vérifie que seenIcons.insert(spec.id).second est vrai. Vérifie que hmi::editorActionForTool(*tool) vaut spec.id. Vérifie que seenTools.size() vaut hmi::EDITOR_TOOL_COUNT. |
| EditorActionsTest.LesCinqOutilsDeCanevasFormentUneBijectionAvecPixelTool (Critique) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:78 | Les quatre outils de canevas forment une bijection avec PixelTool. | 1. Pour chaque hmi::PixelTool, resoudre l'action puis reconvertir vers l'outil. 2. Verifier que l'action appartient au groupe PixelTools. | Vérifie que seen.insert(id).second est vrai. Vérifie que hmi::editorActionSpec(id).group vaut hmi::EditorActionGroup::PixelTools. Vérifie que hmi::editorActionTool(id).has_value() est faux. Vérifie que roundTrip.has_value() est vrai. Vérifie que *roundTrip vaut tool. Vérifie que seen.size() vaut 5u. |
| EditorActionsTest.DefinitionUniqueDeRaccourci (Critique) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:108 | Aucun raccourci n'est attribue a deux actions. | 1. Parcourir le catalogue, ignorer les raccourcis vides. 2. Verifier qu'aucune valeur n'apparait deux fois. | Vérifie que shortcuts.insert(shortcut).second est vrai. |
| EditorActionsTest.GeometrieDesIconesNonVideEtDansLeCadre (Majeur) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:131 | La geometrie de chaque icone est non vide et dans le cadre normalise. | 1. Pour chaque action du catalogue, produire sa geometrie. 2. Verifier qu'elle a au moins un trait, et que chaque point est dans [0,1]. | Vérifie que geometry.strokes.empty() est faux. Vérifie que stroke.points.empty() est faux. Vérifie que point.x est supérieur ou égal à 0.0f. Vérifie que point.x est inférieur ou égal à 1.0f. Vérifie que point.y est supérieur ou égal à 0.0f. Vérifie que point.y est inférieur ou égal à 1.0f. |
| EditorActionsTest.ChaqueLibelleExisteDansLesDeuxLangues (Majeur) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:158 | Chaque cle de libelle du catalogue d'actions existe en francais et en anglais. | 1. Lire fr.lang et en.lang. 2. Verifier que chaque labelKey du catalogue y figure. | Vérifie que fr.empty() est faux. Vérifie que en.empty() est faux. Vérifie que fr.count(spec.labelKey) > 0 est vrai. Vérifie que en.count(spec.labelKey) > 0 est vrai. |
| EditorActionsTest.AucuneActionRemappableOrpheline (Critique) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:181 | Chaque action d'editeur remappable a une commande effective. | 1. Comparer le nombre d'actions remappables (hors outil) au nombre d'entrees de la table de correspondance. 2. Verifier que chaque entree pointe vers une commande reelle du catalogue et que l'aller-retour restitue l'action d'origine. | Vérifie que hmi::KEY_BINDING_ICON_COUNT vaut hmi::EDITOR_ACTION_COUNT - 1. EXPECT_NO_THROW(static_cast<void>(hmi::editorActionSpec(entry.id))) Vérifie que seen.insert(entry.id).second est vrai. Vérifie que roundTrip.has_value() est vrai. Vérifie que *roundTrip vaut entry.action. |
| EditorActionsTest.LaBarreDOutilsNePorteQueLEssentiel (Critique) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:215 | La barre d'outils ne porte que les outils et un petit nombre de commandes. | 1. Compter les actions de surface ToolBarAndMenu qui ne sont pas des outils, pour l'espace de niveau puis pour l'atelier. | Vérifie que isTool est faux. Vérifie que levelCommands est inférieur ou égal à hmi::TOOLBAR_COMMAND_BUDGET. Vérifie que pixelCommands est inférieur ou égal à hmi::TOOLBAR_COMMAND_BUDGET. Vérifie que toolsInToolBar vaut static_cast<int>(hmi::EDITOR_TOOL_COUNT) + 5. |
| EditorActionsTest.AucuneActionOrphelineDeSurface (Majeur) Source/Test/Unit/HMI/Interface/test_editor_actions.cpp:255 | Chaque action du catalogue reste atteignable par au moins une surface. | 1. Parcourir le catalogue et lire la surface de chaque action. | Vérifie que spec.surface == hmi::ActionSurface::ToolBarAndMenu \|\| spec.surface == hmi::ActionSurface::MenuOnly est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EditorWorkspaceTest.ChaquePanneauAppartientAAuMoinsUnEspace (Critique) Source/Test/Unit/HMI/Interface/test_editor_workspace.cpp:56 | Chaque panneau appartient a au moins un espace de travail. | 1. Parcourir les neuf panneaux et resoudre leur masque d'espaces. 2. Verifier que le compte couvert vaut PANEL_COUNT et que les trois espaces sont representes. | Vérifie que seen.insert(panel).second est vrai. Vérifie que mask diffère de 0u. Vérifie que seen.size() vaut hmi::PANEL_COUNT. Vérifie que workspacesCovered.size() vaut hmi::EDITOR_WORKSPACE_COUNT. |
| EditorWorkspaceTest.CanevasPartageEntreLesDeuxEspacesDePeinture (Critique) Source/Test/Unit/HMI/Interface/test_editor_workspace.cpp:87 | Le canevas et ses panneaux servent aux deux espaces de peinture. | 1. Resoudre le masque du canevas, de l'historique et de la palette. | Vérifie que hmi::workspaceMaskContains(mask, hmi::EditorWorkspace::PixelArt) est vrai. Vérifie que hmi::workspaceMaskContains(mask, hmi::EditorWorkspace::Planes) est vrai. Vérifie que hmi::workspaceMaskContains(mask, hmi::EditorWorkspace::Level) est faux. |
| EditorWorkspaceTest.UneSeuleBarreDOutilsParEspace (Critique) Source/Test/Unit/HMI/Interface/test_editor_workspace.cpp:108 | Les deux barres d'outils ne sont jamais visibles simultanement. | 1. Lire l'habillage des deux espaces. 2. Verifier qu'exactement une barre est visible dans chacun. | Vérifie que dressing.levelToolBarVisible diffère de dressing.pixelToolBarVisible. Vérifie que level.levelToolBarVisible est vrai. Vérifie que planes.pixelToolBarVisible est vrai. Vérifie que pixel.pixelToolBarVisible est vrai. |
| EditorWorkspaceTest.MenuAtelierReserveASonEspace (Majeur) Source/Test/Unit/HMI/Interface/test_editor_workspace.cpp:140 | Le menu de l'atelier n'existe que dans l'espace de l'atelier. | 1. Lire l'habillage des trois espaces. | Vérifie que hmi::dressingForWorkspace(hmi::EditorWorkspace::Level).workshopMenuVisible est faux. Vérifie que hmi::dressingForWorkspace(hmi::EditorWorkspace::PixelArt).workshopMenuVisible est vrai. Vérifie que hmi::dressingForWorkspace(hmi::EditorWorkspace::Planes).workshopMenuVisible est vrai. |
| EditorWorkspaceTest.LesDeuxFamillesDOutilsSontDisjointes (Critique) Source/Test/Unit/HMI/Interface/test_editor_workspace.cpp:159 | Chaque famille d'outils mene a son propre espace. | 1. Resoudre l'espace de chacun des huit outils de niveau. 2. Resoudre celui des cinq outils de canevas. | Vérifie que hmi::workspaceForTool(tool) vaut hmi::EditorWorkspace::Level. Vérifie que levelTools vaut hmi::EDITOR_TOOL_COUNT. Vérifie que hmi::workspaceForPixelTool(tool) vaut hmi::EditorWorkspace::PixelArt. |
| EditorWorkspaceTest.LaMiseEnAvantResteDansSonEspace (Critique) Source/Test/Unit/HMI/Interface/test_editor_workspace.cpp:185 | La mise en avant ne traverse jamais la frontiere entre espaces. | 1. Parcourir la table outil -> panneau, puis celle des outils de canevas. 2. Comparer l'espace de l'outil a celui du panneau qu'il met en avant. | Vérifie que hmi::workspaceMaskContains(hmi::workspacesForPanel(entry.panel), hmi::workspaceForTool(entry.tool)) est vrai. Vérifie que hmi::workspaceMaskContains(hmi::workspacesForPanel(entry.panel), hmi::workspaceForPixelTool(entry.tool)) est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| IdentityScaleTest.FacteurToujoursBorneEntreUnEtLePlafond (Critique) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:18 | Le facteur reste entier, superieur a 1 et borne par le plafond. | 1. Demander le facteur pour des hauteurs allant du negatif au tres grand. | Vérifie que scale est supérieur ou égal à 1. Vérifie que scale est inférieur ou égal à hmi::IDENTITY_MAX_SCALE. |
| IdentityScaleTest.FacteurMonotoneEnHauteur (Majeur) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:37 | Le facteur croit de facon monotone avec la hauteur de fenetre. | 1. Parcourir les hauteurs de 0 a 2400 par pas de 1. 2. Comparer chaque facteur au precedent. | Vérifie que scale est supérieur ou égal à previous. |
| IdentityScaleTest.LeSeuilEstAtteintParDefautJamaisParArrondi (Critique) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:59 | Une hauteur juste insuffisante ne declenche pas le facteur superieur. | 1. Demander le facteur juste avant et juste apres chaque multiple de la hauteur de base. | Vérifie que hmi::identityScaleFor(threshold) vaut factor. Vérifie que hmi::identityScaleFor(threshold - 1) vaut factor - 1 < 1 ? 1 : factor - 1. |
| IdentityScaleTest.HauteursCourantesDonnentLesFacteursAnnonces (Majeur) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:79 | Les hauteurs d'ecran courantes donnent les facteurs annonces. | 1. Demander le facteur pour 360, 720, 1080 et 1440 pixels logiques. | Vérifie que hmi::identityScaleFor(360) vaut 1. Vérifie que hmi::identityScaleFor(720) vaut 2. Vérifie que hmi::identityScaleFor(1080) vaut 3. Vérifie que hmi::identityScaleFor(1440) vaut 3. |
| IdentityScaleTest.FacteurBorneParLaZoneDisponible (Bloquant) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:98 | Le facteur borne n'excede jamais celui de la zone disponible. | 1. Demander le facteur borne pour des couples (hauteur de fenetre, zone disponible). 2. Comparer au facteur de la seule zone disponible. | Vérifie que bounded est inférieur ou égal à hmi::identityScaleFor(available). Vérifie que bounded est supérieur ou égal à 1. |
| IdentityScaleTest.UneFenetreDebordanteNeGagnePasDeFacteur (Bloquant) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:124 | Une fenetre plus haute que l'ecran ne gagne pas de facteur. | 1. Zone disponible de 1009 pixels (cas rapporte). 2. Demander le facteur pour des hauteurs de fenetre croissantes, jusqu'au-dela de l'ecran. | Vérifie que ceiling vaut 2. Vérifie que hmi::identityScaleForDisplay(window, AVAILABLE) vaut ceiling. |
| IdentityScaleTest.ZoneDisponibleInconnueLaisseLaFenetreDecider (Majeur) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:146 | Une zone disponible inconnue laisse la fenetre decider. | 1. Demander le facteur borne avec une zone disponible nulle puis negative. | Vérifie que hmi::identityScaleForDisplay(window, 0) vaut hmi::identityScaleFor(window). Vérifie que hmi::identityScaleForDisplay(window, -1) vaut hmi::identityScaleFor(window). |
| IdentityScaleTest.UnePetiteFenetreGardeSonFacteur (Majeur) Source/Test/Unit/HMI/Interface/test_identity_scale.cpp:164 | Une petite fenetre garde son facteur sur un grand ecran. | 1. Zone disponible de 1440 pixels. 2. Demander le facteur pour des fenetres de 360 et 720 pixels. | Vérifie que hmi::identityScaleForDisplay(360, 1440) vaut 1. Vérifie que hmi::identityScaleForDisplay(720, 1440) vaut 2. Vérifie que hmi::identityScaleForDisplay(1080, 1440) vaut 3. |
test_parchment_frame.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ParchmentFrameTest.AucuneBandeNeDeborde (Critique) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:47 | Aucune bande de l'encadrement ne sort du rectangle du widget. | 1. Produire la geometrie pour un balayage de tailles et d'echelles. 2. Verifier que chaque bande a des dimensions positives et reste dans [0,largeur] x [0,hauteur]. | Vérifie que stroke.width est strictement supérieur à 0. Vérifie que stroke.height est strictement supérieur à 0. Vérifie que stroke.x est supérieur ou égal à 0. Vérifie que stroke.y est supérieur ou égal à 0. Vérifie que stroke.x + stroke.width est inférieur ou égal à size. Vérifie que stroke.y + stroke.height est inférieur ou égal à size. |
| ParchmentFrameTest.LesQuatreRolesSontPresents (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:78 | Un encadrement de taille utile porte les quatre roles de couleur. | 1. Produire la geometrie d'un cadre de 120 x 80 a l'echelle 2. 2. Chercher chacun des quatre roles. | Vérifie que containsRole(strokes, hmi::ParchmentRole::Field) est vrai. Vérifie que containsRole(strokes, hmi::ParchmentRole::Edge) est vrai. Vérifie que containsRole(strokes, hmi::ParchmentRole::Ornament) est vrai. Vérifie que containsRole(strokes, hmi::ParchmentRole::Shadow) est vrai. |
| ParchmentFrameTest.UneReserveSepareLeTraitDuFilet (Critique) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:99 | Une reserve de parchemin separe le trait exterieur du filet ornemental. | 1. Produire la geometrie d'un cadre de 120 x 80 a l'echelle 2. 2. Relever le role visible a mi-hauteur, une unite a l'interieur du trait exterieur. | Vérifie que topRoleAt(strokes, 0, 40) vaut hmi::ParchmentRole::Edge. Vérifie que topRoleAt(strokes, UNIT, 40) vaut hmi::ParchmentRole::Field. Vérifie que topRoleAt(strokes, 2 * UNIT, 40) vaut hmi::ParchmentRole::Ornament. Vérifie que topRoleAt(strokes, 3 * UNIT, 40) vaut hmi::ParchmentRole::Shadow. |
| ParchmentFrameTest.LesAnglesPortentUnCabochon (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:122 | Les quatre angles du cadre portent un cabochon ornemental. | 1. Produire la geometrie d'un cadre de 120 x 80 a l'echelle 2. 2. Relever le role visible au pixel de chacun des quatre angles. | Vérifie que topRoleAt(strokes, 0, 0) vaut hmi::ParchmentRole::Ornament. Vérifie que topRoleAt(strokes, WIDTH - 1, 0) vaut hmi::ParchmentRole::Ornament. Vérifie que topRoleAt(strokes, 0, HEIGHT - 1) vaut hmi::ParchmentRole::Ornament. Vérifie que topRoleAt(strokes, WIDTH - 1, HEIGHT - 1) vaut hmi::ParchmentRole::Ornament. |
| ParchmentFrameTest.LesBorduresOpposeesSontSymetriques (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:145 | Les bordures opposees de l'encadrement ont la meme epaisseur. | 1. Produire la geometrie d'un cadre rectangulaire. 2. Mesurer l'epaisseur des quatre bandes du trait exterieur. | Vérifie que left est strictement supérieur à 0. Vérifie que left vaut right. Vérifie que top est strictement supérieur à 0. Vérifie que top vaut bottom. |
| ParchmentFrameTest.TaillesDegenereesSansGeometrieInvalide (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:193 | Les tailles degenerees produisent le vide ou un champ nu, jamais une geometrie invalide. | 1. Demander la geometrie pour une largeur ou une hauteur nulle, puis negative. 2. Demander celle d'un cadre de 2 x 2 a l'echelle 3. | Vérifie que hmi::parchmentFrameStrokes(0, 40, 2).empty() est vrai. Vérifie que hmi::parchmentFrameStrokes(40, 0, 2).empty() est vrai. Vérifie que hmi::parchmentFrameStrokes(-10, -10, 2).empty() est vrai. Vérifie que tiny.size() vaut 1u. Vérifie que tiny.front().role vaut hmi::ParchmentRole::Field. Vérifie que tiny.front().width vaut 2. Vérifie que tiny.front().height vaut 2. |
| ParchmentFrameTest.LeFleuronEstUnePointeEchancree (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:219 | Le fleuron de focus est une pointe echancree contenue dans son carre. | 1. Produire le fleuron pour plusieurs tailles. 2. Verifier le confinement, la symetrie haut/bas, l'orientation a droite et la presence de l'echancrure arriere. | Vérifie que points.size() vaut 4u. Vérifie que point.x est supérieur ou égal à 0. Vérifie que point.y est supérieur ou égal à 0. Vérifie que point.x est inférieur ou égal à size. Vérifie que point.y est inférieur ou égal à size. Vérifie que points[1].x vaut size. Vérifie que points[1].y vaut size / 2. Vérifie que points[0].y vaut 0. Vérifie que points[2].y vaut size. Vérifie que points[0].x vaut points[2].x. Vérifie que points[3].x est strictement supérieur à points[0].x. Vérifie que points[3].x est strictement inférieur à points[1].x. |
| ParchmentFrameTest.FleuronTropPetitEstVide (Mineur) Source/Test/Unit/HMI/Interface/test_parchment_frame.cpp:253 | Un fleuron trop petit pour son echancrure est vide. | 1. Demander le fleuron pour une taille inferieure a quatre, nulle et negative. | Vérifie que hmi::focusFleuronPoints(3).empty() est vrai. Vérifie que hmi::focusFleuronPoints(0).empty() est vrai. Vérifie que hmi::focusFleuronPoints(-8).empty() est vrai. |
test_parchment_ornaments.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| CabochonTest.ToutTientDansLeCarreEnglobant (Critique) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:61 | Le cabochon ne deborde jamais de son carre d'angle. | 1. Produire la geometrie pour cinq tailles, de 8 a 96 pixels. 2. Relever la boite englobante de toutes les formes. | Vérifie que shapes.empty() est faux. Vérifie que bounds.left est supérieur ou égal à 0.0f. Vérifie que bounds.top est supérieur ou égal à 0.0f. Vérifie que bounds.right est inférieur ou égal à static_cast<float>(size). Vérifie que bounds.bottom est inférieur ou égal à static_cast<float>(size). |
| CabochonTest.SousLaTailleMinimaleIlNEstPlusDessine (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:86 | Un cabochon trop petit n'est pas dessine plutot que reduit a une tache. | 1. Demander la geometrie pour toutes les tailles de -4 a la taille minimale exclue. 2. Demander la geometrie a la taille minimale. | Vérifie que cabochonShapes(size).empty() est vrai. Vérifie que cabochonShapes(ORNAMENT_MINIMUM_SIZE).empty() est faux. |
| CabochonTest.LaGemmeEstInscriteDansLeSerti (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:104 | La gemme est inscrite dans son serti, sans l'affleurer. | 1. Produire un cabochon de 64 pixels. 2. Comparer la boite de chaque facette a celle du serti. | Vérifie que gem.left est strictement supérieur à bezel.left. Vérifie que gem.top est strictement supérieur à bezel.top. Vérifie que gem.right est strictement inférieur à bezel.right. Vérifie que gem.bottom est strictement inférieur à bezel.bottom. |
| CabochonTest.LEclatEstPoseEnDernier (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:134 | L'ordre de dessin du cabochon met l'eclat par-dessus la facette qu'il eclaire. | 1. Produire un cabochon de 64 pixels. 2. Lire le role de la premiere et de la derniere forme, et compter les traits d'encre. | Vérifie que shapes.empty() est faux. Vérifie que shapes.back().role vaut OrnamentRole::OrnamentLight. Vérifie que shapes.front().role vaut OrnamentRole::Ornament. Vérifie que countRole(shapes, OrnamentRole::Edge) vaut 1. |
| CabochonTest.ToutesLesFormesOntAuMoinsTroisSommets (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:156 | Aucune forme du cabochon n'a moins de trois sommets. | 1. Produire la geometrie pour cinq tailles. 2. Compter les sommets de chaque forme. | Vérifie que shape.points.size() est supérieur ou égal à 3U. |
| TitleBannerTest.LEnvergureSuitLaHauteurEtPasLaLargeur (Critique) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:179 | Les ailes du bandeau gardent leur envergure quand sa largeur triple. | 1. Produire trois bandeaux de meme hauteur et de 600, 900 puis 1400 pixels de large. 2. Mesurer la largeur de l'aile gauche de chacun. | Vérifie que shapes.size() est supérieur ou égal à 5U. Vérifie que measured vaut reference, à reference * 0.05f près. Vérifie que measured vaut first (comparaison flottante). Vérifie que bannerWingSpan(80) est strictement supérieur à bannerWingSpan(40). |
| TitleBannerTest.SurUnBandeauEtroitCeSontLesAilesQuiCedent (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:216 | Sur un bandeau etroit, ce sont les ailes qui cedent et non la plaque. | 1. Produire un bandeau de 60 x 40, puis un de 20 x 40. 2. Compter les formes dorees et mesurer l'aile. | Vérifie que narrow.empty() est faux. Vérifie que countRole(narrow, OrnamentRole::Ornament) vaut 3. Vérifie que wing.right - wing.left est strictement inférieur à static_cast<float>(bannerWingSpan(40)). Vérifie que tiny.empty() est faux. Vérifie que countRole(tiny, OrnamentRole::Ornament) vaut 1. Vérifie que countRole(tiny, OrnamentRole::GemShadow) est supérieur ou égal à 1. Vérifie que countRole(tiny, OrnamentRole::Gem) est supérieur ou égal à 1. |
| TitleBannerTest.ToutTientDansLeBandeau (Critique) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:246 | Aucune forme du bandeau ne deborde de son rectangle. | 1. Produire la geometrie pour trois largeurs et quatre hauteurs. 2. Relever la boite englobante de chaque bandeau non vide. | Vérifie que bounds.left est supérieur ou égal à 0.0f. Vérifie que bounds.top est supérieur ou égal à 0.0f. Vérifie que bounds.right est inférieur ou égal à static_cast<float>(width). Vérifie que bounds.bottom est inférieur ou égal à static_cast<float>(height). |
| TitleBannerTest.LesDeuxAilesSontSymetriques (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:273 | Les deux ailes du bandeau sont symetriques au centieme de pixel. | 1. Produire un bandeau de 800 x 40. 2. Comparer les boites des deux premieres formes, l'une reflechie autour de l'axe vertical. | Vérifie que shapes.size() est supérieur ou égal à 2U. Vérifie que left.left vaut static_cast<float>(width) - right.right, à 0.01f près. Vérifie que left.right vaut static_cast<float>(width) - right.left, à 0.01f près. Vérifie que left.top vaut right.top, à 0.01f près. Vérifie que left.bottom vaut right.bottom, à 0.01f près. |
| TitleBannerTest.UnBandeauDegenereNeDonneRien (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:298 | Un bandeau degenere ne produit aucune forme. | 1. Demander la geometrie pour une largeur nulle, negative, puis une hauteur sous le seuil. 2. Demander l'envergure pour une hauteur nulle et negative. | Vérifie que titleBannerShapes(0, 40).empty() est vrai. Vérifie que titleBannerShapes(-10, 40).empty() est vrai. Vérifie que titleBannerShapes(800, ORNAMENT_MINIMUM_SIZE - 1).empty() est vrai. Vérifie que bannerWingSpan(0) vaut 0. Vérifie que bannerWingSpan(-5) vaut 0. |
| TitleBannerTest.LeFiletEstTraceEtPoseEnDernier (Majeur) Source/Test/Unit/HMI/Interface/test_parchment_ornaments.cpp:316 | Le filet du bandeau est trace, non rempli, et pose en dernier. | 1. Produire un bandeau de 800 x 40. 2. Verifier que la derniere forme est doree et non remplie, et que toutes les autres sont remplies. | Vérifie que shapes.empty() est faux. Vérifie que shapes.back().filled est faux. Vérifie que shapes.back().role vaut OrnamentRole::Ornament. Vérifie que shapes[i].filled est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| RpgScreensTest.LeCycleTraverseLesNeufEcrans (Critique) Source/Test/Unit/HMI/Interface/test_rpg_screens.cpp:43 | Le cycle de navigation traverse les neuf ecrans et revient au premier. | 1. Partir du premier ecran. 2. Appeler nextRpgScreen neuf fois en notant chaque ecran atteint. | Vérifie que rpgScreens().size() vaut hmi::RPG_SCREEN_COUNT. Vérifie que visited.size() vaut hmi::RPG_SCREEN_COUNT. Vérifie que screen vaut first. |
| RpgScreensTest.LePasArriereEstLInverseDuPasAvant (Majeur) Source/Test/Unit/HMI/Interface/test_rpg_screens.cpp:68 | Le pas arriere est l'inverse du pas avant. | 1. Pour chaque ecran, avancer puis reculer. 2. Reculer depuis le premier ecran. | Vérifie que previousRpgScreen(nextRpgScreen(descriptor.id)) vaut descriptor.id. Vérifie que nextRpgScreen(previousRpgScreen(descriptor.id)) vaut descriptor.id. Vérifie que previousRpgScreen(rpgScreens().front().id) vaut rpgScreens().back().id. |
| RpgScreensTest.LaRegleDeSuperpositionEstCelleAttendue (Majeur) Source/Test/Unit/HMI/Interface/test_rpg_screens.cpp:87 | La regle de superposition est celle attendue pour chacun des neuf ecrans. | 1. Interroger pausesGame pour chacun des neuf ecrans. | Vérifie que pausesGame(RpgScreenId::CharacterSheet) est vrai. Vérifie que pausesGame(RpgScreenId::Inventory) est vrai. Vérifie que pausesGame(RpgScreenId::QuestJournal) est vrai. Vérifie que pausesGame(RpgScreenId::Dialogue) est vrai. Vérifie que pausesGame(RpgScreenId::Merchant) est vrai. Vérifie que pausesGame(RpgScreenId::GuildBoard) est vrai. Vérifie que pausesGame(RpgScreenId::TeamSheet) est vrai. Vérifie que pausesGame(RpgScreenId::WorldMap) est faux. Vérifie que pausesGame(RpgScreenId::CombatHud) est faux. |
| RpgScreensTest.ChaqueEcranEstIdentifiableEtNonVide (Majeur) Source/Test/Unit/HMI/Interface/test_rpg_screens.cpp:114 | Chaque ecran a un nom d'objet unique, un titre unique et une ossature non vide. | 1. Collecter noms d'objets et cles de titre. 2. Verifier leur unicite et la presence d'au moins un bloc par ecran. | Vérifie que objectNames.insert(descriptor.objectName).second est vrai. Vérifie que titleKeys.insert(descriptor.titleKey).second est vrai. Vérifie que descriptor.layout.leftColumn.empty() est faux. Vérifie que hmi::rpgScreenDescriptor(descriptor.id).id vaut descriptor.id. |
| RpgScreensTest.ChaqueBlocEstCoherentAvecSonGenre (Majeur) Source/Test/Unit/HMI/Interface/test_rpg_screens.cpp:144 | Chaque bloc de l'ossature est coherent avec son genre. | 1. Parcourir les blocs des deux colonnes de chaque ecran. 2. Verifier les dimensions et libelles exiges par chaque genre. | Vérifie que block.fields.empty() est faux. Vérifie que field.labelKey[0] diffère de '\\0'. Vérifie que block.columns est strictement supérieur à 0. Vérifie que block.rows est strictement supérieur à 0. Vérifie que block.rows > 0 \|\| !block.valueIds.empty() est vrai. Vérifie que block.columns est strictement supérieur à 0. |
| RpgScreensTest.ChaqueCleDeLOssatureExisteDansLesDeuxLangues (Majeur) Source/Test/Unit/HMI/Interface/test_rpg_screens.cpp:198 | Chaque cle de l'ossature des ecrans du RPG existe en francais et en anglais. | 1. Lire fr.lang et en.lang. 2. Verifier chaque cle de titre, de bloc et de champ, plus les cles du pied d'actions. | Vérifie que fr.empty() est faux. Vérifie que en.empty() est faux. Vérifie que fr.count(key) > 0 est vrai. Vérifie que en.count(key) > 0 est vrai. |
| RpgScreensTest.LesIdentifiantsDeValeurSontUniquesParEcran (?) Source/Test/Unit/HMI/Interface/test_rpg_screens.cpp:253 | Les identifiants de valeur sont uniques a l'interieur d'un ecran. cat Unitaire · Ecrans du RPG crit Majeur etapes 1. Collecter les identifiants de valeur de chaque ecran. 2. Verifier qu'aucun ne se repete dans un meme ecran. attendu Aucun identifiant duplique. | Vérifie que vus.insert(field.valueId).second est vrai. Vérifie que vus.insert(id).second est vrai. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ScreenFlowTest.TransitionsAutoriseesMenentALEcranAttendu (Critique) Source/Test/Unit/HMI/Interface/test_screen_flow.cpp:27 | Chaque transition autorisée mène à l'écran attendu. | 1. Résoudre chacune des transitions autorisées listées. 2. Vérifier l'écran résultant. | Vérifie que resolveTransition(menu, ScreenEvent::OpenEditor)->screen vaut ScreenId::Editor. Vérifie que resolveTransition(menu, ScreenEvent::OpenGame)->screen vaut ScreenId::Game. Vérifie que resolveTransition(menu, ScreenEvent::OpenOptions)->screen vaut ScreenId::Options. Vérifie que resolveTransition(editor, ScreenEvent::OpenMenu)->screen vaut ScreenId::Menu. Vérifie que resolveTransition(game, ScreenEvent::OpenMenu)->screen vaut ScreenId::Menu. Vérifie que resolveTransition(game, ScreenEvent::OpenPause)->screen vaut ScreenId::Pause. Vérifie que resolveTransition(pause, ScreenEvent::ResumePause)->screen vaut ScreenId::Game. Vérifie que resolveTransition(pause, ScreenEvent::QuitPauseToMenu)->screen vaut ScreenId::Menu. Vérifie que resolveTransition(pause, ScreenEvent::OpenOptions)->screen vaut ScreenId::Options. Vérifie que resolveTransition(optionsFromMenu, ScreenEvent::CloseOptions)->screen vaut ScreenId::Menu. Vérifie que resolveTransition(optionsFromPause, ScreenEvent::CloseOptions)->screen vaut ScreenId::Pause. Vérifie que resolveTransition(pause, ScreenEvent::QuitPauseToMenu)->screen vaut ScreenId::Menu. Vérifie que resolveTransition(menu, ScreenEvent::OpenCredits)->screen vaut ScreenId::Credits. Vérifie que resolveTransition(credits, ScreenEvent::CloseCredits)->screen vaut ScreenId::Menu. Vérifie que resolveTransition(menu, ScreenEvent::OpenRpgScreen)->screen vaut ScreenId::RpgScreen. Vérifie que resolveTransition(game, ScreenEvent::OpenRpgScreen)->screen vaut ScreenId::RpgScreen. Vérifie que resolveTransition(pause, ScreenEvent::OpenRpgScreen)->screen vaut ScreenId::RpgScreen. |
| ScreenFlowTest.OptionsRevientVersSonEcranDOrigine (Critique) Source/Test/Unit/HMI/Interface/test_screen_flow.cpp:74 | Options revient vers son écran d'origine (Menu ou Pause). | 1. Ouvrir Options depuis Menu, puis le fermer : vérifier le retour au Menu. 2. Ouvrir Options depuis Pause, puis le fermer : vérifier le retour à Pause. | Vérifie que openedFromMenu.has_value() est vrai. Vérifie que resolveTransition(*openedFromMenu, ScreenEvent::CloseOptions)->screen vaut ScreenId::Menu. Vérifie que openedFromPause.has_value() est vrai. Vérifie que resolveTransition(*openedFromPause, ScreenEvent::CloseOptions)->screen vaut ScreenId::Pause. |
| ScreenFlowTest.TransitionInterditeEstRefusee (Critique) Source/Test/Unit/HMI/Interface/test_screen_flow.cpp:102 | Une transition interdite est refusée. | 1. Tenter Editor -> Pause (via OpenPause). 2. Tenter Menu -> LevelComplete (via LevelSucceeded). 3. Tenter Menu -> Pause directement. | Vérifie que resolveTransition(editor, ScreenEvent::OpenPause) vaut std::nullopt. Vérifie que resolveTransition(menu, ScreenEvent::OpenPause) vaut std::nullopt. Vérifie que resolveTransition(menu, ScreenEvent::ResumePause) vaut std::nullopt. Vérifie que resolveTransition(editor, ScreenEvent::OpenOptions) vaut std::nullopt. Vérifie que resolveTransition(editor, ScreenEvent::OpenCredits) vaut std::nullopt. Vérifie que resolveTransition(game, ScreenEvent::OpenCredits) vaut std::nullopt. Vérifie que resolveTransition(editor, ScreenEvent::OpenRpgScreen) vaut std::nullopt. Vérifie que resolveTransition(menu, ScreenEvent::CloseRpgScreen) vaut std::nullopt. |
| ScreenFlowTest.EcranDuRpgRevientVersSonEcranDOrigine (?) Source/Test/Unit/HMI/Interface/test_screen_flow.cpp:131 | Un ecran du RPG revient vers son ecran d'origine (Menu, Game ou Pause). cat Unitaire · Machine à états des écrans crit Critique etapes 1. Ouvrir un ecran du RPG depuis le menu, le jeu puis la pause. 2. Le fermer a chaque fois et verifier l'ecran atteint. attendu Chaque fermeture revient a l'ecran d'origine respectif. | Vérifie que opened.has_value() est vrai. Vérifie que opened->rpgReturnTo vaut expected. Vérifie que resolveTransition(*opened, ScreenEvent::CloseRpgScreen)->screen vaut expected. | |
| ScreenFlowTest.HabillageDeFenetreEstCeluiAttenduParEcran (Majeur) Source/Test/Unit/HMI/Interface/test_screen_flow.cpp:159 | L'habillage de fenêtre est celui attendu pour chaque écran. | 1. Interroger l'habillage de chacun des sept écrans. 2. Vérifier chaque champ. | Vérifie que menu.docksVisible est faux. Vérifie que menu.menuBarVisible est faux. Vérifie que menu.toolBarVisible est faux. Vérifie que menu.pixelToolBarVisible est faux. Vérifie que menu.editingCommandsEnabled est faux. Vérifie que menu.gamepadNavigationActive est vrai. Vérifie que menu.overlayVisible est faux. Vérifie que editor.docksVisible est vrai. Vérifie que editor.menuBarVisible est vrai. Vérifie que editor.toolBarVisible est vrai. Vérifie que editor.pixelToolBarVisible est vrai. Vérifie que editor.editingCommandsEnabled est vrai. Vérifie que editor.gamepadNavigationActive est faux. Vérifie que editor.overlayVisible est faux. Vérifie que game.docksVisible est faux. Vérifie que game.menuBarVisible est faux. Vérifie que game.toolBarVisible est faux. Vérifie que game.pixelToolBarVisible est faux. Vérifie que game.editingCommandsEnabled est faux. Vérifie que game.gamepadNavigationActive est faux. Vérifie que game.overlayVisible est faux. Vérifie que options.docksVisible est faux. Vérifie que options.menuBarVisible est faux. Vérifie que options.toolBarVisible est faux. Vérifie que options.pixelToolBarVisible est faux. Vérifie que options.editingCommandsEnabled est faux. Vérifie que options.gamepadNavigationActive est vrai. Vérifie que options.overlayVisible est faux. Vérifie que rpg.docksVisible est faux. Vérifie que rpg.menuBarVisible est faux. Vérifie que rpg.editingCommandsEnabled est faux. Vérifie que rpg.gamepadNavigationActive est vrai. Vérifie que rpg.overlayVisible est faux. Vérifie que credits.docksVisible est faux. Vérifie que credits.menuBarVisible est faux. Vérifie que credits.toolBarVisible est faux. Vérifie que credits.pixelToolBarVisible est faux. Vérifie que credits.editingCommandsEnabled est faux. Vérifie que credits.gamepadNavigationActive est vrai. Vérifie que credits.overlayVisible est faux. Vérifie que overlay.docksVisible est faux. Vérifie que overlay.menuBarVisible est faux. Vérifie que overlay.toolBarVisible est faux. Vérifie que overlay.pixelToolBarVisible est faux. Vérifie que overlay.editingCommandsEnabled est faux. Vérifie que overlay.gamepadNavigationActive est vrai. Vérifie que overlay.overlayVisible est vrai. |
test_theme_teardown_guards.cpp
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ThemeTeardownGuardsTest.AucunePropieteDeBarreDeTitreDeDock (Critique) Source/Test/Unit/HMI/Interface/test_theme_teardown_guards.cpp:58 | La feuille de style ne porte aucune propriete de barre de titre de dock. | 1. Lire les feuilles de theme et en retirer les commentaires. 2. Chercher les proprietes de barre de titre de dock. | Vérifie que theme.empty() est faux. Vérifie que theme.find(forbidden) vaut std::string::npos. |
| ThemeTeardownGuardsTest.AucuneReferenceDeFichierExterne (Majeur) Source/Test/Unit/HMI/Interface/test_theme_teardown_guards.cpp:83 | La feuille de style ne reference aucun fichier externe. | 1. Lire les feuilles de theme et en retirer les commentaires. 2. Chercher un appel url(...). | Vérifie que theme.empty() est faux. Vérifie que target.empty() est faux. Vérifie que target.front() vaut ':'. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| LocalizationTest.AnalyseIgnoreCommentairesEtEspaces (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:35 | L'analyse ignore les lignes vides et les commentaires, et retire les espaces autour de '='. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que strings.size() vaut 2u. Vérifie que strings.at("menu.quitter") vaut "Quitter". Vérifie que strings.at("menu.titre") vaut "JustAnotherDnDGame". |
| LocalizationTest.AnalyseConserveEgalDansLaValeur (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:60 | Seul le premier '=' sépare ; un '=' dans la valeur est conservé. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que strings.size() vaut 1u. Vérifie que strings.at("expression") vaut "a = b + c". |
| LocalizationTest.CleExistanteResolue (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:77 | Une clé existante est résolue dans la langue active. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que localization.text("menu.quitter") vaut "Quitter". Vérifie que localization.activeLanguage() vaut "fr". |
| LocalizationTest.CleInconnueRenvoieLaCle (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:95 | Une clé inconnue partout est renvoyée telle quelle (repli déterministe, pas de plantage). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que localization.text("menu.inconnue") vaut "menu.inconnue". |
| LocalizationTest.ChangementDeLangue (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:114 | Changer de langue résout les valeurs de la nouvelle langue. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que localization.activeLanguage() vaut "en". Vérifie que localization.text("menu.quitter") vaut "Quit". |
| LocalizationTest.RepliSurLangueParDefaut (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:133 | Une clé manquante dans la langue active retombe sur la langue par défaut. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que localization.text("menu.quitter") vaut "Quit". Vérifie que localization.text("menu.titre") vaut "Jeu". |
| LocalizationTest.LangueAbsenteEstRecuperable (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:152 | Charger une langue absente échoue proprement et conserve la langue active (récupérable). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que localization.loadLanguage("xx") est faux. Vérifie que localization.activeLanguage() vaut "fr". Vérifie que localization.text("menu.quitter") vaut "Quitter". |
| LocalizationTest.CatalogueFrancaisLivreSeCharge (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:173 | Le catalogue français livré (Source/Elements/Localization) se charge et résout ses clés. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que localization.loadDefaultLanguage("fr") est vrai. Vérifie que localization.activeLanguage() vaut "fr". Vérifie que localization.text("menu.quit") vaut "Quitter". Vérifie que localization.text("menu.new_game") vaut "Nouvelle partie". |
| LocalizationTest.LesDeuxCataloguesDeclarentLesMemesCles (Majeur) Source/Test/Unit/HMI/Localization/test_localization.cpp:201 | Les catalogues francais et anglais declarent les memes cles. | 1. Charger fr.lang et en.lang. 2. Comparer les ensembles de cles dans les deux sens. | Vérifie que french.empty() est faux. Vérifie que english.empty() est faux. Vérifie que english.count(key) > 0 est vrai. Vérifie que french.count(key) > 0 est vrai. Vérifie que french.size() vaut english.size(). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| AnimationPersonnageIntegration.ALArretEstEnRepos (Majeur) Source/Test/Integration/test_animation_personnage.cpp:41 | A l'arret, le clip est Idle et l'image alterne 0/1 apres chaque duree d'image. | 1. Placer un acteur de vitesse nulle. 2. Avancer l'animation d'une duree d'image. | Vérifie que animation.clipIndex vaut core::PLAYER_CLIP_IDLE. Vérifie que animation.frameIndex vaut 0. Vérifie que animation.clipIndex vaut core::PLAYER_CLIP_IDLE. Vérifie que animation.frameIndex vaut 1. |
| AnimationPersonnageIntegration.EnMouvementCourt (Majeur) Source/Test/Integration/test_animation_personnage.cpp:71 | En mouvement, le clip est Run et l'image boucle sur les 4 images dans l'ordre. | 1. Placer un acteur en mouvement horizontal. 2. Avancer l'animation de quatre durees d'image. | Vérifie que animation.clipIndex vaut core::PLAYER_CLIP_RUN. Vérifie que animation.frameIndex vaut 0. Vérifie que animation.clipIndex vaut core::PLAYER_CLIP_RUN. Vérifie que animation.frameIndex vaut expectedFrame. |
| AnimationPersonnageIntegration.MarcheVerticaleCourtAussi (Majeur) Source/Test/Integration/test_animation_personnage.cpp:108 | Une marche purement verticale anime comme une marche horizontale. | 1. Placer un acteur dont la vitesse est purement verticale. 2. Avancer d'un pas. | Vérifie que world.getComponent<core::Animation>(entity).clipIndex vaut core::PLAYER_CLIP_RUN. |
| AnimationPersonnageIntegration.ChangementDeClipReinitialiseLImage (Majeur) Source/Test/Integration/test_animation_personnage.cpp:128 | Un changement de clip reinitialise immediatement l'image et le chronometre. | 1. Faire courir un acteur jusqu'a une image differente de 0. 2. Annuler sa vitesse. | Vérifie que animation.clipIndex vaut core::PLAYER_CLIP_RUN. Vérifie que animation.frameIndex vaut 1. Vérifie que animation.clipIndex vaut core::PLAYER_CLIP_IDLE. Vérifie que animation.frameIndex vaut 0. Vérifie que animation.elapsed vaut 0.0f (comparaison flottante). |
| AnimationPersonnageIntegration.EntiteSansAnimationIgnoree (Mineur) Source/Test/Integration/test_animation_personnage.cpp:161 | Une entite sans composant Animation n'est pas affectee par le systeme. | 1. Creer un acteur sans composant Animation. 2. Avancer le systeme dix pas. | Vérifie que world.hasComponent<core::Animation>(entity) est faux. |
| AnimationPersonnageIntegration.AnimationSansJeuDeClipsResteInerte (Mineur) Source/Test/Integration/test_animation_personnage.cpp:185 | Une entite Animation sans jeu de clips assigne reste inerte, sans planter. | 1. Creer un acteur dont l'Animation n'a aucun jeu de clips. 2. Avancer le systeme dix pas. | Vérifie que animation.clipIndex vaut 0. Vérifie que animation.frameIndex vaut 0. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| BoucleSimulationIntegration.CadenceurPiloteLaSimulation (Majeur) Source/Test/Integration/test_boucle_simulation.cpp:53 | Le cadenceur découpe un temps réel variable en pas fixes, et la position finale correspond exactement au nombre de pas réellement exécutés (aucune dérive). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que totalSteps vaut 4. Vérifie que position.x vaut 6.0f * totalSteps * STEP, à TOLERANCE près. |
| BoucleSimulationIntegration.MemeEntreeMemeResultat (Majeur) Source/Test/Integration/test_boucle_simulation.cpp:79 | Déterminisme : même séquence de frames et même état initial -> même résultat. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que firstPosition.x vaut secondPosition.x, à TOLERANCE près. Vérifie que firstPosition.y vaut secondPosition.y, à TOLERANCE près. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| EcsMouvementIntegration.EntiteMobileAvanceDeVitesseFoisPas (Majeur) Source/Test/Integration/test_ecs_mouvement.cpp:28 | Une entité Transform + Velocity avance de velocity * fixedDelta par pas ; après N pas, la position attendue est déterministe. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que position.x vaut 2.0f * steps * STEP, à TOLERANCE près. Vérifie que position.y vaut -3.0f * steps * STEP, à TOLERANCE près. |
| EcsMouvementIntegration.EntiteSansVelociteNeBougePas (Majeur) Source/Test/Integration/test_ecs_mouvement.cpp:58 | Une entité sans Velocity ne bouge pas. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que position.x vaut 5.0f, à TOLERANCE près. Vérifie que position.y vaut 5.0f, à TOLERANCE près. |
| EcsMouvementIntegration.DeuxEntitesEvoluentIndependamment (Majeur) Source/Test/Integration/test_ecs_mouvement.cpp:84 | Deux entités de vitesses différentes évoluent indépendamment. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que slowPosition.x vaut 1.0f, à TOLERANCE près. Vérifie que slowPosition.y vaut 0.0f, à TOLERANCE près. Vérifie que fastPosition.x vaut 0.0f, à TOLERANCE près. Vérifie que fastPosition.y vaut 4.0f, à TOLERANCE près. |
| EcsMouvementIntegration.IntegrationViaWorldUpdate (Majeur) Source/Test/Integration/test_ecs_mouvement.cpp:117 | Enregistré dans le World, le système s'exécute via World::update (chaîne complète). | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que position.x vaut 10.0f * steps * STEP, à TOLERANCE près. |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| NiveauEcsIntegration.DuJsonAuxEntites (Majeur) Source/Test/Integration/test_niveau_ecs.cpp:52 | Le niveau chargé peuple le monde d'une entité par tuile non vide, bien placée et typée. | 1. Mettre en place le contexte du test (arrangement). 2. Executer le scenario et verifier les assertions. | Vérifie que result.ok() est vrai. Vérifie que tilesByPosition.size() vaut 3u. Vérifie que tilesByPosition.count({0, 1}) vaut 0u. Vérifie que tilesByPosition.at({0, 0}) vaut static_cast<int>(core::TileType::Entry). Vérifie que tilesByPosition.at({1, 0}) vaut static_cast<int>(core::TileType::Solid). Vérifie que tilesByPosition.at({1, 1}) vaut static_cast<int>(core::TileType::Exit). |
| Titre (criticité) | Brief | Étapes | Résultat attendu |
|---|---|---|---|
| ParcoursEditionSysteme.EditeAnnuleEnregistreEtRechargeLeCadrageDeCamera (Critique) Source/Test/Systeme/test_parcours_edition.cpp:29 | Parcours complet d'édition du cadrage de caméra : choisir, annuler, enregistrer, recharger. | 1. Choisir le mode suivi sur un brouillon. 2. Annuler (undo) : retour au cadrage par défaut. 3. Choisir le mode par salle avec une taille personnalisée. 4. Enregistrer sur disque, recharger. | Vérifie que draft.cameraFraming().mode vaut core::CameraFramingMode::Follow. Vérifie que draft.undo() est vrai. Vérifie que draft.cameraFraming().mode vaut core::CameraFramingMode::WholeLevel. Vérifie que validated.ok() est vrai. Vérifie que core::LevelWriter::saveToFile(*validated.level, path) est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que level.cameraFraming().mode vaut core::CameraFramingMode::PerRoom. Vérifie que level.cameraFraming().roomWidthTiles.has_value() est vrai. Vérifie que *level.cameraFraming().roomWidthTiles vaut 10. Vérifie que level.cameraFraming().roomHeightTiles.has_value() est vrai. Vérifie que *level.cameraFraming().roomHeightTiles vaut 8. |
| ParcoursEditionSysteme.EditeDessineDesZonesDeCameraEnregistreEtRecharge (Critique) Source/Test/Systeme/test_parcours_edition.cpp:82 | Parcours complet d'édition des zones de caméra dessinées à la main. | 1. Passer en mode par salle, dessiner deux zones. 2. Retirer la première par erreur, annuler le retrait. 3. Enregistrer sur disque, recharger. | Vérifie que draft.cameraFraming().zones.size() vaut 2u. Vérifie que draft.cameraFraming().zones.size() vaut 1u. Vérifie que draft.undo() est vrai. Vérifie que draft.cameraFraming().zones.size() vaut 2u. Vérifie que validated.ok() est vrai. Vérifie que core::LevelWriter::saveToFile(*validated.level, path) est vrai. Vérifie que reloaded.ok() est vrai. Vérifie que level.cameraFraming().zones.size() vaut 2u. Vérifie que level.cameraFraming().zones[0] vaut (core::CameraZone{.x = 0, .y = 0, .width = 20, .height = 20}). Vérifie que level.cameraFraming().zones[1] vaut (core::CameraZone{.x = 20, .y = 0, .width = 10, .height = 20}). |