Web

Webアプリのバグ調査方法

会社でWebアプリを開発しています。
新人よりバグ

  • 知識によるものもあるのですが、
  • エラーメッセージを理解していない
  • 検討違いのところでデバッグしている

私のバグ調査方法をまとめてみました。

ここでいうバグとは「開発者が期待した通りに動かない」こととします。

開発環境

  • Terasolunaフレームワーク(strutsベース, iBatis, spring)
  • Tomcat8
  • Java8
  • Eclipse4.5
  • HTML, JavaScript, CSS
  • PostgresSQL9.5

1. コードが最新の状態であることを確認

キャッシュが残っていたり、古いコードがデプロイされているなど、そもそもコードが新しくない場合があります。
まずはコードが最新であることを確認しましょう。

サーバ上のファイル(Java, JSP, XML, properties)

  1. プロジェクトのリフレッシュ
  2. サーバの再起動
  3. %TOMCAT_HOME%/work/フォルダ内のclass,jspファイルの更新日時が、最新であることを確認
  4. テスト環境/本番環境の場合は、%TOMCAT_HOME%/webapps/[warファイル名]/WEB-INF/classes

クライアント上のファイル(HTML, JavaScript, CSS)

  1. ブラウザのキャッシュをクリア
    • [Ctrl+F5]を押す(IEの場合クリアされないときがある)
    • ブラウザの設定からキャッシュクリア
    • 対象ファイルのURLに、URLクエリを付与して最新のコードを表示(URLが変わるのでキャッシュしたコードは表示されない)
  2. ブラウザの開発者ツールなどで、対象のファイルが最新であることを確認

2. 再現条件を探す

再現条件が分からないと、デバッガなどを使った調査ができません。
「Aボタンを2回押したときバグが発生する」のような、ざっくりとした条件でよいので、再現条件を探しましょう。

この段階では、「バグが発生しない条件」は探す必要はありません。
たとえば「ブラウザAではバグが起こるけど、ブラウザBでは起こらない」などです。
知っているに越したことはありませんが、知らなくてもエラーメッセージやデバッガを使えば、解決できるバグがほとんどです。
ここでの再現条件は、「エラーメッセージの確認」や「デバッガを使った調査」ができる程度の条件でよいです。

再現しないバグもたまにはありますが、直接メモリを操作しないJavaを使っているので、そうそうないでしょう。

3. エラーメッセージを確認する

エラーメッセージをよく読み、何が原因かを考えましょう。
また、エラーメッセージに「答えとなる原因」が書いてあるときが、意外に多いです。
英語メッセージのため理解しづらいかもしれませんが、斜め読みせずによく読みましょう。

サーバ側のエラーメッセージを確認

以下のいずれかで、エラーメッセージを確認します。

  • Eclipseのコンソールウィンドウ
  • テスト環境/本番環境の場合は、%TOMCAT_HOME%/log/*stdout*.log,%TOMCAT_HOME%/log/*stderr*.log

Exceptionのスタックトレースが出力されていなければ、出力するようにしましょう。
スタックトレースでは、どのメソッドから呼ばれて、ソースの何行目でエラーが発生したという、情報が分かります。
スタックトレースの読み方は、下記サイトが参考になります。
http://www.atmarkit.co.jp/ait/articles/0605/20/news012.html

わんさかエラーが出ている場合、一番最初に出力されたエラーメッセージを確認してください。
そこがエラーメッセージの「元」です。それ以降のエラーメッセージは、エラーが発生したことによる別のエラーメッセージで、確認してもあまり意味はありません。

SQL関係のエラーが発生した場合

  • データベースに接続できていない
    • データベースは起動しているか。OSのサービスなどを確認。
    • ホスト名、ユーザ名、パスワードを間違っていないか?
  • 呼び出すSQL文が存在していない

    • 呼び出すSQL文のID名は、Java側とXML側(SQL外部ファイル)で一致しているか?namespace属性も確認。
    • SQL文を書いた外部ファイルが読み込まれているか。webapps/WEB-INF/sqlMapConfig.xmlを確認。
    • parameter mapでエラー(JavaからSQL側に入力値を渡す部分)
    • parameterClass属性に書いたクラス名は存在しているか
    • <parameter>タグのproperty属性値は、Java側と一致するか?またJava側でpublicのgetterが用意されているか?
    • result mapでエラー(SELECT文の結果をJava側に渡す部分)
    • resultClass属性に書いたクラス名は存在しているか
    • <result>タグのproperty属性値は、Java側と一致するか。またJava側でpublicのsetterが用意されているか?

クライアント側(JavaScript)のエラーメッセージを確認する

ブラウザの開発ツールからコンソールを開いて、エラーメッセージを確認しましょう。
なお、クライアント側のエラーメッセージは、通常スタックトレースではなく「~ is not defined」のような一文なので、サーバ側と比べると分かりづらいです。
(try-catchを使えばスタックトレースを出力できるが、一般的ではない?)

4. デバッガを使って

エラーメッセージを読んでも理解できなかった場合は、デバッガを使ってバグの原因を調査しましょう。

# 参考サイト
http://qiita.com/jkr_2255/items/4b8a8245a48a1df29b3e
http://www.avnet.co.jp/embedded/column/Theme5/04.aspx