gopwt(PowerAssert for golang)がだいたいできた

http://github.com/ToQoz/gopwt

この時は、「Assert内で副作用のある関数を呼んでいるとそれがコケた場合に、出力の時に再度呼ばれて実際の値と違うものが表示されたり、それ以降のテストに影響がある」みたいな問題があった。それを解決するには適当に関数の呼び出しをキャッシュしてやる必要があって、型のチェックが実行時にしかない言語なら、a() == b() とかってのを memorized(a) == memorized(b) とかってできると思うけど、わりかし大変だった。

  • reflect.ValueOf(f).Call(reflect.ValueOf(arg1), reflect.ValueOf(arg2))[0].Interface() というように変換して変換後のコンパイル時の型のチェックを捨てる
  • そうすると取れる型が決まってる二項演算子が使えない Opなんとか(x, y interface{}) を実装してその中で型をチェックしながら適当に適用していく感じにする
  • 組み込みの関数は、reflect.ValueOf(f).Call で呼べないから普通に呼ぶがそうすると型がハマらないので Op*と一緒のようなものを実装する
  • このへんまではまあ別にいいかなと思ってたんだけど、型の変換(string('r')) で上手くいかないことに気付いてかなり辛くなる。
  • こざかしいことをして*ast.CallExprが普通の関数呼び出しか型の変換かを調べて、後者なら reflect.ValueOf(x).Convert(reflect.ValueOf(new(t)).Elem().Type()) に変換する。

みたいなことをやった。こざかしいことは、code.google.com/p/go.tools/goのgcimporterとtypesのおかげで、楽に出来たんだけど一気にブラックボックス感が高まった感じがした。

そもそもこういうアプローチはGoっぽくないと思う(作る前もgo testに乗せれないかとかなんとか色々悩んだ)けど、TDDでdebugの代わりのテストみたいなのを書いて開発してく時とか、CIでテストコケた時の情報量の多さは結構メリットがあるかなと思う。自分以外が関わるところでこれに依存したテストをコミットするかどうかは今のところ自分自身悩ましい感じはある。まずはv0.0.1を打てるようにやっていく予定

(仕事する気力が無さすぎてエントリ書き出したものの気力がないから雑になった。)