Skip to content

HTMLやJavaScriptのデバッグ

ソフトウェア開発を進める作業段階では,

  • 設計どおりに動作しない!
  • 出力結果がおかしい!

など,多く不具合に悩まされる.このような不具合は,主としてプログラムが正しく書かれていないことに起因するものがほとんどであり,このことをバグがある(bug: 小さな虫,という意味)という.ソフトウェア開発においては,この「バグ」を発見したり修正したりする作業が不可欠である.

特に,HTMLやJavaScriptは(C言語などのコンパイラ言語とは違って)実行してみるまで文法的なエラーが分からないといったデメリットもある.JavaScriptは(良い意味でも悪い意味でも)自由すぎる言語なので,何の支援もなしにデバッグ作業を行う(de-bug: bugを取り除く)と相当に苦労する.

ここでは,chromium-browserやFirefoxなどのブラウザに搭載されているデバッグ支援ツールを利用した典型的なデバッグ方法を記載するので,各自うまく使いこなそう.

デバッグ支援ツールの起動

本講義サイトのあちこちに記載しているが,chromium-browserやFirefoxの場合,

  • F12キー
  • または Ctrl+Shift+I キー

デベロッパツール(Firefoxだと開発ツールという名称)を開くことができる.

  • chromium-browserの場合

chrome-developer

  • Firefoxの場合

firefox-developer

これを上手く利用すると,デバッグを効率的に行うことができる.

consoleを使いこなす

console.log

console.log('コンソールに表示する');

これを(ブラウザ経由で)実行すると,デベロッパツールのconsoleタブに表示される.

このように,プログラム(スクリプト)内の適当な場所にconsole.log()を挟み,実行中にconsoleタブでその内容を確認することがまず第一の基本となる.


console.error, console.warn

エラーや警告などの用途によって,出力先を分けることもできる.

console.error('エラーの場合');
console.warn('警告の場合');

この場合,consoleタブでは色分けされて(かつアイコンも追加されて)表示される.


console.table

配列の中身を確認したい場合は,console.logよりもconsole.tableがお勧め.

var ary = [{
    name1: "sato",
    name2: "suzuki",
    name3: "tanaka"
}];
  • console.logの場合
console.log(ary);

  • console.tableの場合
console.table(ary);

array_table


console.trace

関数の呼び出し元をトレースできる.

(function first() {
    function second() {
        function third() {
            console.trace();
        }
        third();
    }
    second();
})();

ブレークポイントを使う

ブレークポイント(break point)を設定すると,プログラム実行時に割り込んで停止や再開を行うことができる.

ブレークポイントの設定法

デベロッパツールを使う方法と,JavaScriptプログラムを直接,編集して設定する方法がある.

例えば,次のようなJavaScriptプログラムに対し,

 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var ary = [
    ['A','B','C'],
    ['D','E','F'],
    ['G','H','I']
];

for (var i = 0; i < ary.length; i++){
    for (var j = 0; j < ary[i].length; j++){
        document.write(ary[i][j] + ' ');
    }
    document.write("<br />");
}

デベロッパツールのSourceタブを開き,「停止させたい該当の行をクリック」すると,以下のようにブレークポイントが設定される.

あるいは,スクリプト内(の止めたい箇所)に直接,debugger;という記述を加えても良い.

 5
 6
 7
 8
 9
10
11
    ['G','H','I']
];

debugger;
for (var i = 0; i < ary.length; i++){
    for (var j = 0; j < ary[i].length; j++){
}

どちらの場合でも,ページをリロードすると設定したブレークポイントで処理が止まる


ブレークポイントからの処理再開

さて,ブレークポイントで処理を止めたら,Sourceタブの右側にあるボタン群を利用して特別な実行を行うことができる.(プログラム実行の流れに介入して,進め方をコントロールすることができる)

処理再開

次のブレークポイントまで,もし無ければ最後まで処理を続行する.

ステップオーバー

現在のステートメントを実行してから次のステートメントで停止する.もし,現在のステートメントが関数呼び出しであった場合には,その関数全体を実行し,関数呼び出し後の次のステートメントで停止する.

ステップイン

現在のステートメントを実行してから次のステートメントで停止する.現在のステートメントが関数呼び出しであった場合,その関数に処理が遷移したところで止まる.

ステップアウト

現在の関数の外まで実行する.関数が入れ子になっている場合には1つ上のレベルまで進んだら止まる(現在の関数を抜けた段階で止まる).


プログラム実行中の値の変更

さて,上記のサンプルでは,配列ary

Array(3)
 0: Array(3)
  0: "A"
  1: "B"
  2: "C"
 1: Array(3)
  0: "D"
  1: "E"
  2: "F"
 2: Array(3)
  0: "G"
  1: "H"
  2: "I"

とセットされるはずである.これは,デベロッパツールSourceタブ右側の,Scopeから確認することができる.

Scope

これを変更してみようScopeに表示されているプロパティのところでダブルグリックすると,直接,値を変更できる.

A〜Iをそれぞれ,J〜Rに変更して「処理再開」すると,実行結果もこれに応じて変わるはずである.


ブレークポイントまとめ

以上のように,任意の箇所にブレークポイントを設定し,ステップ実行しながら動作確認,場合によっては変数の値を変更してみる,などのデバッグが行えるようになる.

さらには,他の班員が作ったモジュールをテストする際,あえてイレギュラーな値を渡して動作確認してみる,といったこともできるので,ぜひ使いこなせるようになろう.

Socket.ioを使ったプログラムの場合

サーバ(Node.js)側

起動時にDEBUG環境変数にsocket.io*を設定しておくと,サーバ動作中にいろいろログが表示されるようになる.

$ DEBUG=socket.io* node main.js
socket.io:server initializing namespace / +0ms
socket.io-parser encoding packet {"type":0,"nsp":"/"} +0ms
socket.io-parser encoded {"type":0,"nsp":"/"} as 0 +1ms
socket.io:server creating engine.io instance with opts {"path":"/socket.io","initialPacket":["0"]} +4ms
socket.io:server attaching client serving req handler +17ms
Server started on port:6004
...

クライアント側

HTML5から導入されたlocalStorageを使うとよい.

スクリプトの中(先頭付近でよい)に

localStorage.debug = 'socket.io-client:socket';

という行を挿入しておくと,ブラウザのConsoleにいろいろログが表示されるようになる.