web-dev-qa-db-fra.com

Comment déboguer les scripts Ruby?

J'ai copié le code Ruby suivant à partir d'Internet et apporté quelques modifications.

Mais ça ne marche pas!

S'il vous plaît aider. Que puis-je faire pour déboguer le programme par moi-même?

146
Andrew Grimm

Utilisez Pry ( GitHub ).

Installer via:

$ gem install pry
$ pry

Puis ajouter:

require 'pry'; binding.pry

dans votre programme.

Cependant, à partir de pry 0.12.2, il n’existe pas de commande de navigation telle que next, break, etc. Cette option est également fournie par d’autres gemmes, voir par exemple pry-byedebug .

134
horseyguy
  1. En rubis:

    Ruby -rdebug myscript.rb 
    

    ensuite,

    • b <line>: mettre le point d'arrêt
    • et n(ext) ou s(tep) et c(ontinue)
    • p(uts) pour l'affichage

    (comme Perl debug)

  2. Dans Rails: Lancez le serveur avec

    script/server --debugger
    

    et ajoutez debugger dans le code.

112
germanlinux

Comme recommandé: utilisez le levier! Je ne peux qu'être d'accord sur ce point.

pry est une bien meilleure réplique que irb.

Vous devez ajouter

require 'pry'

dans votre fichier source, puis insérez un point d'arrêt dans votre code source en ajoutant

binding.pry

à l'endroit où vous voulez jeter un coup d'œil sur les choses (c'est comme déclencher un point d'arrêt dans un environnement IDE classique)

Une fois que votre programme a atteint le

binding.pry

ligne, vous serez directement projeté dans la réplique, avec tout le contexte de votre programme à portée de main, de sorte que vous pourrez simplement explorer tout ce qui se trouve autour de vous, explorer tous les objets, changer d'état et même changer le code à la volée.

Je crois que vous ne pouvez pas changer le code de la méthode dans laquelle vous vous trouvez, vous ne pouvez donc malheureusement pas changer la prochaine ligne à exécuter. Mais bon Ruby le code a tendance à être simple ligne de toute façon ;-)

55
edx

Le débogage en levant des exceptions est beaucoup plus facile que jeté un œil sur les instructions de journal print, et pour la plupart des bogues, il est généralement beaucoup plus rapide que d’ouvrir un débogueur irb tel que pry ou byebug. Ces outils ne devraient pas être votre première étape.


Débogage rapide de Ruby/Rails:

1. Méthode rapide: élevez un Exception alors et _.inspect_ son résultat

Le moyen le plus rapide de déboguer le code Ruby (en particulier Rails) consiste à raise une exception le long du chemin d'exécution de votre code lors de l'appel de _.inspect_ sur la méthode ou l'objet (par exemple, foo):

_raise foo.inspect
_

Dans le code ci-dessus, raise déclenche un Exception qui interrompt l'exécution de votre code et renvoie un message d'erreur contenant commodément _.inspect_ informations sur l'objet/la méthode (c'est-à-dire foo) sur la ligne que vous êtes essayer de déboguer.

Cette technique est utile pour rapidement examiner un objet ou une méthode (. Par exemple, est-il nil? ) et pour confirmer immédiatement si une ligne de code est même exécutée dans un contexte donné.

2. Repli: utilisez un Ruby CISR débogueur comme byebug ou pry

Une fois que vous avez des informations sur l'état du flux d'exécution de vos codes, envisagez de passer à un débogueur Ruby gem irb tel que pry ou byebug, où vous pourrez approfondir l'état des objets dans votre chemin d'exécution.


Conseils généraux pour débutants

Lorsque vous essayez de déboguer un problème, nous vous conseillons de toujours: Lire le message d'erreur! @ # $ Ing (RTFM)

