やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

Unite Tokyo 2019『Unity Test Runnerを活用して内部品質を向上しよう』のフォローアップ #UniteTokyo

9/25, 26に開催されたUnite Tokyo 2019 Day 2に『Unity Test Runnerを活用して内部品質を向上しよう』というタイトルで登壇させていただきました。

スライドはすでにUnity Learning Materialsで公開中。動画は後日公開される予定です。

learning.unity3d.jp togetter.com

以下、説明が足りなかったところ、質疑応答やTwitterでコメントいただいた点など補足していきます。

CEDEC 2019『組織にテストを書く文化を根付かせる戦略と戦術』 (p.6)

いきなり、TDD(テスト駆動開発)の大家、@t_wadaさんによるCEDEC 2019でのセッションを紹介しました。 私はUnity製ゲームに特化した話をしましたが、そのベースとなる、より一般的な視点での開発者テストについて語られています。 ぜひ併せて読んでいただくことをおすすめします。

cedil.cesa.or.jp

当日「すでに見た」という方に挙手いただきましたが、2割いないくらいで驚きました。こちらを見てテストに興味を持って来る方が大多数だと思っていたので、その前段階なしでテストのセッションに興味を持ってたくさん来ていただいたのは良い意味で予想外でした。

Unity Test Framework (p.33)

Unity 2019.2からUnity Test Runnerがpackage化されたことに触れましたが、それにまつわる変更についてコメントいただきましたので確認して別記事にまとめました。

www.nowsprinting.com

Player(実機)でのテスト実行 (p.34)

実機でのテスト実行についてセッションで触れなかったので、別記事にまとめました【10.2追記】

www.nowsprinting.com

インテグレーションテスト (p.52)

スライドで紹介した、Sceneベースのテストフレームワークはこちら。

github.com gitlab.com

AltUnityTesterについては、以前Gotanda.unityでお話したスライドも参考にしてください。

www.slideshare.net

インライン化 (p.65)

これはきちんと検証できていないので情報のみですが、インライン化してほしいメソッドに [MethodImpl(MethodImplOptions.AggressiveInlining)] アノテーションをつけることで積極的なインライン化を指示できるはずです。

ただし、Unityエディタ上では無効、MonoおよびIL2CPPでは有効なようです。

このあたり情報源はForumのこのスレッドを読んだだけなので、追って検証していくつもりです。

検証しました。次の記事を参照してください。 [2021/12/16追記] www.nowsprinting.com

AllocatingGCMemory (p.68)

Unity 2018.3で追加されたAPIです。ドキュメントはこちら。

Class AllocatingGCMemoryConstraint | Test Framework | 1.1.30

使用例はこんな感じ。下はsut.UsePrimitive()の中でGCされるメモリ(ヒープ)を確保していたら(Is.Notなので)failするテストです。

[Test]
public void UsePrimitive_isNotAllocatingGCMemory()
{
    Assert.That(() => sut.UsePrimitive(), Is.Not.AllocatingGCMemory());
}

AllocatingGCMemoryについては、お伝え忘れていた重要なトピックがあります。対象のメソッド内(上例ではUsePrimitive())でDebug.Log()を使用していると、その中でメモリ確保が行われるためfailしてしまいます。

性能を要求されるメソッド内でDebug.Log()を使うことは無いとは思うのですが、ご注意ください。

依存オブジェクト (p.70)

依存オブジェクトを持つコンポーネントのテストを行なうためのパターンとして、「Dependency Injectionパターン」や「Test Doubleパターン」があります。

そのパターンを踏まえて、少ないコードで実現させるフレームワークが存在します。確かに便利なのですが、ツール・フレームワークに振り回されることがないように、基本を知っておくことは大事です。

スライドでもご紹介した『xUnit Test Patterns』、Kindle版がセール中のようです。この機会に買って積んでみてはいかがでしょうか。

テストダブル (p.71)

Test Doubleパターンについては、@goyokiさんのこちらの記事が参考になります。

goyoki.hatenablog.com

もしくは拙著『iOSアプリテスト自動化入門』(絶版)がお手元にあれば、「2.3.5 テストダブル」を参照してください。

YAGNI (p.77)

