会社でWebアプリを開発しています。
新人よりバグ
- 知識によるものもあるのですが、
- エラーメッセージを理解していない
- 検討違いのところでデバッグしている
私のバグ調査方法をまとめてみました。
ここでいうバグとは「開発者が期待した通りに動かない」こととします。
開発環境
- Terasolunaフレームワーク(strutsベース, iBatis, spring)
- Tomcat8
- Java8
- Eclipse4.5
- HTML, JavaScript, CSS
- PostgresSQL9.5
1. コードが最新の状態であることを確認
キャッシュが残っていたり、古いコードがデプロイされているなど、そもそもコードが新しくない場合があります。
まずはコードが最新であることを確認しましょう。
サーバ上のファイル(Java, JSP, XML, properties)
- プロジェクトのリフレッシュ
- サーバの再起動
-
%TOMCAT_HOME%/work/
フォルダ内のclass,jspファイルの更新日時が、最新であることを確認 - テスト環境/本番環境の場合は、
%TOMCAT_HOME%/webapps/[warファイル名]/WEB-INF/classes
クライアント上のファイル(HTML, JavaScript, CSS)
- ブラウザのキャッシュをクリア
- [Ctrl+F5]を押す(IEの場合クリアされないときがある)
- ブラウザの設定からキャッシュクリア
- 対象ファイルのURLに、URLクエリを付与して最新のコードを表示(URLが変わるのでキャッシュしたコードは表示されない)
- ブラウザの開発者ツールなどで、対象のファイルが最新であることを確認
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
を確認。
- 呼び出すSQL文のID名は、Java側とXML側(SQL外部ファイル)で一致しているか?
-
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