Cela signifie lire les messages d'erreur attentivement et complètement avant d'agir afin que vous comprend ce que vous essayez de vous dire. Lorsque vous déboguez, posez les questions mentales suivantes dans cet ordre , lors de la lecture d'un message d'erreur:

  1. Qu'est-ce que class l'erreur fait-elle référence? (i.e. est-ce que j'ai la classe d'objet correcte ou mon objet est-il nil? )
  2. Quelle méthode l'erreur fait-elle référence? (c'est-à-dire que est un type dans la méthode; puis-je appeler cette méthode sur ce type/cette classe d'objet? )
  3. Enfin, en utilisant ce que je peux déduire de mes deux dernières questions, quelles lignes de code dois-je examiner? (rappelez-vous: la dernière ligne de code dans la trace de la pile n'est pas nécessairement à l'origine du problème.)

Dans la trace de la pile, faites particulièrement attention aux lignes de code issues de votre projet (par exemple, les lignes commençant par _app/..._ si vous utilisez Rails). 99% du temps, le problème vient de votre propre code.


Pour illustrer pourquoi interpréter dans cet ordre est important ...

Par exemple. un message d'erreur Ruby qui déroute de nombreux débutants:

Vous exécutez du code qui s'exécute à un moment donné comme tel:

_@foo = Foo.new

...

@foo.bar
_

et vous obtenez une erreur qui dit:

undefined method "bar" for Nil:nilClass

Les débutants voient cette erreur et pensent que le problème est que la méthode bar est non définie . Ce n'est pas le cas. Dans cette erreur, la vraie partie qui compte est:

_for Nil:nilClass_

_for Nil:nilClass_ signifie que _@foo_ est nul! _@foo_ n'est pas une variable d'instance Foo! Vous avez un objet qui est Nil. Lorsque vous voyez cette erreur, c'est simplement Ruby qui essaie de vous dire que la méthode bar n'existe pas pour les objets de la classe Nil. (bien duh! puisque nous essayons d'utiliser une méthode pour un objet de la classe Foo et non Nil).

Malheureusement, en raison de la façon dont cette erreur est écrite (_undefined method "bar" for Nil:nilClass_), il est facile de se faire avoir en lui faisant croire que cette erreur a à voir avec bar étant undefined. Lorsqu'elle n'est pas lue attentivement, cette erreur amène les débutants à creuser par erreur dans les détails de la méthode bar sur Foo, en omettant entièrement la partie de l'erreur qui suggère que l'objet est de la mauvaise classe (dans le cas présent: nil). C'est une erreur qui peut être facilement évitée en lisant les messages d'erreur dans leur intégralité.

Résumé:

Toujours avec précaution lisez le message d'erreur entier avant de commencer tout débogage. Cela signifie: vérifiez toujours le type ) d'un objet dans un message d'erreur en premier , puis ses méthodes , avant vous commencez à chercher dans n'importe quelle pile ou ligne de code où vous pensez que l'erreur peut se produire. Ces 5 secondes peuvent vous faire économiser 5 heures de frustration.

tl; dr: Ne louchez pas les journaux d'impression, mais déclenchez des exceptions. Évitez les trous de lapin en lisant attentivement les erreurs avant le débogage.

29
Kelsey Hannan
  1. Imprimez les variables autant que possible. (Ceci s’appelle le débogage printf) Vous pouvez le faire en lançant

    STDERR.puts x.inspect
    

    ou

    STDERR.puts "Variable x is #{x.inspect}"
    

    Si vous voulez rendre cela plus facile à taper, alors vous voudrez peut-être utiliser la gemme exemple .

  2. Activer les avertissements. Si vous utilisez Ruby, exécutez-le avec le commutateur -w (par exemple, Ruby -w script.rb). Si vous l'exécutez à partir d'irb et que vous utilisez une version de Ruby antérieure à la 1.9.2, tapez $VERBOSE = true au début de votre session. Si vous mal orthographiez une variable d'instance, une fois les avertissements activés, vous obtiendrez

    warning: la variable d'instance @valeus n'est pas initialisée

  3. Comprendre le concept d'une côtelette binaire (la citation suivante est tirée de Pratiques d'un développeur agile )

    Divisez l'espace du problème en deux et voyez quelle moitié contient le problème. Puis divisez encore cette moitié en deux et répétez l'opération.

  4. Si vous réussissez avec un hachage binaire, vous constaterez peut-être qu’une seule ligne ne fait pas ce que vous attendez. Par exemple

    [1, 2, 3].include?([1,2])
    

    donne une valeur de false, même si on pourrait penser qu'il renverrait true. Dans ce cas, vous voudrez peut-être consulter la documentation. Les sites Web de documentation comprennent Ruby-doc.org , ou APIdock . Dans ce dernier cas, vous devriez taper include? à côté de la loupe située dans le coin supérieur droit, choisissez le include? qui comporte Array (si vous ne savez pas quelle classe [1, 2, 3] est, tapez [1, 2, 3].class dans irb) et vous obtenez include? (Array) , qui décrit son rôle.

    Cependant, si la documentation ne vous aide pas, vous obtiendrez probablement une bonne réponse si vous pouvez poser une question sur le fait qu'une ligne spécifique ne fait pas ce qu'elle devrait être, plutôt que sur la raison pour laquelle un script entier ne fait pas ce que vous faites. cela devrait.

