Ă propos du test des requĂȘtes personnalisĂ©es
CodeQL fournit un framework de test simple pour le test de rĂ©gression automatisĂ© des requĂȘtes. Testez vos requĂȘtes pour vous assurer quâelles se comportent comme prĂ©vu.
Au cours dâun test de requĂȘte, CodeQL compare les rĂ©sultats que lâutilisateur attend de la requĂȘte avec ceux rĂ©ellement gĂ©nĂ©rĂ©s. Si les rĂ©sultats attendus et rĂ©els diffĂšrent, le test de requĂȘte Ă©choue. Pour corriger le test, vous devez effectuer une itĂ©ration sur la requĂȘte et les rĂ©sultats attendus jusquâĂ ce que les rĂ©sultats rĂ©els et les rĂ©sultats attendus correspondent exactement. Cette rubrique vous montre comment crĂ©er des fichiers de test et exĂ©cuter des tests dessus Ă lâaide de la sous-commande test run
.
Configuration dâun pack de test CodeQL pour les requĂȘtes personnalisĂ©es
Tous les tests CodeQL doivent ĂȘtre stockĂ©s dans un pack CodeQL de « test » spĂ©cial. Autrement dit, un rĂ©pertoire pour les fichiers de test avec un fichier qlpack.yml
qui définit :
name: <name-of-test-pack>
version: 0.0.0
dependencies:
<codeql-libraries-and-queries-to-test>: "*"
extractor: <language-of-code-to-test>
La valeur dependencies
spĂ©cifie les packs CodeQL contenant des requĂȘtes Ă tester.
En gĂ©nĂ©ral, ces packs sont rĂ©solus Ă partir de la source. Il nâest donc pas nĂ©cessaire de spĂ©cifier une version fixe du pack. Lâextracteur (extractor
) dĂ©finit le langage quâutilisera lâinterface CLI pour crĂ©er des bases de donnĂ©es de test Ă partir des fichiers de code stockĂ©s dans ce pack CodeQL. Pour plus dâinformations, consultez « Personnalisation de lâanalyse avec des packs CodeQL ».
Il peut ĂȘtre utile dâexaminer la façon dont les tests de requĂȘtes sont organisĂ©s dans le dĂ©pĂŽt CodeQL. Chaque langage a un rĂ©pertoire src
, ql/<language>/ql/src
, qui contient des bibliothĂšques et des requĂȘtes pour lâanalyse des codebases. En plus du rĂ©pertoire src
, il existe un répertoire test
contenant des tests pour ces bibliothĂšques et requĂȘtes.
Chaque répertoire test
est configuré en tant que pack de test CodeQL avec deux sous-répertoires :
query-tests
sĂ©rie de sous-rĂ©pertoires contenant des tests pour les requĂȘtes stockĂ©es dans le rĂ©pertoiresrc
. Chaque sous-rĂ©pertoire contient du code de test et un fichier de rĂ©fĂ©rence QL qui spĂ©cifie la requĂȘte Ă tester.library-tests
sĂ©rie de sous-rĂ©pertoires contenant des tests pour les fichiers de bibliothĂšque QL. Chaque sous-rĂ©pertoire contient du code et des requĂȘtes de test qui ont Ă©tĂ© Ă©crites en tant que tests unitaires pour une bibliothĂšque.
AprÚs avoir créé le fichier qlpack.yml
, vous devez vous assurer que toutes les dĂ©pendances sont tĂ©lĂ©chargĂ©es et disponibles dans lâinterface CLI. Pour ce faire, exĂ©cutez la commande suivante dans le mĂȘme rĂ©pertoire que le fichier qlpack.yml
:
codeql pack install
Cette commande génÚre un fichier codeql-pack.lock.yml
qui spĂ©cifie toutes les dĂ©pendances transitives requises pour exĂ©cuter les requĂȘtes dans ce pack. Ce fichier doit ĂȘtre activĂ© dans le contrĂŽle de code source.
Configuration des fichiers de test pour une requĂȘte
Pour chaque requĂȘte que vous souhaitez tester, vous devez crĂ©er un sous-rĂ©pertoire dans le pack de test CodeQL. Ajoutez ensuite les fichiers suivants au sous-rĂ©pertoire avant dâexĂ©cuter la commande de test :
-
Fichier de rĂ©fĂ©rence de requĂȘte (fichier
.qlref
) dĂ©finissant lâemplacement de la requĂȘte Ă tester. Lâemplacement est dĂ©fini par rapport Ă la racine du pack CodeQL qui contient la requĂȘte. En gĂ©nĂ©ral, il sâagit dâun pack CodeQL spĂ©cifiĂ© dans le blocdependencies
du pack de test. Pour plus dâinformations, consultez « Fichiers de rĂ©fĂ©rence de requĂȘte ».Vous nâavez pas besoin dâajouter un fichier de rĂ©fĂ©rence de requĂȘte si la requĂȘte que vous souhaitez tester est stockĂ©e dans le rĂ©pertoire de test, mais il est gĂ©nĂ©ralement recommandĂ© de stocker les requĂȘtes sĂ©parĂ©ment des tests. La seule exception concerne les tests unitaires pour les bibliothĂšques QL, qui sont susceptibles dâĂȘtre stockĂ©es dans des packs de test, indĂ©pendamment des requĂȘtes qui gĂ©nĂšrent des alertes ou des chemins.
-
Exemple de code sur lequel vous souhaitez exĂ©cuter votre requĂȘte. Il doit sâagir dâun ou de plusieurs fichiers contenant des exemples du code que la requĂȘte est chargĂ©e dâidentifier.
Vous pouvez Ă©galement dĂ©finir les rĂ©sultats attendus lorsque vous exĂ©cutez la requĂȘte sur lâexemple de code, en crĂ©ant un fichier avec lâextension .expected
. Ou bien vous pouvez laisser la commande de test créer le fichier .expected
pour vous.
Pour obtenir un exemple montrant comment crĂ©er et tester une requĂȘte, consultez lâexemple ci-dessous.
Remarque
Vos fichiers .ql
, .qlref
et .expected
doivent avoir des noms cohérents :
- Si vous souhaitez spécifier directement le fichier
.ql
lui-mĂȘme dans la commande de test, il doit avoir le mĂȘme nom de base que le fichier.expected
correspondant. Par exemple, si la requĂȘte estMyJavaQuery.ql
, le fichier de rĂ©sultats attendu doit ĂȘtreMyJavaQuery.expected
. - Si vous souhaitez spécifier un fichier
.qlref
dans la commande, il doit avoir le mĂȘme nom de base que le fichier.expected
correspondant, mais la requĂȘte elle-mĂȘme peut avoir un nom diffĂ©rent. - Les noms des exemples de fichiers de code nâont pas besoin dâĂȘtre cohĂ©rents avec les autres fichiers de test. Tous les exemples de fichiers de code se trouvant en regard du fichier
.qlref
(ou.ql
) et dans tous les sous-rĂ©pertoires seront utilisĂ©s pour crĂ©er une base de donnĂ©es de test. Par consĂ©quent, par souci de simplicitĂ©, nous vous recommandons de ne pas enregistrer les fichiers de test dans des rĂ©pertoires qui sont des ancĂȘtres les uns des autres.
En cours dâexĂ©cution codeql test run
Les tests de requĂȘtes CodeQL sont exĂ©cutĂ©s en exĂ©cutant la commande suivante :
codeql test run <test|dir>
Lâargument <test|dir>
peut ĂȘtre un ou plusieurs des Ă©lĂ©ments suivants :
- Chemin dâun fichier
.ql
. - Chemin dâun fichier
.qlref
qui fait référence à un fichier.ql
. - Chemin dâun rĂ©pertoire dans lequel les fichiers
.ql
et.qlref
seront recherchés de maniÚre récursive.
Vous pouvez également spécifier :
--threads:
Facultatif. Nombre de threads Ă utiliser lors de lâexĂ©cution de requĂȘtes. Lâoption par dĂ©faut est1
. Vous pouvez spĂ©cifier dâautres threads pour accĂ©lĂ©rer lâexĂ©cution des requĂȘtes. Le fait de spĂ©cifier0
définir le nombre de threads sur le nombre de processeurs logiques.
Pour des dĂ©tails complets sur toutes les options que vous pouvez utiliser lors dâun test de requĂȘtes, consultez test run.
Exemple
Lâexemple suivant vous montre comment configurer un test pour une requĂȘte qui recherche dans du code Java des instructions if
qui ont des blocs then
vides. Il comprend des Ă©tapes permettant dâajouter la requĂȘte personnalisĂ©e et les fichiers de test correspondants Ă des packs CodeQL distincts en dehors de votre extraction du dĂ©pĂŽt CodeQL. Cela garantit que, lorsque vous mettez Ă jour les bibliothĂšques CodeQL ou que vous extrayez une autre branche, vous ne remplacerez pas vos requĂȘtes et tests personnalisĂ©s.
PrĂ©parer une requĂȘte et des fichiers de test
-
DĂ©veloppez la requĂȘte. Par exemple, la requĂȘte simple suivante recherche les blocs
then
vides dans le code Java :import java from IfStmt ifstmt where ifstmt.getThen() instanceof EmptyStmt select ifstmt, "This if statement has an empty then."
-
Enregistrez la requĂȘte dans un fichier nommĂ©
EmptyThen.ql
dans un rĂ©pertoire avec vos autres requĂȘtes personnalisĂ©es. Par exemple :custom-queries/java/queries/EmptyThen.ql
. -
Si vous nâavez pas encore ajoutĂ© vos requĂȘtes personnalisĂ©es Ă un pack CodeQL, crĂ©ez maintenant un pack CodeQL. Par exemple, si vos requĂȘtes Java personnalisĂ©es sont stockĂ©es dans
custom-queries/java/queries
, ajoutez un fichierqlpack.yml
avec le contenu suivant Ăcustom-queries/java/queries
:name: my-custom-queries dependencies: codeql/java-queries: "*"
Pour plus d'informations sur les packs CodeQL, consultez Personnalisation de lâanalyse avec des packs CodeQL.
-
Créez un pack CodeQL pour vos tests Java en ajoutant un fichier
qlpack.yml
avec le contenu suivant Ăcustom-queries/java/tests
, en mettant à jour les dépendances (dependencies
) pour quâelles correspondent au nom de votre pack CodeQL de requĂȘtes personnalisĂ©es :Le fichier
qlpack.yml
suivant indique quemy-github-user/my-query-tests
dépend demy-github-user/my-custom-queries
dont la version est ultĂ©rieure ou Ă©gale Ă 1.2.3 et antĂ©rieure Ă 2.0.0. Il dĂ©clare Ă©galement que lâinterface CLI doit utiliser lâextracteur (extractor
) Java lors de la création de bases de données de test. La lignetests: .
déclare que tous les fichiers.ql
du pack doivent ĂȘtre exĂ©cutĂ©s en tant que tests quandcodeql test run
est exĂ©cutĂ© avec lâoption--strict-test-discovery
. En général, les packs de test ne contiennent pas de propriétéversion
. Cela vous empĂȘche de les publier accidentellement.name: my-github-user/my-query-tests dependencies: my-github-user/my-custom-queries: ^1.2.3 extractor: java-kotlin tests: .
-
Exécutez
codeql pack install
à la racine du répertoire de test. Cette commande génÚre un fichiercodeql-pack.lock.yml
qui spĂ©cifie toutes les dĂ©pendances transitives requises pour exĂ©cuter les requĂȘtes dans ce pack. -
Dans le pack de test Java, crĂ©ez un rĂ©pertoire pour contenir les fichiers de test associĂ©s Ă
EmptyThen.ql
. Par exemple :custom-queries/java/tests/EmptyThen
. -
Dans le nouveau répertoire, créez
EmptyThen.qlref
pour dĂ©finir lâemplacement deEmptyThen.ql
. Le chemin de la requĂȘte doit ĂȘtre spĂ©cifiĂ© par rapport Ă la racine du pack CodeQL qui contient la requĂȘte. Dans ce cas, la requĂȘte se trouve dans le rĂ©pertoire de niveau supĂ©rieur du pack CodeQL nommĂ©my-custom-queries
, qui est déclaré en tant que dépendance pourmy-query-tests
. Par conséquent,EmptyThen.qlref
doit simplement contenirEmptyThen.ql
. -
Créez un extrait de code à tester. Le code Java suivant contient une instruction
if
vide sur la troisiĂšme ligne. Enregistrez-le danscustom-queries/java/tests/EmptyThen/Test.java
.class Test { public void problem(String arg) { if (arg.isEmpty()) ; { System.out.println("Empty argument"); } } public void good(String arg) { if (arg.isEmpty()) { System.out.println("Empty argument"); } } }
Exécuter le test
Pour exécuter le test, accédez au répertoire custom-queries
et exécutez codeql test run java/tests/EmptyThen
.
Lorsque le test sâexĂ©cute, il :
-
Recherche un test dans le répertoire
EmptyThen
. -
Extrait une base de données CodeQL à partir des fichiers
.java
stockés dans le répertoireEmptyThen
. -
Compile la requĂȘte rĂ©fĂ©rencĂ©e par le fichier
EmptyThen.qlref
.Si cette Ă©tape Ă©choue, câest parce que lâinterface CLI ne trouve pas votre pack CodeQL personnalisĂ©. RĂ©exĂ©cutez la commande et spĂ©cifiez lâemplacement de votre pack CodeQL personnalisĂ© ; par exemple :
codeql test run --search-path=java java/tests/EmptyThen
Pour plus dâinformations sur lâenregistrement du chemin de recherche dans le cadre de votre configuration, consultez SpĂ©cification des options de commande dans un fichier de configuration CodeQL.
-
ExĂ©cute le test en exĂ©cutant la requĂȘte et en gĂ©nĂ©rant un fichier de rĂ©sultats
EmptyThen.actual
. -
Recherche un fichier
EmptyThen.expected
à comparer avec le fichier de résultats.actual
. -
Signale les résultats du test ; dans le cas présent, un échec :
0 tests passed; 1 tests failed:
. Le test a Ă©chouĂ© car nous nâavons pas encore ajoutĂ© un fichier avec les rĂ©sultats attendus de la requĂȘte.
Afficher la sortie du test de requĂȘte
CodeQL génÚre les fichiers suivants dans le répertoire EmptyThen
:
EmptyThen.actual
, un fichier qui contient les rĂ©sultats rĂ©els gĂ©nĂ©rĂ©s par la requĂȘte.EmptyThen.testproj
, une base de données de test que vous pouvez charger dans VS Code et utiliser pour déboguer les tests défaillants. Lorsque les tests se terminent correctement, cette base de données est supprimée dans une étape de nettoyage. Vous pouvez remplacer cette étape en exécutanttest run
avec lâoption--keep-databases
.
Dans le cas prĂ©sent, lâĂ©chec Ă©tait attendu et est facile Ă corriger. Si vous ouvrez le fichier EmptyThen.actual
, vous pouvez voir les résultats du test :
| Test.java:3:5:3:22 | stmt | This if statement has an empty then. |
Ce fichier contient une table, avec une colonne pour lâemplacement du rĂ©sultat, ainsi que des colonnes distinctes pour chaque partie de la clause select
que la requĂȘte gĂ©nĂšre.
Ătant donnĂ© que les rĂ©sultats correspondent Ă ce que nous attendions, nous pouvons mettre Ă jour lâextension de fichier pour la dĂ©finir ce rĂ©sultat comme rĂ©sultat attendu pour ce test (EmptyThen.expected
).
Si vous réexécutez le test maintenant, la sortie sera similaire, mais il se terminera en signalant : All 1 tests passed.
.
Si les rĂ©sultats de la requĂȘte changent, par exemple si vous rĂ©visez lâinstruction select
pour la requĂȘte, le test Ă©chouera. Pour les rĂ©sultats ayant Ă©chouĂ©, la sortie de lâinterface CLI inclut une diffĂ©rence unifiĂ©e des fichiers EmptyThen.expected
et EmptyThen.actual
.
Ces informations peuvent ĂȘtre suffisantes pour dĂ©boguer des Ă©checs de test triviaux.
Pour les échecs qui sont plus difficiles à déboguer, vous pouvez importer EmptyThen.testproj
dans CodeQL pour VS Code, exécuter EmptyThen.ql
et afficher les rĂ©sultats dans lâexemple de code Test.java
. Pour plus dâinformations, consultez « Gestion de bases de donnĂ©es CodeQL ».