Wikipediaさんにも載っているYAGNI*1。"You ain't gonna need it"の略で、今必要ないものは考えない・実装しない、という意味で使います。技術者なら言いたいセリフ「こんなこともあろうかと」とは対極にある言葉です。

ja.wikipedia.org

シンプルに「今は必要ないから考慮しない」という意味でも使えますが、テストコードがあることによって後々の仕様変更のコストとリスクが減るために取れる選択肢でもあります。

また、これはセッションでは取り上げなかったのですが、XPやアジャイル開発の文脈で言われる「ドキュメントは書かない」も、本来はテストコードがドキュメントの役割をなす "Test as Documentation" が前提だったりします。

境界値を攻めすぎない (p.80)

前提となる「境界値テスト」の話を端折ってしまったので補足します。

例えば、HPゲージが通常はグリーン、HP 50%以下はイエロー、HP 20%以下はレッド、という色を返すメソッドを例にします。

public static Color GaugeColor(int hp, int maxHp)
{
    var percent = hp / maxHp;
    if (percent <= 20)
    {
        return Color.red;
    }
    if (percent <= 50)
    {
        return Color.yellow;
    }
    return Color.green;
}

このとき、結果が分岐する条件となる入力値である「0〜20%」「21〜50%」「51〜100%」はテスト用語で「同値クラス」と呼ばれます。 そして同値クラス同士の隣接した値、ここでは 20, 21, 50, 51 が「境界値」です。

境界値にはバグが発生しやすいので*2、通常のテストではよく境界値のテストを実施します。しかしゲームの世界では、「やっぱりHP 30%で赤にしよう」といった変更もあるのではないでしょうか。

同じ境界値でも、「HPが0になったら死ぬ」といった境界値は厳密にテストしていいのですが、HPゲージの見た目であれば「10%」「40%」「80%」くらいのゆるい値でテストしておけば、最低限色が変わることは保証できますし、しきい値が調整されてもテストコードを修正する手間もありません。

つまり、境界値を厳密に評価する必要があるテストなのかどうか、という「出力」の見極めが大事ということです。

なお、上例では、引数がhp > maxHpmaxHp=0で呼ばれる可能性を考慮していません。テストを書く過程でこうしたことに気付けるケースもよくあります。

テストコードの構造化 (p.82)

@goyokiさんのスライドが参考になります。

www.slideshare.net

ただし、過度の構造化によってテストコードの可読性が損なわれたり、プロダクトコード側にテストのためのコードが紛れ込んでしまうアンチパターンもありますので注意が必要です。

あくまでも目的は、テストコードが壊れにくくなる、堅牢性 (robustness) のための構造化です。

質疑応答

講演後の質疑応答には10名ほど来てくださり、30分ほどQ&Aさせていただきました。以下、覚えている範囲で*3

Unity Test Runner以外のテストツール・フレームワークは使っていないのか?(Miyamasuとか)

  • ユニットテストとしてはEdit mode testsに絞っているので、Unity Test Runnerのみ
  • もう少し上層の(結合度の)テストは、ツールから分けている

MonoBehaviourのテストをどうしているか(Play mode testsでしかできないのか)

  • MonoBehaviourのテストであっても、Edit mode testsでのテストは可能
  • ただし、責務が分離されていないとテストしづらいのはお話した通り。コンポーネントごとの分離も必要だし、MonoBehaviourと、個々の処理を分離することも必要。例えば、Update()にすべて書くのではなくメソッドを分けていく
  • テスタビリティを上げるためのデザインパターンとしてHumble Object Patternが知られています。これも『xUnit Test Patterns』に書かれています

Humble Object Patternについては、@adarapataさんのスライドも参考になります。

www.slideshare.net

静的解析ツールはあるのか

  • JetBrainsさんが "ReSharper Command Line Tools" を提供しています。インスペクション、重複コードの検出、コードクリーンナップをコマンドラインから実行できます
  • 実行にUnityエディタライセンスもReSharperライセンスも不要ですが、WIndows版のみ

www.jetbrains.com

所感

テストのセッションということでどのくらい来ていただけるか不安でしたが、400人部屋の8割くらい埋まっていたように見えました。ありがとうございました。