20
Andrew Grimm

supprime toutes les choses

Bienvenue en 2017 ^ _ ^

Donc, si vous n'êtes pas opposé à essayer un nouveau IDE, vous pouvez procéder comme suit pour free .

Instructions rapides

  1. Installer vscode
  2. Installez Ruby Dev Kit si vous ne l'avez pas déjà fait.
  3. Installation des extensions Ruby, Ruby-linter et Ruby-rubocop pour vscode
  4. Installez manuellement toutes les gemmes spécifie rubyide/vscode-Ruby , si nécessaire
  5. Configurez votre launch.json pour utiliser les champs "cwd" et et "program" à l'aide de la macro {workspaceRoot}.
  6. Ajoutez un champ appelé "showDebuggerOutput" et définissez-le sur true.
  7. Activer les points d'arrêt partout dans vos préférences Debug en tant que "debug.allowBreakpointsEverywhere": true

Instructions détaillées

  1. Télécharger Code Visual Studio aka vscode; ce n'est pas la même chose que Visual Studio . C'est gratuit, léger et généralement considéré positivement.
  2. Installez le Ruby Kit de développement; vous devriez suivre les instructions à leur dépôt ici: https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
  3. Ensuite, vous pouvez installer des extensions via un navigateur Web ou à l’intérieur de l’EDI; c'est pour l'intérieur de l'IDE. Si vous choisissez l'autre, vous pouvez aller ici . Accédez à la partie Extensions de vscode; vous pouvez le faire de plusieurs façons, mais la méthode la plus durable sera probablement de frapper F1et en tapant ext jusqu'à ce qu'une option appelée Extensions: Installer les extensions devienne disponible. Des alternatives sont CtrlShiftx et dans la barre de menus supérieure, View->Extensions
  4. Ensuite, vous allez vouloir les extensions suivantes; ceux-ci ne sont pas nécessaires à 100%, mais je vous laisse décider de ce qu'il faut garder après en avoir bricolé:
    • Rubis; extension auteur Peng Lv
    • Ruby-rubocop; extension auteur misogi
    • Ruby-linter; extension auteur Cody Hoover
  5. Dans le répertoire de votre script Ruby, nous allons créer un répertoire via la ligne de commande appelée .vscode et vous y trouverez uniquement un fichier nommé launch.json. pour stocker des options de configuration.
    • launch.json contenu

{ "version": "0.2.0", "configurations": [ { "name": "Debug Local File", "type":"Ruby", "request": "launch", "cwd": "${workspaceRoot}", "program": "{workspaceRoot}/../script_name.rb", "args": [], "showDebuggerOutput": true } ] }

  1. Suivez les instructions des auteurs des extensions pour les installations manuelles de gemmes. Il se trouve ici pour l'instant: https://github.com/rubyide/vscode-Ruby#install-Ruby-dependencies
  2. Vous voudrez probablement pouvoir placer des points d'arrêt où bon vous semble; ne pas avoir cette option activée peut causer de la confusion. Pour ce faire, nous allons aller à la barre de menu supérieure et sélectionnez File->Preferences->Settings (ou Ctrl, ) et faites défiler jusqu'à la section Debug. Développez-le et cherchez un champ appelé "debug.allowBreakpointsEverywhere" - sélectionnez-le, cliquez sur la petite icône représentant un crayon et réglez-le sur true.

