1. Avant de commencer
Arrivés à ce stade, il est probable que la plupart des développeurs sachent comment déboguer à l'aide d'instructions de journal. Si vous avez terminé le module 1, vous savez également comment lire les traces de la pile et faire des recherches dans les messages d'erreur. Bien qu'il s'agisse là de deux puissants outils de débogage, les IDE modernes offrent davantage de fonctionnalités pour améliorer l'efficacité de votre processus de débogage.
Dans cette leçon, vous allez découvrir ce qu'est le débogueur intégré d'Android Studio, comment suspendre l'exécution d'une application et comment exécuter le code ligne par ligne pour identifier la source exacte du bug. Vous apprendrez également à utiliser la fonctionnalité Watches et à effectuer le suivi de variables spécifiques sans devoir ajouter d'instructions de journalisation spécifiques.
Conditions préalables
- Vous savez comment naviguer dans un projet dans Android Studio.
- Vous maîtrisez la journalisation en langage Kotlin.
Points abordés
- Comment associer le débogueur à une application en cours d'exécution.
- Utiliser des points d'arrêt pour mettre en pause une application en cours d'exécution et inspecter le code ligne par ligne.
- Ajouter des expressions conditionnelles à des points d'arrêt pour accélérer le débogage.
- Ajouter des variables au volet Watches pour faciliter le débogage.
Ce dont vous avez besoin
- Un ordinateur sur lequel est installé Android Studio
2. Créer un projet
Plutôt que de déboguer une application volumineuse et complexe, nous allons commencer par un projet vide et introduire du code comportant des bugs pour faire la démonstration des outils de débogage d'Android Studio.
Commencez par créer un projet Android Studio.
- Sur l'écran Sélectionner un modèle de projet, choisissez Activité vide.
- Nommez l'application Débogage et assurez-vous que le langage est défini sur Kotlin. Ne modifiez pas les autres champs.
- Un nouveau projet Android Studio vous est proposé. Il affiche un fichier nommé
MainActivity.kt
.
Introduire un bug
Vous vous souvenez de l'exemple de division par zéro présenté dans la leçon sur le débogage du module 1 ? Dans la dernière itération de la boucle, lorsque l'application tente d'effectuer une division par zéro, elle plante avec java.langArithmeticException
, car il est impossible de diviser par zéro. Ce bug a été trouvé et corrigé en examinant la trace de la pile, et cette hypothèse a été validée à l'aide d'instructions de journalisation.
Comme vous connaissez déjà cet exemple, nous nous en servirons pour montrer comment utiliser des points d'arrêt. Les points d'arrêt parcourent le code ligne par ligne, sans qu'il soit nécessaire d'ajouter des instructions de journalisation, ni de réexécuter votre application au préalable.
- Ouvrez
MainActivity.kt
et remplacez le code par ce qui suit :
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
public val TAG = "MainActivity"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
division()
}
fun division() {
val numerator = 60
var denominator = 4
repeat(5) {
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
}
- Exécutez l'application. Notez que l'application plante comme prévu.
3. Déboguer avec des points d'arrêt
Lorsque vous avez découvert la journalisation, vous avez appris à placer des journaux de manière stratégique pour identifier les bugs et vérifier qu'ils ont bien été corrigés. Toutefois, lorsque vous rencontrez des bugs que vous n'avez pas introduits, il n'est pas toujours évident de savoir où placer les instructions de journalisation ou quelles variables imprimer. Souvent, ces informations ne sont disponibles qu'au moment de l'exécution.
fun division() {
val numerator = 60
var denominator = 4
repeat(5) {
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
C'est là que les points d'arrêt entrent en jeu. Même si vous n'avez qu'une vague idée de l'origine du bug sur la base des informations figurant dans la trace de la pile, vous pouvez ajouter un point d'arrêt qui fait office de panneau d'arrêt pour une ligne de code spécifique. Une fois le point d'arrêt atteint, l'exécution est suspendue, ce qui vous permet d'utiliser d'autres outils de débogage au moment de l'exécution pour obtenir une vue précise de ce qui se passe et de ce qui ne va pas.
Associer le débogueur
En arrière-plan, Android Studio utilise un outil appelé Android Debug Bridge, également connu sous sa forme abrégée ADB. Cet outil de ligne de commande est intégré à Android Studio et fournit des fonctionnalités de débogage (telles que des points d'arrêt) à vos applications en cours d'exécution. Les outils de débogage sont souvent appelés débogueurs.
Pour utiliser le débogueur ou l'associer à une application, vous ne pouvez pas simplement exécuter l'application en sélectionnant Exécuter > Exécuter, comme auparavant, mais vous devez utiliser Exécuter > Déboguer l'application.
Ajouter des points d'arrêt à votre projet
Pour voir les points d'arrêt en action, procédez comme suit :
- Ajoutez un point d'arrêt en cliquant dans la marge à côté du numéro de ligne au niveau duquel effectuer la pause. Un point apparaît à côté du numéro de ligne et la ligne est mise en surbrillance.
- Exécutez votre application avec le débogueur associé. Pour cela, utilisez Run > Debug 'app' ou l'icône dans la barre d'outils. Au lancement de l'application, l'écran suivant doit s'afficher :
Une fois l'application lancée, le point d'arrêt est mis en surbrillance lors de son activation.
Un nouvel onglet Débogage s'ouvre au bas de l'écran où la fenêtre Logcat était précédemment affichée.
Sur la gauche se trouve une liste de fonctions (les mêmes que celles figurant dans la liste affichée dans la trace de la pile). Le volet de droite vous permet de vérifier les valeurs des différentes variables de la fonction actuelle (division()
). En haut de l'écran, des boutons vous permettent de naviguer dans votre programme lorsque l'exécution est suspendue. Le bouton que vous utiliserez le plus souvent est Passer, qui exécute la ligne de code mise en surbrillance.
Pour déboguer le code, procédez comme suit :
- Une fois le point d'arrêt atteint, la ligne 19 (qui déclare la variable
numerator
) est mise en surbrillance, mais elle n'a pas encore été exécutée. Utilisez le bouton Passer pour exécuter la ligne 19. La ligne 20 apparaît maintenant en surbrillance.
- Définissez un point d'arrêt à la ligne 22. C'est à ce niveau que la division a eu lieu et que la trace de la pile a signalé l'exception.
- Utilisez le bouton Reprendre le programme à gauche de la fenêtre Débogage pour accéder au point d'arrêt suivant. Exécutez le reste de la fonction
division()
.
- Notez que l'exécution s'arrête à la ligne 17, avant de l'exécuter.
- Les valeurs de chaque variable
numerator
etdenominator
sont affichées à côté de leurs déclarations. Les valeurs des variables sont visibles dans la fenêtre de débogage de l'onglet Variables.
- Appuyez encore quatre fois sur le bouton Resume Program (Reprendre le programme) à gauche de la fenêtre de débogage. À chaque fois, la boucle s'interrompt et observe les valeurs de
numerator
etdenominator
. Lors de la dernière itération,numerator
doit être60
, etdenominator
doit être0
. Et vous ne pouvez pas diviser 60 par 0 !
Désormais, vous connaissez précisément la ligne de code à l'origine du bug, ainsi que la raison exacte du problème. Comme précédemment, vous pouvez corriger le bug en modifiant le nombre de répétitions du code, qui passe de 5
à 4
.
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
4. Définir des conditions pour les points d'arrêt
Dans la section précédente, vous deviez parcourir chaque itération de la boucle jusqu'à ce que le dénominateur soit égal à zéro. Dans les applications plus complexes, cela peut s'avérer fastidieux si vous disposez de moins d'informations sur le bug. Toutefois, si vous avez une hypothèse (par exemple, l'application plante uniquement lorsque le dénominateur est égal à zéro), vous pouvez modifier le point d'arrêt de sorte qu'il ne soit atteint que lorsque cette hypothèse se vérifie, au lieu de devoir parcourir chaque itération en boucle.
- Si nécessaire, introduisez à nouveau le bug en remplaçant
4
par5
dans la boucle de répétition.
repeat(4) {
...
}
- Placez un nouveau point d'arrêt sur la ligne avec l'instruction
repeat
.
- Effectuez un clic droit sur l'icône de point d'arrêt rouge. Un menu s'affiche avec quelques options permettant, par exemple, d'activer ou non le point d'arrêt. Il existe toujours un point d'arrêt désactivé, mais il ne se déclenche pas au moment de l'exécution. Vous avez également la possibilité d'ajouter une expression Kotlin qui, si elle prend la valeur "True", déclenche le point d'arrêt. Par exemple, si vous avez utilisé l'expression
denominator > 3
, le point d'arrêt n'est déclenché que lors de la première itération de la boucle. Pour que le point d'arrêt ne soit déclenché que lorsque votre application est susceptible d'effectuer une division par zéro, définissez l'expression surdenominator == 0
. Les options du point d'arrêt doivent se présenter comme suit :
- Sélectionnez Exécuter > Déboguer l'Application pour exécuter votre application et vérifiez que le point d'arrêt est atteint.
Comme vous pouvez le voir, le dénominateur est déjà égal à 0. Le point d'arrêt n'a été déclenché que lorsque la condition était remplie, ce qui vous permet de parcourir le code plus rapidement et plus facilement.
- Ici encore, vous constatez que le bug est causé par un nombre d'exécutions trop élevé de la boucle, alors que le dénominateur était défini sur 0.
Ajouter des variables Watch
Si vous souhaitez surveiller une valeur spécifique pendant le débogage, il n'est pas nécessaire de parcourir l'onglet Variables pour la trouver. Pour ce faire, vous pouvez en effet ajouter ce que l'on appelle des Watches. Ces variables sont visibles dans le volet de débogage. Lorsque l'exécution est suspendue et que cette variable entre dans le champ d'application, elle est visible dans le volet "Watches". Cela améliore l'efficacité du débogage lorsque vous travaillez sur des projets plus importants. Vous pourrez effectuer le suivi de toutes les variables pertinentes au même endroit.
- Dans la vue de débogage, un autre volet vide intitulé Watches est normalement visible à droite du volet des variables. Cliquez sur le bouton Plus dans l'angle supérieur gauche. L'option de menu New Watch s'affiche alors.
- Saisissez le nom de la variable,
denominator
, dans le champ prévu à cet effet, puis appuyez sur Entrée. - Exécutez à nouveau votre application en sélectionnant Run > debug 'app'. Lorsque le point d'arrêt est atteint, la valeur du dénominateur s'affiche alors dans le volet "Watches".
5. Félicitations
En résumé :
- Vous pouvez définir des points d'arrêt pour suspendre l'exécution de votre application.
- Lorsque l'exécution est suspendue, vous pouvez "passer outre" pour n'exécuter qu'une seule ligne de code.
- Vous pouvez définir des instructions conditionnelles pour ne déclencher les points d'arrêt qu'en fonction d'une expression Kotlin.
- Les Watches vous permettent de regrouper des variables d'intérêt lors du débogage.