セッションのほうは、後半急ぎ足になってしまい反省しています。これでも直前になっていくつかトピックを削ったりTipsにまわしたりしたのですが…。

なお、壇上から客席まで距離があり、かつ照明の関係で暗く、客席の反応がほとんどわからなかったので戸惑いました。冒頭で笑いを取ってペースを掴むのが常套手段なのですが、ウケているのかどうかわからないのはつらかったです。

Unite Tokyo 2019全体について。皆さんTwitter等で書かれていますが、とても素晴らしい会場とホスピタリティで、たいへん満足度の高いカンファレンスでした。スピーカー特典で利用できたVIPルームおよびVIP席もものすごく快適で、来年は登壇しなくてもVIPチケットは確保しようと心に決めました。

最後に。今回のUniteのセッション公募、気づいたのは締め切り4.5h前でした。@nkjzmさんに感謝。

参考文献

*1:読みは「ヤグニ」でいいはず。みんなそう言ってるので…

*2:実装以前に、仕様書の段階で「以下」と「未満」があいまいであったり矛盾があったりもありがちなバグです

*3:こんな質問もしたよ!というのがあればTwitter等で教えて下さい

Unity 2019.2からのUnity Test RunnerとUnity Test Framework #UniteTokyo

9/25, 26に開催されたUnite Tokyo 2019の『Unity Test Runnerを活用して内部品質を向上しよう』というセッションで、Unity Test RunnerがUnity 2019.2からpackage化されたことをお話ししました。

その際、以下の情報をいただいたので確認してみました。

なお、本セッションのスライドはすでにUnity Learning Materialsで公開中。動画は後日公開される予定です。

learning.unity3d.jp togetter.com

セッション全体のフォローアップ記事はこちら。

www.nowsprinting.com

Unity 2019.2のAssembly Definition Files

Unity 2019.2でのAssembly Definitionは次のようにインスペクタに表示されます。

f:id:nowsprinting:20190928122522p:plain:w400

たしかに"Test Assemblies"のチェックボックスは無くなり、かわりにUnityEngine.TestRunnerおよびUnityEditor.TestRunnerへの参照が追加されています。

しかし実際のasmdefファイルの中身は下記の通りで、Unity 2019.1以前と変わっていませんでした。Unity 2019.1以前からのマイグレーションでも、新規に作ったasmdefでも同様です。

{
    "name": "UniteSample-Test-EditMode",
    "references": [
        "UniteSample",
        "UniteSample-Editor"
    ],
    "optionalUnityReferences": [
        "TestAssemblies"
    ],
    (snip)
}

このあたりはUnityエディタのインスペクタ上の表示仕様であり*1、package化されたUnity Test Frameworkのバージョンには依存しないと思われますので、これ以上は追求しないことにします。

Play mode tests用テストコードを格納するフォルダとasmdefファイルは、Projectウィンドウで右クリック > Create > Testing > Tests Assembly Folder で作ることができます*2

Edit mode tests用フォルダは、以下いずれかの方法で作ることができます【9/30修正】

  • パスに/Editor/を含むフォルダ(asmdefファイル不要)
  • 任意のフォルダにasmdefを置き、Platformsの"Editor"をonにする*3

なお、UnityEngine.TestRunnerおよびUnityEditor.TestRunnerは、Unity Test Frameworkパッケージに含まれるアセンブリです。名称から、Play mode tests用とEdit mode tests用に分かれているように見えますが未検証です。

Rider Integrationとの相性

Unity 2019.2から、JetBrains Rider Integrationもpackage化され、プロジェクト内にpluginを置く必要がなくなりました*4

しかし、このRider Editor(com.unity.ide.rider)はTest Framework(com.unity.test-framework)に依存しており*5、バージョンの相性がありますので注意しましょう。

確認した範囲では、Rider Editorのバージョンを1.1.1に上げるとき、Test Frameworkも1.1.3以上に上げる必要があるようです。

*1:内部的にも参照方法が変わっているはずですが

*2:この方法、セッションで言ってなかったことにこの記事を書いていて気づきました…

*3:Unity 2019.1まではEdit mode testsでもTest Assembliesをonにする必要がありましたが、2019.2からは不要となりました

