この広告は、90日以上更新していないブログに表示しています。
3年前にこんな記事をあげました。
3行でまとめると、
というエントリでした。そしたらid:pocketberserker が作ってくれました!
PowerAssertより強そうな名前でいい感じです。
Power Assertは時代遅れ、今はMuscle Assertだ!的な話かな?
— 裸のWPF/MVVMを書く男(マン) (@gab_km)2016年6月1日
このライブラリは、PersimmonというF#用のテスティングフレームワークを拡張するライブラリとして作られています。ただ、ざっくり概要をつかむだけであればどちらも知らなくても問題ありません。このライブラリでできることはほぼ1つだけです。
openPersimmonopenPersimmon.Syntax.UseTestNameByReflectionopenPersimmon.MuscleAssertletadd x y= x+ ylet ``add23が5を返す``()= test{do! add23===5}
以上。簡単。これを実行しても成功してしまって面白みがないので、わざと間違ってみましょう。
openPersimmonopenPersimmon.Syntax.UseTestNameByReflectionopenPersimmon.MuscleAssertletadd x y= x+ x// ミス!let ``add23が5を返す``()= test{do! add23===5}
これをPersimmon.Consoleで実行すると、
Assertion Violated: add 2 3が5を返す 1. . left 4 right 5
こんなエラーが出てきました。普通ですね。
では、例えばこんなJSONがあったとしましょう。
{"widget":{ "debug": "on", "window":{ "title": "Sample Konfabulator Widget", "name": "main_window", "width":500, "height":500}, "image":{ "src": "Images/Sun.png", "name": "sun1", "hOffset":250, "vOffset":250, "alignment": "center"}, "text":{ "data": "Click Here", "size":36, "style": "bold", "name": "text1", "hOffset":250, "vOffset":100, "alignment": "center", "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"}}}
これを読み込む関数を定義したとして、その関数をテストしたいですよね。
letexpected=let ``JSONが読み込める``()= test{do! read json=== expected}
read 関数の実装にミスがあり、text のvOffset にhOffset の値を使ってしまったとしましょう。このテストを実行すると、下記のようなエラーメッセージが表示されます。
Assertion Violated: JSONが読み込める 1. .text.vOffset left 250 right 100
text のvOffset の値が左は250 だったけど、右は100 だった、ということが一目瞭然です。
MuscleAssertとPowerAssertの目的ははっきりと分かれています。MuscleAssertが最初からテスティングフレームワークのアサーションを書くために特化しているのに対して、PowerAssertは(テストではなく)表明に使うことを前提にデザインされています。
表明手段としてのPowerAssertはとても便利です。言語内蔵のassert は、条件式がfalse の場合に何やらメッセージを出しますが、「どこで表明がfalse と評価された」くらいの情報しか持っていません。メッセージをカスタマイズすることはできますが、文字列で指定する必要があるため「どうなったか」を埋め込むのは大変です。
PowerAssertは、言語内蔵のassert をそのままに表示されるメッセージをリッチにしてくれます。表明として埋め込んだ式の「部分式の値」がメッセージとして表示されるため、「どの式の評価値が想定と違うのか」を調べるための情報をコーディングのコストを払わずに得られるようになるのです。
対してMuscleAssertはそもそも、Persimmon.MuscleAssertはPersimmon用のライブラリとして作られているため、Persimmonに依存しており単体で使えるものではありません。表明に使えたとしても、MuscleAssertは式全体の評価結果の差分を出すため、ほしい情報である「どの式の評価値が想定と違うのか」を調べるための情報はそこに乗っていないでしょう。
表明手段としては、PowerAssertの圧勝です。
しかし、MuscleAssertがやりたかったのは表明ではありません。ユニットテストのアサーションとして使いたかったのです。
MuscleAssertが例えばJSONのようなネストした構造に対するテストに強そうだ、というのは先ほど紹介した例で分かると思います。XMLやJSONやYAMLは当然として、そもそもクラス自体が何かを内部に持っているネスト構造をしているため、ネストした構造をそのまま比較してもわかりやすいメッセージが出力されるMuscleAssertは便利です。
対してPowerAssertはこの例には貧弱です。
let ``JSONが読み込める``()= test{do! read json=== expected}
このテストが失敗するとして、PowerAssertで表示されるのは
json 変数の中身read json の結果expected の中身read json === expected がfalse になったということですかね。どれもドバドバと大量の出力をするわりに、本当に欲しい「どこがどう違うのか?」という情報はそこから得るのは容易ではありません。diffツールを使って外部でdiffとるとかしたことある人も多いんじゃないでしょうか?
そもそも、テストでactual 側に部分式が出てうれしいほど何かを書くことって多いのか?というのも疑問です。このテストのように、多くのテストでは期待値との一点比較ができればいいのではないでしょうか?
ちなみに、MuscleAssertでは一度に複数の箇所の間違いを出してくれますので、小さいテストをまとめるのも容易です。
1. .image.hOffset left 500 right 250 .image.vOffset left 500 right 250 .text.vOffset left 250 right 100 .text.alignment left centre right center @@ -1,6 +1,6 @@ cent -re +er
MuscleAssertの弱点は、一点比較しかできないところです。そのため、浮動小数点数を含むデータ構造を、浮動小数点数の一致範囲を指定して比較、ということは現状ではできません。また、大小比較などもサポートしていません。
現状でこれらをテストしたい場合は、MuscleAssertを使わずにテストするしかありません。今のところ、これで困ったことはありません(そういうテストが必要なドメインで仕事をしていない)。
まとめも3行で。
みなさんも自分が使っている言語でMuscleAssertを実装してみてはいかがでしょう?便利ですよ。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。