การพัฒนา Unit Testing โดย xUnit test library (.NET Core)

บทความนี้นำเสนอขั้นตอนการพัฒนา Unit Test อย่างง่ายโดยแสดงให่้เห็นการพัฒนาทีละขั้นตอน สำหรับระบบที่พัฒนาบน .NET Core โดยใช้ xUnit เพื่อทำความเข้าใจการพัฒนาแบบ test-driven development (TDD) ซึ่งในขั้นแรก เริ่มต้นด้วยการสร้าง source project ที่จะใช้สำหรับการทดสอบ สร้าง folder “TestSample” และ sub folder ชื่อ “CalcTool”  จากนั้นเปิด command prompt เข้าไปที่ folder “CalcTool” เพื่อทำการสร้าง .NET Core project โดยใช้คำสั่ง

dotnet new classlib

rename class1.cs เป็นชื่อ calc.cs และเขียน code ดังนี้

using System;

namespace CalcTool
{
    public class Calc
    {
        public int AbsAddByOne(int value)
        {
            throw new NotImplementedException("Not implemented");
        }
    }
}

สร้าง test project โดยกลับไปที่ folder “TestSample” และสร้าง sub folder ชื่อ “CalcTool.Tests” จากนั้นเปิด command prompt เข้าไปที่ folder “CalcTool.Tests” เพื่อทำการสร้าง .NET Core project โดยใช้คำสั่ง

dotnet new xunit

โดยคำสั่งนี้จะทำการสร้าง test project ที่ใช้ xunit test library และกำหนดค่า test runner ไว้ใน CalcTool.Tests.csproj

file : CalcTool.Tests.csproj

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0"/>
    <PackageReference Include="xunit" Version="2.2.0"/>
    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0"/>
</ItemGroup>

</Project>

เพิ่ม reference ไปยัง project ที่ต้องการทดสอบซึ่งในที่นี้คือ CalcTool project โดยใช้คำสั่ง

dotnet add reference ../CalcTool/CalcTool.csproj

ก่อนที่จะ build CalcTool project หรือ CalcTool.Tests project ต้อง execute คำสั่ง dotnet restore เพื่อ restore NuGet package ที่จำเป็นต้องใช้ในแต่ละ project

เริ่มพัฒนา unit testing โดยลบ file “UnitTest1.cs” และสร้าง file ใหม่โดยใช้ชื่อว่า “CalcTest.cs” และเขียน code ดังนี้

using System;
using Xunit;
using CalcTool;

namespace CalcTool.Tests
{
    public class CalcTest
    {
        [Fact]
        public void AbsAddByOneTest()
        {
            var c = new Calc();
            var result = c.AbsAddByOne(5);

            Assert.Equal(result, 6);
        }
    }
}

*[Fact] attribute ใช้กำหนดว่า method นั้นๆเป็นแบบ single test

ทำการทดสอบโดยการ execute dotnet test ซึ่งจะทำการ build และ start xUnit test runner ซึ่งพบว่าผลการทดสอบ fail เนื่องมาจากยังไม่ได้ implement code ใน method “AbsAddByOne” ของ class “Calc” ดังนั้นกลับไปที่ method “AbsAddByOne” เพิ่ม code ลงไปเพื่อให้ผลการทดสอบถูกต้อง/ผ่าน (test pass)

        public int AbsAddByOne(int value)
        {
            return Math.Abs(value) + 1;
            //throw new NotImplementedException("Not implement");
        }

กลับไปที่ folder “CalcTool.Tests” และ execute dotnet test ซึ่งจะทำการ build และ start xUnit test runner ซึ่งพบว่า ผ่านการทดสอบ (test pass)

ใน xUnit ยังมี attribute ที่ใช้กำหนด suite of tests ซึ่ง execute code เดียวกันแต่มี input ที่มีค่าแตกต่างกันนั่นคือ [Theory] attribute และใช้ [InlineData] attribute ในการกำหนดค่าของ input

        [Theory]
        [InlineData(5)]
        [InlineData(-5)]
        public void AbsAddByOneTest2(int value)
        {
            var c = new Calc();
            var result = c.AbsAddByOne(value);

            Assert.Equal(result, 6);
        }

การพัฒนาในรูปแบบ test-driven development (TDD) จะทำเป็นรอบๆในลักษณะนี้โดย เพิ่ม unit testing , เพิ่ม code ใหม่เข้าไป ทดสอบ unit test จนผ่านและเริ่มรอบใหม่ จนกระทั่งได้ test ชุดสุดท้ายและโปรแกรม/library ที่สมบูรณ์ ก็เป็นอันจบการพัฒนาในรูปแบบ test-driven development (TDD)