*4:普通のプロジェクトなら.gitignoreに書いておけばいいのですが、UPMパッケージに混ぜてpublishされてしまいがちだったので嬉しい

*5:Riderからテスト実行できるので当然といえば当然ですね

Unity++ 〜ショートセッション勉強会 presented by Unity部〜 #unity_pp に行ってきました

7/20(土)に開催された『Unity++ 〜ショートセッション勉強会 presented by Unity部〜』に行ってきました。

meetup.unity3d.jp

主催は日本Androidの会Unity部さん*1、会場はGINZA SIXのユニティ・テクノロジーズ・ジャパンさん。 スライドや動画は後日ユニティ・ジャパンさんのUnity Learning Materialsで配信されると思いますので、ごく簡単に。

Democratized Unity Package Manager

speakerdeck.com

  • Unity 2019.1からUnity Package Manager Scoped Registryが使えるようになった
  • Unity Package Managerは2017.2から導入
  • パッケージには4種類ある
    • 公式/verified
    • 公式/preview
    • 公式/built-in
    • 非公式 ← これを扱いやすくなった! 民主化
  • Package Name: reverse domain記法
  • Version: semver形式、previewもここで表現
  • Unity Version: 最低ver*2
  • Dependencies: 依存パッケージ
  • Registory: npm仕様
  • Scoped registory
    • package nameのスコープごとにRegistryを切り替えられる((uplinksで上位のレジストリを書くことでカスケードにもできるが、Scopedでのほうが様々な構成に対応できる)) -VerdaccioというOSSで簡単に立てられる
  • Package Manager UIには表示できないのでPackages/manifest.json直書きする
    • Removeはできる
  • Packageを作る
    • Assets/直下にpackage.jsonを置く
    • README.mdとかもAssets/直下に置く
    • asmdef必須
    • Documentation~直下に置くとメタファイルがつくられないのでべんり
    • Test Assembryがコンパイルされないバグ
  • 公開する
    • 認証を通す
    • ROOT/.npmrmにレジストリURLなどを書いておくと便利
    • $ npm publish
  • 詳しくはUNIBOOK 11(C96 4日目 南リ45a)で!
  • upm-packages.dev を立てた*3
  • Command line interface for Unity Package Manager を作った

補足

よーし、パパ Cinemachineを2Dプロジェクトに適応して遊んじゃうぞー

speakerdeck.com

  • プレイヤーにカメラを追従させる処理 → 親子にするなどで実現はできる
  • いい感じにしたい → Cinemachine
  • Unity 2017から、Package Managerでインストール可能
  • 遅延移動、プレイヤーの動きを先読み
  • 特定の範囲から外を見せたくない
    • コライダを設定できる
  • 複数カメラの切り替え、ブレンド
  • 複数ターゲットを収める(拡大縮小して収める): Target Group
  • カメラシェイク: Impuls Listener
  • ドキュメント充実してる+テラシュールブログも参考
  • [非公式] Unite Tokyo 2019 Eve2 LT Fes - connpassが8/2募集開始なのでよろしく

アクションゲームにおけるポーズ系演出の難しさと解決法

Preview機能のプレビュー 公式Localizationパッケージの今

Unity開発者が知っておきたい.NETのこと

speakerdeck.com

  • Scripting Backend
    • .NET 4.xが使える
  • Compatibility
    • .NET 4.x: dll大きい。動かないAPIもある
    • .NET Standard 2.0: dll小さい
  • .NET実装: ランタイム+クラスライブラリ
  • .NET Standard: 仕様・規格

Unity サウンドTips 2019

www.slideshare.net

  • 基礎的なことは 【Unite Tokyo 2018】Audio機能の基礎と実装テクニック 参照
  • Unityはサウンドエフェクトがややムズ
  • Audio Mixer とっつきにくいけど優秀
  • VR特有
    • 指向性:位置情報、直接音:パンニング、初期反射、
    • 360度から聞こえる音:ambisonics
  • VRサウンドSDK多すぎ問題:Oculus Audio SDKがほぼ正解
  • 罠: OculusSpatializerUnityコンポーネント
    • 単位がフィート
  • 処理はそれなりに重い。無理に使わなくてもパンニング+距離減衰だけでいいことも
  • CRI ADX2
    • 法人向け有償版、個人開発者向けLE
  • Audio DSP Graph
    • previewですらない。Megacityデモからコード抜いて調べた
    • 2-3年先では

