今回のリリースでは「テスト実行順のランダム化」を実装しました。正直気は進まなかったんですけどね・・・。shuf コマンドでいいやん。
なんで実装したかというと、bats-core のリポジトリを眺めていてこのプルリクを見つけたからです。
あー、対応するんだー、対応するんやー。って感じで。
「テスト実行順のランダム化」は、基本の実行順番のランダム化の機能に加えて、SEED値を与えることで同じ順番を再現する機能があります。後者の機能は「SEED値 + ファイル名 + example ID」の文字列のハッシュ値を計算しその値を元に乱数を求めて、その順番で並び替えることで実現しています。つまり、ハッシュ計算、乱数計算、ソート の3つの処理が必要になります。
bats-core では awk とか paste とか使ってやってるようでギリギリPOSIX準拠の範囲での実装かな?とも思うのですが、awk は gawk やら nawk やら mawk やらいろいろ派生バージョンがあって互換性でハマるのが見えてるのであまり使いたくない所です。
ランダム値の取得は bash であれば $RANDOM 変数からを取れるのですが、POSIX準拠の範囲ではawkを使う以外では(おそらく)ないんじゃないかと思います。/dev/random や /dev/urandom も必ずしも実装されているわけじゃないようですし。
またハッシュ計算は、POSIX準拠の範囲では cksum コマンドがあるのですが、データの入力は当たり前ではありますが(複数の)ファイルもしくは標準入力からとなっています。今回やるべきことは全てのテスト項目「SEED値 + ファイル名 + example ID」のそれぞれに対してハッシュ値を求めることなのですが、例えば shellspec 自身のテストは 400 以上あります。つまり400個以上のプロセス起動かファイル作成が必要になります。ちょっとやりたくないですね。
ということで、ハッシュ計算と乱数計算をシェルスクリプトだけで実装することにしました。実装が簡単で処理が速そうなものと言う観点から、ハッシュ計算として FNV-1a、 乱数計算としてXorshift を採用しました。どちらもコードが短く四則演算とビット演算の機能だけで実装できます。
ソートに関しては sort コマンドを実行しています。シェルスクリプトで実装するのは手間な割に必要な呼び出し回数は1回だけだし、POSIX準拠コマンドの中でも基本のコマンドなので busybox を含め動かないということはないでしょう。