1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【unity】Test Runnerを使ってみる

Last updated at Posted at 2021-06-02

初書 : 2021/06/01
mac : 11.4
unity : 2020.3.10f1
vscode : 1.56.2

前置き

今回はunityでもテストコードを書いておきたい!ということで調べていたらTest Runnerなるものが存在しているらしいので、それを使ってみる。

Test Runnerとは

Unity Test Runner は、Edit (編集) モードと Play (再生) モードでコードをテストするツールです。また、スタンドアロン、Android、iOS などのターゲットプラットフォーム上でも同様にテストできます。

Unity Test Runner - Unity マニュアルより

つまり、Unityに標準でついているテストツール。なるほど、使うしかない。

起動 (?)

果たして起動と表現するものなのか。
とりあえずウィンドウを表示してみる。

ウィンドウ(window)一般(general)Test Runnerから開くと、上にPlayMode | EditModeと書かれたウィンドウが開く。

テストは主にこの画面から行うらしい。

テストコードを書く準備をする

テストコードは単純に.csを置くだけではできないので、準備をする必要がある。

ディレクトリはどこでもいいのだが、PlayModeEditModeのテストコードと、実際にunityで使うメインのコードはそれぞれ別のディレクトリに入れる必要があるため、ここは簡単に両方のフォルダを作ってしまう。

まず、Assets直下にTests\Editorディレクトリを作成する。

その後、右クリックから作成(create)TestingTests Assembly Folderを選択し、EditModeTestsPlayModeTestsの2つのディレクトリをそれぞれ作成する。

2つ作成できたら、EditModeTestsの中に入り、EditModeTests.asmdef1を開く(インスペクターに表示)

その後、プラットフォームの箇所をEditorにのみチェックが入っている状態にする。(任意のプラットフォームのチェックを外し、全ての選択を解除し、Editorにチェック)

これにより、EditModeTests下に入れたテストスクリプトは、EditModeで動作し、PlayModeTests下に入れたスクリプトはPlayModeで動作する。

PlayMode, EditModeとは

そういえば説明をしていなかった。詳しくどこかに書いているのかは知らないが、

PlayMode : テストコードに沿ってゲームを再生し、テストを行う
EditMode : ゲームの再生を行うことなく、テストコードを実行する

大体2つの違いはこんな感じ。つまり、関数の動作を確認したい時などはEditModeを使い、わざわざゲームを実行することなくスクリプトをテストできる。
逆に(3D)オブジェクトの動作を確認したい時などはPlayModeを使い、ゲームを実行しながらテストを行う感じ。

ちなみにこれ記述時点ではEditModeしか使っていないため、PlayModeの詳しいお話は後日追記する予定。

(EditMode)テストコードを書く…前準備(2回目)

テストコードを書く前に、テスト対象となるコードがなければ話にならないので、まずはそちらを作成する。

Assets/Scripts/TestedCode.csを作成し、適当にコードを記述する。

TestedCode.cs
using UnityEngine;

public class TestedCode{
    /// <summary>
    /// 料金に税金を上乗せします。
    /// </summary>
    /// <param name="Fee">料金</param>
    /// <param name="isFood">食料品かどうか</param>
    /// <returns>税金が入った金額</returns>
    public static int AddTax(int Fee, bool isFood){
        if(isFood){
            return MultiplyAndRoundup(Fee, 1.08f);
        }else{
            return MultiplyAndRoundup(Fee, 1.1f);
        }
    }

    /// <summary>
    /// 2数を掛け算し、小数点以下を切り上げ整数にします。
    /// </summary>
    /// <param name="number">数値</param>
    /// <param name="magnification">倍率</param>
    /// <returns>切り上げた値</returns>
    private static int MultiplyAndRoundup(int number, float magnification){
        return Mathf.CeilToInt(number * magnification);
    }
}

適当なわりに若干複雑なことしているのは後で使うからです。(そしてこれくらいのコードしか思いつかなかった)

次にテストコードを書きたいのだが、実はこのままだと記述できない。

Assembly Definition

unityにはもう一つ大切なものとして、Assembly Definitionというのがある。これの詳しい説明は他の方に任せるとして、必要な部分だけ説明する。

Unity Assembly Definition 完全に理解した - Qiita

簡単にいうと、複数の.csをまとめて一つのアセンブリにする。そのアセンブリを複数に分割するのがAssembly Definition。

で、複数に分割するキーになるものとして、先程のEditModeTests.asmdefPlayModeTests.asmdefが該当する。

このファイルを含んだディレクトリとその下の階層は全て一括りにされて、一つのアセンブリとなる。