書籍が8/27に発売されます

Unityサウンド エキスパート養成講座

Unityサウンド エキスパート養成講座

UniTask入門

speakerdeck.com

  • コルーチンの置き換え、戻り値を返せる
  • C#のTaskより軽い
  • UniRxよりはわかりやすい
  • C# 7以降
  • 生成
    • asyncの戻り
      • async UniTaskVoid: async voidの代わりに使える
    • UniTaskCompletionSource
    • (UniRxの)Observableから変換する
      • 必ず完了するObservableであること
      • ToObservableするとメインスレッドで動く
  • UniTask.Run, UniTask.Delayとか
  • UniTask.WhenAll: 型が違っても待てる
  • WhenAny: どれかひとつ終わったら抜ける
  • Awaiter
    • GetAwaiter()が生えてればawaitできる。拡張メソッドでもok
    • UniTaskはいろいろ提供している
  • UniTask.ToCoroutineでコルーチンに変換できる
  • SceneManager.LoadSceneAsync()とかを待てる
  • progressも取れる
  • OnCollisionEnterとかも
  • コルーチンの上位互換として使える
  • UniTask Tracker
  • UniTaskとキャンセル
    • CancellationToken
      • GetCancellationOnDestroy() べんり
    • OperationCanceledException: 投げるとUniTaskは「キャンセル状態」になる
      • エラーログには出ない
      • 外部からキャンセル要求があったとき
      • 下流で投げたら上までスルーして伝えること
      • 悪用しないこと
  • 標準Taskは必要がなければ使わないでok
  • Observable: イベント処理、結果が複数になるなら使う

カシスちゃんのグッズ発売中

所感

Unityはできることが多く、普段触らない分野の知識はなかなか入ってこないので、Gotanda.unityRoppongi.unityのようなLT、また今回のようなショートセッション形式で色々聞ける勉強会というのはとてもありがたいです。

似たようなインプットとしては、Unity Pro Tipsのメールマガジンもいいですね。ちょうど先日Cinemachineの記事を読んで興味を持っていたところでした。

いつもながら、企画・運営、そして登壇者のみなさんには感謝。

*1:当時、雨後の筍のようにたくさんあった「部」の数少ない生き残り。テスト部とか酒部とかVR部とかありました

*2:休憩のとき聞きましたが、rangeでは指定できないそうです

*3:ちょうど個人的に、ローカルにVerdaccio立ててもUnity Cloud Buildから使えないしなーと考えていたところだったので、使わせてもらおうかと

GitKraken v6.0リリースとIndividual料金プランの新設

マスコットキャラクターがたいへんかわいいと評判のGitクライアント"GitKraken"のバージョン6.0がリリースされました!

youtu.be

とりあえず触ってみたい! という方は、ぜひ下のリンクからサインアップして試してみてください。

www.gitkraken.com

主な変更点

爆速

起動やリポジトリを開くスピードがとても早くなりました。

起動時のたいへんかわいいアニメーションはいつまで見ていても飽きないのですが、それでも素早く作業に取り掛かれるほうが良いですね。

タブ

画面上部にタブが付き、複数のリポジトリを開いた状態で保持できるようになりました。

従来通りプルダウンでの切り替え操作もできますが、タブのほうが便利。

マージコンフリクト警告

PRをつくるときにマージ先とのコンフリクトを検出したら警告してくれるようになりました。

Individualプランの新設

これまで、Freeプランと$49/yのProプランの二択でしたが、$29/yのIndividualプランが新設されました!

Individualプランでは、従来Proでのみ可能だった以下の機能を使えます。

なお、複数プロファイル切り替え、GitHub Enterpriseの利用などは、これまで通りProプランが必要です。

免責事項

私はGitKraken Ambassadorであり、GitKraken開発元のAxosoft社の従業員ではありません。

I am a GitKraken Ambassador, not a paid employee of GitKraken by Axosoft.

