Power Assertを試してみる

Groovy

Groovy1.7から導入されたPower Assertを試してみた。

これによりassertによる検証エラーが発生した場合の式の状態が詳細に表示され、問題の原因を素早く特定できる。

まずは実行

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

Groovy