Après avoir fait toutes ces choses amusantes, vous devriez pouvoir définir des points d'arrêt et déboguer dans un menu similaire à celui-ci pour le milieu de 2017 et sur un thème plus sombre: enter image description here avec tout ce qui est amusant comme votre pile d’appel, votre afficheur de variables, etc.

Le plus gros fichier PITA est 1) l’installation des pré-requêtes et 2) la mémorisation de la configuration du fichier .vscode\launch.json. Seul le numéro 2 devrait ajouter n'importe quel bagage aux projets futurs, et vous pouvez simplement copier une configuration assez générique telle que celle listée ci-dessus. Il y a probablement un emplacement de configuration plus général, mais je ne le sais pas par cœur.

7
kayleeFrye_onDeck

Toutes les autres réponses donnent déjà presque tout ... Juste un petit ajout.

Si vous voulez plus de débogueur de type IDE (non-CLI) et que vous n’ayez pas peur d’utiliser Vim en tant qu’éditeur, je suggère Vim Ruby Debugger plug-in.

Sa documentation est assez simple, alors suivez le lien et voyez. En bref, cela vous permet de définir un point d'arrêt sur la ligne courante dans l'éditeur, d'afficher les variables locales dans une fenêtre astucieuse en pause, de passer de/vers - dans presque toutes les fonctions habituelles du débogueur.

Pour moi, il était très agréable d’utiliser ce débogueur vim pour déboguer une application Rails, bien que capacités d’enregistreur riche sur Rails en élimine presque le besoin.

6
NIA

Je viens de découvrir ce petit bijou (transforme Pry en un débogueur pour MRI Ruby 2.0+)

https://github.com/deivid-rodriguez/pry-byebug

Installer avec:

gem install pry-byebug

puis utilisez exactement comme pry, marquez la ligne que vous souhaitez interrompre à:

require 'pry'; binding.pry

Cependant, contrairement à Vanilla Pry, cette gemme contient des commandes de navigation clés telles que next, step et break:

break SomeClass#run            # Break at the start of `SomeClass#run`.
break Foo#bar if baz?          # Break at `Foo#bar` only if `baz?`.
break app/models/user.rb:15    # Break at line 15 in user.rb.
break 14                       # Break at line 14 in the current file.
6
nurettin
  1. Vous pouvez imprimer vos variables en cours de route
  2. Activer le drapeau -w (avertissements)
  3. Utilisez un outil tel que Ruby-debug
5
ghostdog74

A partir de Ruby 2.4.0, il est plus facile de démarrer une session IRB REPL au milieu de tout programme Ruby. Placez ces lignes au point du programme que vous souhaitez déboguer:

require 'irb'
binding.irb

Vous pouvez exécuter le code Ruby et imprimer des variables locales. Tapez Ctrl + D ou quit pour terminer le programme REPL et laisser le programme Ruby continuer à s'exécuter.

Vous pouvez également utiliser puts et p pour imprimer les valeurs de votre programme en cours d'exécution.

5
David Grayson

Je recommande fortement cette vidéo, afin de choisir le bon outil pour déboguer notre code.

https://www.youtube.com/watch?v=GwgF8GcynV

Personnellement, je soulignerais deux grands sujets dans cette vidéo.

  • Pry est génial pour les données de débogage, "Pry est un explorateur de données" (sic)
  • Le débogueur semble être préférable pour déboguer étape par étape.

C'est mes deux centimes!

5
DavidSilveira

Pour déboguer facilement le script shell Ruby, modifiez sa première ligne à partir de:

#!/usr/bin/env Ruby

à:

#!/usr/bin/env Ruby -rdebug

