Power Assertを試してみる
Groovy1.7から導入されたPower Assertを試してみた。
これによりassertによる検証エラーが発生した場合の式の状態が詳細に表示され、問題の原因を素早く特定できる。
Contents
- 1. まずは実行
- 2. javaコマンドから実行した場合は?
- 3. コードに直接既述してるからじゃね?
- 4. 2010/01/23 追記
まずは実行
assertを利用した簡単なコードを記述する。
test.groovy
#!/usr/bin/env groovy def list = [1, 3, 4, 5, 2] assert 5 == list.max() - 1
ほいで実行。
$ chmod750test.groovy $ ./test.groovy
Caught: Assertion failed: assert 5 == list.max() - 1 | | | | | | 5 4 | [1, 3, 4, 5, 2] false at test.run(test.groovy:3)
これはわかりやすい。ただ、いくつか疑問点が浮かんできた。
javaコマンドから実行した場合は?
groovycでコンパイルしたクラスファイルをjavaコマンドで呼び出してもちゃんと表示されるのか?
と思ったので試してみた。
$ groovyc test.groovy $ java -cp$GROOVY_HOME/embeddable/groovy-all-1.7.0.jar:. test Exception in thread "main" Assertion failed: assert 5== list.max() - 1 | | | | | | 54 | [1, 3, 4, 5, 2]false at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:378) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:662) at test.run(test.groovy:3) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:88) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886) at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:743) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:726) at org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:386) at org.codehaus.groovy.runtime.InvokerHelper$runScript.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:129) at test.main(test.groovy)
groovyコマンドで実行した場合と表示される例外文の量に違いはあるが、Power Assertの解析結果はちゃんと表示されている。javaにも欲しい。
コードに直接既述してるからじゃね?
ということでコマンドライン引数からもらった値を利用したコードに書き換える。
test2.groovy
#!/usr/bin/env groovy def list = args.collect{ it.toInteger() } assert 5 == list.max() - 1
ほいで実行。
$ groovyc test2.groovy $ java -cp$GROOVY_HOME/embeddable/groovy-all-1.7.0.jar:. test2 37814 Exception in thread "main" Assertion failed: assert 5== list.max() - 1 | | | | | | 87 | [3, 7, 8, 1, 4]false at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:378) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:662) at test2.run(test2.groovy:3) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:88) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886) at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:743) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:726) at org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:386) at org.codehaus.groovy.runtime.InvokerHelper$runScript.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:129) at test2.main(test2.groovy)
これはデバッグ時だけでなく、本番稼働時の不具合原因時に貢献してくれるはず。
2010/01/23 追記
しくみはid:uehajさんのBlogや、コメントのPowerAssertを参考に。
uehaj's blog
ディスカッション
コメント一覧
こんちは!。PowerAssertいいですよね。PowerAssertの結果がgroovycでコンパイルしても表示される理由ですが、Power AssertはAST変換で実現されていて、AST変換はその名のとおり、コンパイルフェイズの構文木の加工変換処理で実行されます。バイトコードになる前の段階ということです。groovycで吐き出されたものは、すでに変換済みのものです。どういう変換かというと、Power Assertに関しては、assert文を、「assertに渡す式の各節の値(式を構成するサブ式の値すべて)を(assertに失敗したときには)ツリー表示する」というコードに変換していますね。ある意味、ソースコード上の式の構造を、コンパイルによって失わずに、ランタイムまで持っていく、という方式です。サイズは結構増えるはずです。
AST変換ですか。なんどか聞いているこのキーワードがからんでるのですね。
いつもコメントありがとうございます。