19.05/06前回(?)CircleCIでUnityをテスト/ビルドする、或いは.unitypackageを作るまででは、ユニットテストに関する部分がうまく行ってなくて放置でした。放置でいっかな、と思ってたんですが、改めてユニットテストをCIでがっつり実行したい、というかIL2CPPのテストをがっつしやりたい。いう切実な要望が私の中で発生したので(N回目)、改めて取り組んでみました。lineの節に書いてありました(コマンドライン引数のほうのマニュアルにはリンクすら張ってなかったので気づかなかった......!)。こんなふうにやればいい、と。結果が入ってるからそっち見ればOK、と。んー、いや、何か違うような。Runnerはいい感じなのだけれど、ビルドしてのテストだとイマイチ感がめっちゃ否めない。Modeテストもしたい。それをそのままCIや実機でテストできるように、表示やパイプラインだけをいい具合に処理するビルドを作る何かを用意すればいいんじゃないか、と。Runnerがイマイチだった頃に作った俺々テストフレームワークがありました。RunnerのCLI/GUIのフロントエンドとして機能するようにリニューアルしました。RunnerのPlayModeで動くテストがあれば、それだけで他に何もする必要はありません。こんなやつがあるとしてメニューのほうで適当にターゲットフレームワークとかIL2CPPがどうのとかを設定してもらってBuildUnitTestを押すと、こんなような結果が得られます。比較的ヒューマンリーダブルなログ!WindowsでもIL2CPPビルドができるようになったのがとっても捗るところで、検証用の小さめプロジェクトなら1分あればコード編集からチェックまで行けるので、リフレクションのキワイ部分をごりごり突いてもなんとかなる!昔のiOSでビルドして動かしてをやってたのは本当に死ぬほど辛かった......。これはHeadless(CUI)でビルドしたものですが、GUIでのビルドも可能です。イケてる画面かどうかでは微妙ですが、機能的には十二分です。Headlessだと上から下まで全部のテストを実行しちゃいますが、GUIだとピンポイントで実行するテストを選べるので(ただしメソッド単位ではなくクラス単位)、テストプロジェクトが大きくなっている場合はこっちのほうが便利ですね。Headlessでビルドしたものは、もちろんCIでそのまま実行できます。これはNGが出ている例ですが、ちゃんと真っ赤にCIのパイプラインが止まるようになってます。止まればもちろんCIの通知設定で、Slackでもなんでもどこにでもサクッと飛ばせます。実に正しい普通で普遍なやり方でいいじゃないですか。いうわけでやりたかったことが完璧にできてるのでめでたしめでたし。Unityでの限界、というかUnityのLinux対応が後手に回ってる影響をくらってビミョーという現実がやっと見えてきました。IL2CPPはまだサポートされてないので、CI上でIL2CPPビルドしたものを実行してテスト、みたいなのはその時点でできない。IL2CPPビルドを作って、実行だけ手元でやるのでもいっか、と思ったらそもそもLinuxでIL2CPPビルドができない。そりゃそうか、って気もしますが悲しみはある。いうわけで、コンテナベースでやるとどうしてもLinuxの上でのパターンが中心になってしまうので、Unityだと結構厳しいところはありますよねえ、という。VMも使えるので、多少コンフィグの書き方も変わってきますが(マシンセットアップ部分が面倒くさくなる!)、動かせなくもないんちゃうんちゃうんといったところです。DevOpsなどを使えばWindowsマシンが使えるので、こちらもUnityのインストールなどのセットアップは必要ですが、安心感はありますね。どちらにせよWindowsでしかビルドできないもの(Hololensとか)もあるので、ちょっとちゃんと考えてみるのはいいのかなあ、と思ってます。何れにせよ、VMでやるんだったらそりゃ普通にできますよね、という当たり前の結論に戻ってくるのが世の中きびすぃ。IL2CPP対応をどうかどうか......。RandomFixtureKitユニットテスト用にもう一個、RandomFixtureKitというライブラリを作りました。Core用とUnity用の両対応です。Cysharp/RandomFixtureKitなにかというと、オブジェクトにランダムで適当な値を自動で詰め込むという代物です。リフレクションの塊で、これのIL2CPP対応に、先のRuntimeUnitTestToolkitが役に立ちました。APIも単純でFixtureFactory.Createで取り出すだけ。short)>();テスト書いていてダミーのデータを延々と書くの面倒くせー、という局面はめっちゃあって、別に賢い名前なんて必要なくて(例えばAddressにはそれっぽい住所、Nameにはそれっぽい人名を入れてくれるとか)、全然ランダム英数でもいいから詰めてくれればそれでいいの!というところにピッタリはまります。実用的には、私はシリアライザの入れ替えとか(なぜか)よくやるんですが、旧シリアライザと新シリアライザで互換性なくて壊れたりしないように、相互に値を詰めたりとかして、同一の結果が得られることを確認したりします。そのときに、dllをなめて対象になる数百の型を取って、RandomFixtureKitを使って、適当な値を詰めた上で、一致を比較するユニットテストを用意するとかやったりします。面白い機能としては、ランダムな値ではなくて、エッジケースになり得る値だけを詰めるモードを用意しています。長さ9の中からランダムで詰める、といったものですね。いうキワいデータが入ったときにー、みたいなことは想定しなきゃいけないし、テストも書いておかなきゃなのは分かってるけれど、毎回データ変えて流すのクソ面倒くさいんですよね(私はシリアライザを(なぜか)よく書くので、本当にこういうデータをいっぱい用意する必要が実際ある)。CreateManyで1000個ぐらい作って流し込んでチェックすれば、多少はケースが埋まった状態になるでしょうというあれそれです。使ってみると意外と便利ですよ。Clientを作ってMagicOnionを強化するぜ、とか息巻いていたのですが全然できてない。副産物というか横道にそれたユニットテスト関連を仕上げて終わりとか、なんと虚しい......。できなかった理由の半分はSwitchでCelesteを遊び始めたらめちゃくちゃハマって延々とやり続けちゃったせいなのですが、まぁそれはそれで面白いゲームをたっぷり楽しめたということで有意義なのでよしということにしておきます。MagicOnionは6月4日に勉強会をやります。いうわけで、やる気もかなりあるし、アップデートネタも溜まっているんですが、実際にアップデートはできてないので(Issueのヘンジはちゃんとやってます!)、GWでガッと手を入れておきたかったんですが、うーん、まぁ明けてからやりまうす。良い感じになっていると思います。