Ensuite, chaque fois que la console du débogueur est affichée, vous pouvez choisir:

  • c pour Continue (à la prochaine exception, point d'arrêt ou ligne avec: debugger),
  • n pour la ligne suivante,
  • w/where to Afficher le cadre/la pile d'appels,
  • l to Afficher le code actuel,
  • cat pour afficher les points d'accroche.
  • h pour plus d'aide.

Voir aussi: Débogage avec Ruby-debug , Raccourcis clés pour Ruby-debug gem .


Si le script ne fait que se bloque et que vous avez besoin d’une trace, essayez d’utiliser lldb/gdb comme:

echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf Ruby)

puis vérifiez votre processus au premier plan.

Remplacez lldb par gdb si cela fonctionne mieux. Préfixe avec Sudo pour déboguer les processus non possédés.

5
kenorb

Si vous utilisez RubyMine , le débogage des scripts Ruby est simple et direct.

Supposons que vous ayez un script Ruby hello_world.rb

1. Définir les points d'arrêt

Définissez un point d'arrêt à la ligne 6 comme ci-dessous.

enter image description here

2. Commencez le débogage

Vous pouvez maintenant démarrer le débogueur pour exécuter le script:

enter image description here

enter image description here

3. Inspecter les variables, etc.

Ensuite, lorsque l'exécution atteindra un point d'arrêt, vous pourrez inspecter des variables, etc.

enter image description here

Informations supplémentaires pour votre référence

  1. Si vous souhaitez tiliser RubyMine pour effectuer un débogage à distance , vous pouvez le faire.
  2. Si vous souhaitez tiliser RubyMine pour déboguer à distance Rails s'exécutant à l'intérieur d'un menu fixe , c'est également simple.
3
Yuci

Eh bien, Ruby lib standard a un débogueur de console simple à utiliser comme gdb: http://Ruby-doc.org/stdlib-2.1.0/libdoc/debug/rdoc/DEBUGGER__. html Pas besoin d'installer de gemmes supplémentaires. Les scripts Rails peuvent également être débogués de cette façon.

par exemple.

def say(Word)
  require 'debug'
  puts Word
end
2
Forvater

débogage printf

Il y a toujours eu une controverse autour des techniques de débogage. Certaines personnes aiment déboguer des instructions imprimées, d'autres aiment creuser plus profondément avec un débogueur.

Je suggère que vous essayez les deux approches.

En fait, un des anciens hommes d'Unix a récemment déclaré que le débogage de printf était un moyen plus rapide de le prendre à certains moments.

Mais si vous êtes nouveau dans un emploi et que vous avez besoin de comprendre un gros bloc de code, alors il est vraiment utile de s'y déplacer, de placer des points de rupture ici et là et de suivre son fonctionnement.

Cela devrait vous aider à comprendre comment le code est tissé.

Si vous êtes novice dans le logiciel d’autres peuples, il peut vous aider à y accéder.

Vous découvrirez rapidement s’ils l’ont arrangé de manière intelligente ou s’il s’agit simplement d’une bande de merde.

2
edx

Il existe de nombreux débogueurs dotés de fonctionnalités différentes, sur lesquels vous faites un choix. Mes priorités étaient satisfaites avec leviers qui était:

  • infos rapidement compréhensibles sur l'utilisation
  • étapes intuitives (comme entrer facilement dans des blocs)
  • "reculer" (les leviers répondent partiellement au besoin)
1
Daniel Garmoshka

La mère de tous les débogueurs est tout simplement un vieil écran d'impression. La plupart du temps, vous ne voulez probablement qu'inspecter des objets simples. Voici comment procéder:

@result = fetch_result

p "--------------------------"
p @result

Ceci imprimera le contenu de @result to STDOUT avec une ligne devant pour faciliter l'identification.

Si vous utilisez un framework capable de charger/recharger automatiquement, tel que Rails, vous n'aurez même pas besoin de redémarrer votre application. (Sauf si le code que vous déboguez n'est pas rechargé en raison de paramètres spécifiques à la structure)

Je trouve que cela fonctionne pour 90% des cas d'utilisation pour moi. Vous pouvez aussi utiliser Ruby-debug, mais la plupart du temps, je le trouve excessif.

1
Aaron Qian