12
8

More than 1 year has passed since last update.

xUnitテストとNUnitテストを比較してみた備忘録

Posted at

はじめに

先月から部署が少々異動になりました。そこで、これまではxUnitテストを使用していたのですが、異動後の部署はNUnitテストを使用しているとのことだったので、違いやら書き方やらがちょっと気になり調べてみました。その備忘録。社内のすーぱーすごい先輩の勉強会の内容もメモ。

環境

  • Windows10
  • Visual Studio 2019 Professional
  • ASP.Net Core

これをおさえとけばなんとか書けそうな2つのテストの違い

xUnit NUnit 補足
コンストラクタに記載 SetUp 最初に実行したい処理をかく。DIとか
Fact Test 1つのテストの塊
InlineData TestCase たくさんテストケース試したいとき用
MemberData TestCaseSource 入力値が複雑なときに使う印象
IDisposable.Dispose Teardown 最後に実行したい処理をかく。 

ドキュメントとしてはこちら(Comparing xUnit.net to other frameworks)にキレイに一覧化されていました。
これをみればバッチリ!

テストする内容

数字を文字列で返すというとても単純なコードを書いたので、こちらをテストします。

using System;

namespace UnitTestDemo
{
    public class UnitTest
    {
        public string NumTest(int i)
        {
            return i.ToString();
        }
    }
}

xUnitテストで試す

以前(C#でxUnitテスト備忘録)実践してるので、細かい部分ははしょります。

プロジェクトの作成

ファイル → 追加 → 新しいプロジェクトからxUnitテストプロジェクトを選択
image.png

テストコードをかく

プロジェクト参照を追加します。テストしたいプロジェクトを選択します。
image.png

using System;
using UnitTestDemo;
using Xunit;

namespace XUnitTestDemo
{
    public class xUnitTestTest
    {
        private UnitTest _unitTest;

        public xUnitTestTest()
        {
            _unitTest = new UnitTest();
        }

        [Theory]
        [InlineData(1, "1")]
        public void Test1(int num, string strAns)
        {
            var result = _unitTest.NumTest(num);
            Assert.Equal(strAns, result);
        }
    }
}

NUnitテストで試す

テストプロジェクトの追加

ファイル → 追加 → 新しいプロジェクトからNUnitテストプロジェクトを選択
(この辺はxUnitテストと同じ)
image.png

NuGetパッケージマネージャーから以下2つをインストールすることで、クラスライブラリをテストプロジェクトにすることもできました。

  • NUnit
  • NUnit3TestAdapter

ちなみにNUnit3TestAdapterは、VisualStudio等のテスト実行時に使用されるものみたいです。

image.png

テストコードをかく

プロジェクト参照を追加します。テストしたいプロジェクトを選択します。(xUnitと同じ)
image.png

using NUnit.Framework;
using UnitTestDemo;

namespace NUnitTestDemo
{
    [TestFixture]
    public class Tests
    {
        private UnitTest _unitTest;

        [SetUp]
        public void Setup()
        {
            _unitTest = new UnitTest();
        }

        [TestCase(1, "1")]
        public void Test1(int num, string strAns)
        {
            var result = _unitTest.NumTest(num);
            Assert.That(strAns, Is.EqualTo(result));
        }
    }
}

①TestFixture → テストメソッドを含むClassをマークするのに使用
②SetUp → テストメソッド実行前に呼ばれるメソッドをマーク
③TestCase → 同一のテストメソッドで値違いなどケースが違う場合に使用
④Assert.That → NUnitテストでのアサーション。Is.EqualToすることで同値テストができる

以前xUnitで試したことをNUnitでかいてみる

こちら(C#でxUnitテスト備忘録)の記事でかいてみたことをNUnitに変えてみました。

インメモリDBを使うときのNUnit

データベース側の設定を書いたクラス。xUnitのときと変わりなし。

MyDbContextFixture
using System;
using Microsoft.EntityFrameworkCore;

namespace Tests
{
    public class MyDbContextFixture : IDisposable
    {
        public DbContextOptions<MyDBContextName> Options;
        public MyDBContextName Context;

        public MyDbContextFixture ()
        {
            Options = new DbContextOptionsBuilder<MyDBContextName>()
                .UseInMemoryDatabase(databaseName: "MyDatabaseName")
                .Options;
            Context = new MyDBContextName(Options);
        }
        public void Dispose()
        {
            Context.Dispose();
        }


    }

テストコード。NUnitではIClassFixtureが[OneTimeSetUp]に、Disposeが[TearDown]に変わることをおさえておけば大丈夫そう。

NUnitTest
using Microsoft.EntityFrameworkCore;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
// テストしたいプロジェクトを参照するのを忘れずに

namespace Tests.Functions
{
        [TestFixture]
        public class NUnitTest
        {
            private MyDbContextFixture _fixture;
            private MyDBContextName _context;

        [OneTimeSetUp]
        public void OneTimeSetup()
        {
            _fixture = new MyDbContextFixture();
        }

        [SetUp]
        public void SetUp()
        {
            _context = _fixture.Context;
        }

        // ご自身で引数のテストデータ作成します

        // DBに登録したいテストデータをいれます
        // GetTestData()

        /// <summary>
        /// テストデータを削除
        /// </summary>
        [TearDown]
        public void TearDown()
        {
            var list = _context.PrPrint.ToList<PrPrint>();
            _context.PrPrint.RemoveRange(list);
            _context.SaveChanges();
        }


        /// <summary>
        /// ステータスコードが60から70に更新
        /// </summary>
        [TestCaseSource(nameof(MyTestDataName))]
        public void UpdateTest(inputModel)
        {
            var function = new TestFunction<MyDBContextName>(_context);
            // テストデータをInsert
            var list = GetTestData();
            _context.TestTable.AddRange(GetTestData());
            _context.SaveChanges();

            // テストしたい内容
            var result = function.Update_Test(inputModel);
            var entity = _context.TestTable.Where(x => x.Id == result.Id).SingleOrDefault();
            // DBのステータスコードが70
            Assert.That("70", Is.EqualTo(entity.StatusCd));
        }
    }
}

例外のときのNUnit

こちらはAssertionsの書き方とかが変わったくらいの変化。
(非同期のファンクションで試してます。)

        /// <summary>
        /// ステータスコードが69
        /// </summary>
        [TestCaseSource(nameof(MyTestDataName))]
        public void UpdateError(TestModel inputModel)
        {
            var function = new TestFunction<MyDBContextName>(_context);
            // テストデータをInsert
            var list = GetTestData();
            _context.PrPrint.AddRange(GetTestData());
            _context.SaveChanges();
            var ex = Assert.Throws<ApplicationException>(async() =>
                await function.Update_Test(inputModel));
            Assert.IsInstanceOf<ApplicationException>(ex);
            Assert.That("状態69であるデータの更新はできません", Is.EqualTo(ex.Message));
        }

まとめ

ちょっとした書き方が違うだけなので、テストを書く上でそこまで困ることはなさそう!

参考

12
8
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
12
8