・・・説明が下手なので今の階層構造を持ってくると、

├── Scripts
│   ├── TestedCode.cs
└── Tests
    └── Editor
        ├── EditModeTests
        │   └── EditModeTests.asmdef
        └── PlayModeTests
            └── PlayModeTests.asmdef

EditModeTests.asmdefがあるEditModeTestsディレクトリと、その下(今はない)がEditModeTests.dllというアセンブリにまとめられ、
PlayModeTests.asmdefがあるPlayModeTestsディレクトリと、その下(今はない)がPlayModeTests.dllというアセンブリにまとめられる。

そしてどちらにも入っていないScriptsとその下やTests\Editorのところは、その他としてAssembly-CSharpというアセンブリにまとめられる。

で、アセンブリ同士では基本的に変数やクラスのやりとりが出来ず、アクセスを求める際は手動で接続する必要がある。

ただし、Assembly-CSharpというのは特別で、他のどのアセンブリからも参照することは出来ない。(手動でもできない)

つまり、今からテストするAssets/Scripts/TestedCode.csAssembly-CSharpにあるため、EditModeTestsアセンブリからアクセスすることが出来ないのである。

(説明難しいな・・・伝わるのかな・・・)

ということでアクセスする方法としては、TestedCode.csを含むスクリプトをアセンブリ化するしかないので、それを作成する。

ここまでの説明で理解できて、応用する場合は好きな形でアセンブリを置いてもらえればいいのだが、今回はとりあえずAssets直下に置くことにする。

右クリック→作成アセンブリ定義で、今回はMainScriptと命名する。

その後、手動で接続するために、EditModeTests.asmdefを開き、アセンブリ定義参照のところに先程のMainScriptを追加する。

これでようやくテストコードを記述することができる。

テストコードを書く

EditModeTestsディレクトリにいき、右クリック→作成TestingC# Test ScriptTestCodeを作成

TestCode.cs
using NUnit.Framework;

public class TestCode{
    [Test]
    public void TestCodeAddTax(){
        int fee = TestedCode.AddTax(1000,false);
        Assert.AreEqual(1100, fee);
    }
}

[Test]と書かれた関数がテスト対象で、正誤判定はAssert.AreEqualで行っている。
左側に期待値、右側に実測値を入れ、不正解だとエラーが起きる。

これで保存し、Test Runnerの画面を開く。

EditModeを選択したら、Run Allを選択。

これでテストが行われ、テストが通ればチェックマーク、通らなければ下にエラーが表示される。

これで無事テストが終了した。

private関数のテストコードを書く

TestedCode.csにはもう一つMultiplyAndRoundupという関数がある。せっかくなのでこちらもテストをしておく。

先ほどと同様にテストをやれればいいのだが、こちらの関数はprivate関数になっていて、そのままではテストできない。

ということで今回はMethodInfo.Invokeというのを使用して、private関数をテストしてみる。

TestCode.cs
using System.Reflection; // これだけ先頭に追加。他はTestCodeクラス内

    [Test]
    public void TestCodeMultiplyAndRoundup(){
        System.Type myClass = typeof(TestedCode);
        Assert.NotNull(myClass);
        MethodInfo myMethod = myClass.GetMethod("MultiplyAndRoundup", BindingFlags.NonPublic | BindingFlags.Static);
        Assert.NotNull(myMethod);
        var value = (int) myMethod.Invoke(this, new object[]{1000,1.1f});
        Assert.AreEqual(1100, value);
    }

簡単に解説すると、myClassに型情報を入れ、GetMethod関数を使ってNonPublicStaticMultiplyAndRoundupを取り出し、
Invokeを使って引数に1000,1.1fを入れて呼び出し、valueに戻り値を入れている。
戻り値はそのまま取得するとオブジェクト型になってしまうので、int型にキャスとしている。

このような形で取得することができる。

あとは先ほどと同様テストするだけ。

終わりに

PlayModeのテストは後日使ったら追記する。
まだ使いたてなのでもしかしたら間違えているところや、より最適な方法があるかもしれないが、もしそういうのがあればコメントで教えてください。

参考サイト:

Unityでテストを書くのが当然になる時代に今から備えよう - Qiita

Unity のUnitTestでprivate な関数をテストしたい場合 | おなかソフト

その他役立ちそうなサイト:

【Unity】Unity Test Runner(Test Framework)の使い方を総まとめ - インストールから自動化まで - LIGHT11

[C#]private、internalなメソッドのUnitTest - Qiita

  1. 名前が同じでややこしいので拡張子を記述したが、UnityEditorでは拡張機能を入れない限り拡張子は見えない。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?