GitKraken Ambassadorになりました

マスコットキャラクターがたいへんかわいいと評判のGitクライアント"GitKraken"のアンバサダーになりました!

今後、当ブログでGitKrakenの(かわいいだけじゃない)機能紹介などを行なっていくとともに、近い内に都内でmeetupなどを開催できればと画策しています。

f:id:nowsprinting:20190426005455p:plain

※以下、当初の原稿が「たいへんかわいい」で埋め尽くされてしまっていたため、大幅にリライトしたものでお送りします。

GitKrakenとは

GitKrakenは、Axosoft社が開発・提供しているGitクライアントです。オープンソースプロジェクトでの利用など、商用でなければ基本機能は無料で使用できます。 またGitクライアントだけでなく、Glo Boardsというカンバン機能も備えています。

とりあえず触ってみたい、という方は、ぜひ下のリンクからサインアップして試してみてください。

www.gitkraken.com

Nintendo Switchがもらえたりもらえなかったりするようです。なにより、meetupを開催するときに送ってもらえるノベルティが豪華になりますので、ぜひこのリンクをご利用ください。

GitKraken Pro

GitKraken Freeでも、その美しいGUIは使用できますし、そもそも他に無料のGitクライアントはいくつもあります。しかし、個人的にGitKrakenをおすすめする最大の*1ポイントは、$4.08/moのProプラン以上で使用できる"Merge conflict editor"です。

Merge conflict editorについては、次の動画の1分20秒あたりから見ると*2その便利さがわかっていただけるのではないでしょうか。

youtu.be

またProでは、個人のGitHub.comのアカウントと、会社で使っているGitHub Enterpriseアカウント、もしくはGitLabやBitbucketなどのアカウントを切り替えて使いたい方のための"Multiple profiles"機能も使うことができます。

なお、GitHubにおける複数アカウント利用は利用規約違反では、という話(全社的に会社用GitHubアカウントを廃止した件 - ZOZO Technologies TECH BLOG)ですのでご注意ください。

GitKraken Proは有料プランですが、7日間のトライアルがあります。ぜひ一度お試しください。

Glo Boards

いわゆるカンバンです。GitHub Projectsなどより高機能で、カレンダー・ビューなどもあります。 こちらも、オープンソースプロジェクトでの利用など、商用開発でなければ基本機能は無料で使用できます。

下はバージョン5における新機能紹介動画ですが、Glo Boardsがどのようなものかわかりやすいはず。

youtu.be

こんな方におすすめ

初心者から上級者まで! と言いたいところなのですが、初心者しかも日本人には英語の壁があるのも確かです。 しかし、先々、複雑な操作をするようになる頃にはCLIに行き着きますし、GUIは慣れるものです。 どうせ使うならキレイなGUIを使いたいという方、ぜひGitKrakenを使ってみてください。

GitおよびGitHub自体に慣れていないという方には、まずはこちらの書籍をおすすめします。

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

また、マージ、リベース、それに伴うコンフリクトの解消がとても強力なクライアントですので、多数のブランチが並列していたり、個々のブランチの寿命が長かったりというつらみの深いプロジェクトに携わっている方は、ぜひぜひGitKraken Proのフリートライアルを試していただきたいです。

まあそもそも、そんなプロジェクト(以下略

免責事項

私はGitKraken Ambassadorであり、GitKraken開発元のAxosoft社の従業員ではありません。

I am a GitKraken Ambassador, not a paid employee of GitKraken by Axosoft.

*1:これは「たいへんかわいい」を差し置いて、最大です。次点で「アイコンがたいへんかわいい」「スプラッシュ画面のアニメーションがたいへんかわいい」などと続きます

*2:埋め込みだと再生開始指定が効かないみたいなので

定職につきました

いわゆる転職エントリです。 長らくフリーランス開発者としてやってきましたが、4月から株式会社ディー・エヌ・エー(以下DeNA)のSWETグループ所属となりました。

副業可・裁量労働でもありますので、自分の会社も副業として細々と存続します。その副業の関係でここ2ヶ月はアルバイト扱いで仕事していたのですが、とても仕事しやすい環境です。

フリーランスから会社員という変化、開発者からテスト系というロールの変化を同時に決めたわけで、そのあたり少し書き残しておきます。

DeNA

お誘いを受けたときの最初の印象は「『電エース*1』みたいな名前の会社だ」というくらいで*2、正直なところ会社員というものが選択肢として考えられていなかった状態でした。

が、なにせ過去に会社員だった記憶は20年前のメーカー系だったわけで、時間をもらって考えるに並の案件よりよほど自由もあるし*3DeNAであれば色々な領域の技術を扱えるのでは、というあたりに惹かれた感じです。

とは言え、ろくに転職活動などしてこなかったので広く他社と比較したりということもせず(できず)、ネガティブな要因に背中を押されたところもあります*4

SWET

GoogleなどでいうSET (Software Engineer in Test)、MicrosoftでいうSDET (Software Development Engineer In Test)にあたり、狭義には開発チームのテスト自動化を支援したり、CI/CDなどのインフラを整えたり、というロールです。

自分のコミュニティ活動、著書もまさにこのあたりの領域なので、チョットデキルと言えるところ。

しかし、先日のJaSST'19 TokyoでのYahoo! JAPAN山口さんの話のように、開発チームが自力でテストを書けるようになれば不要になるはずのロールであり、現にGoogleではインフラ色の濃いSETI (Software Engineer, Tools & Infrastructure)に名称も変わり、MicrosoftのSDETはなくなっているそうです。

ソースはこのあたり。

この点は最初の面談でまず聞いたところでなのですが、DeNAでは狭義のSETのロールだけでなく、形式手法や機械学習との連携などR&D的な活動も進めているという話であったり*5、AI for Testingとかゲームとかのテスト技術を個人で追うことに限界を感じていたところもあったので、もう片手間でなくこちらに舵を切ってしまおうか、と決断したのです。

フリーランスについて

フリーランスという働き方については、勧めもしないし止めもしないです。20年前と今とは違うし、どちらが良いとも悪いとも言えないです。DeNAの居心地は今のところとても良い*6ですが、まだ2ヶ月なのでいつ手のひらを返すかわかりませんし。

個人的には、本業で開発、コミュニティ活動でテスト自動化と活動を分けた挙げ句、本業側でろくなポートフォリオを残せていないというバカなことをやってきたわけで、後進には反面教師以外の何も残せないのは申し訳ないです。

最後に参考までに、会社が副業可であっても年金事務所の手続きとかめんどくさくて、日本社会がまだまだなんだなという感想。なにせ絶賛手続き途中なので落ち着いたらエントリ書くかも知れません。 あと雇用保険が7年で失効するとか。

参考資料

テストから見えてくる グーグルのソフトウェア開発

テストから見えてくる グーグルのソフトウェア開発

実践アジャイルテスト テスターとアジャイルチームのための実践ガイド (IT Architects' Archiveソフトウェア開発の実践)

実践アジャイルテスト テスターとアジャイルチームのための実践ガイド (IT Architects' Archiveソフトウェア開発の実践)

電エースBOX 河崎実監督作品 [DVD]

電エースBOX 河崎実監督作品 [DVD]

電エースQuiz - 河崎実監督と特撮映画の世界

電エースQuiz - 河崎実監督と特撮映画の世界

  • HUB Systems, Inc.
  • エンターテインメント
  • ¥600

*1:平成元年、バンダイのビデオマガジン『電影帝国』内の1コーナーとしてはじまった特撮作品のシリーズで、30年続いている河崎実監督のライフワーク。気持ちが良くなると変身するヒーロー、電エースの活躍が描かれている。近年はクラウドファンディングで出資者を出演させるという商法が展開されている

*2:実は数年前DeNAセミナールームで登壇したときネタに使ったのですが、盛大に滑りました

*3:フリーだとなかなか案件から抜けられないこともあり、逆にDeNAでは社内での異動がしやすい制度が整っていたりします

*4:最近フリーランスが流行りっぽいけど余り良い案件流れてないとか、35歳定年説については諸説ありますが個人的には内部品質の低いコードの読み書きはつらくなってきたとか、営業めんどくさくなってきたとか

*5:日付は前後しますが https://speakerdeck.com/orgachem/story-of-a-swet-engineer

*6:ぬるいわけではないです。みんな頭良くてついていくだけでも大変

Unity 2018のUnity Test Runner

ようやく重い腰を上げて手元のUnity 2017.4プロジェクトを2018.3に移行したので*1何番煎じかわからないけどテスト(Unit tests)まわりについてまとめ。

Test Runnerウィンドウ

2017ではメニューのWindow直下にあった"Test Runner"ですが、Window > General > Test Runnerに移動されました。

Edit mode Tests

2017.4までは、EditModeで実行するテストコードはAssets/**/Editor/**/下にあればよかったのですが、2018では条件が増えています。

例えばAssets/Xxx/Editor/のようなフォルダ階層でXxx下にAssembly Definition(以下asmdef)ファイルを置いてしまうと、Editorまで同じアセンブリに含まれてしまいます。

Xxx/Editor下にEdit mode Testsがある場合はXxx/Editor直下にもうひとつadmdefファイルを作り*2、"Test Assemblies"と"Editor"の2つのチェックボックスをonにする必要があります。

f:id:nowsprinting:20190402003537p:plain

なお、Edit modeでは[UnityTest]属性をつけたテストはEditorApplication.updateコールバックループで実行されるという点は2017も2018も同様です。

Play mode Tests

2017ではPlay modeでテストを実行するには”Enable playmode tests”をクリックしてから再起動する手順が必要でしたが、2018では不要になっています。

代わりに、テストコードは任意のフォルダ下に置き、そこにadmdefファイルを作り、"Test Assemblies"チェックボックスをonにする必要があります。

f:id:nowsprinting:20190402003606p:plain

なお、Play modeでは[UnityTest]属性をつけたテストはコルーチンで実行されるという点は2017も2018も同様です。

Enable playmode tests for all assemblies

もし、Play modeのテストコードを容易に移動できない、asmdefによってアセンブリを分けることが困難といった場合、Test Runnerウィンドウ右上のハンバーガーメニューから"Enable playmode tests for all assemblies"をクリックして有効にすることで、Unity 2017のようにモードを切り替えてPlay mode Testsを実行することができるようです(未確認)。

f:id:nowsprinting:20190402003321p:plain

ただし、このままではビルドに追加のアセンブリが含まれるため、プロジェクトのサイズとビルド時間が長くなってしまいますので、ビルドを行なうときにはDisableに戻すべきです。

アセンブリの依存関係

Assembly Definitionファイル(以下asmdef)はUnity 2017.3から導入された機能で、アセンブリを小分けすることでプロジェクトのビルド時間を節約する効果があります。

Unity 2018からはテストコードは専用のアセンブリ("Test Assemblies"チェックボックスをonにしたもの)に属する必要が生じたため、テストコードのasmdefからSUT(system under test: テスト対象)ほか使用しているasmdefを参照する旨を"Assembly Definition References"に設定する必要があります。

下図はSUTである"SUTClient"と、"UniRx"に依存している例です。

f:id:nowsprinting:20190402021134p:plain

Internalの扱い

C#では、Internalアクセス修飾子をつけたclass/methodは同一アセンブリ内からのみ参照できます。Unity 2018でテストコードが別アセンブリになったことによって、そのままではInternalなclass/methodのテストを書くことができません*3

これに対し、参照される側(SUT)の中に以下のコードを書くことで、指定したアセンブリに対してInternalなclass/methodを公開することができます。

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]
[assembly: InternalsVisibleTo("SampleTestsAssembly")]

""の中には、公開するアセンブリ(この文脈上はテストコードのアセンブリ)名を書きます。"Assembly-CSharp-Editor"はUnityエディタです。

なお、このコードはアセンブリ内のどのファイルに書いても良いようなのですが、過去の経緯から"AssemblyInfo.cs"というファイルに書くことが多い? ようです。

おまけのTips

*1:2017.4から2018.3に上げたので、差分は2018.1か2か3のどこで入ったものかまでは確認していません

*2:右クリック > Create > Assembly Definition

*3:Unity 2017以前でも、Edit modeのテストコードはAssembly-CSharp-Editorというアセンブリに入るため、Internalなclass/methodのテストはそのままテストできませんでした