انجام Unit Testing در سی شارپ و .Net Core با MSTest

پرووید

دسته های مقالات

در این آموزش از وبسایت پرووید در رابطه با انجام unit testing در .NET Core و با استفاده از MSTest صحبت خواهیم کرد. اگر مایل هستید که همین آموزش را با استفاده از فریم ورک xUnit و فریم ورک nUnit بخوانید باید بگوییم که پیش از این بر روی سایت پرووید منتشر شده اند. ضمناً می توانید فایل های پروژه ی این آموزش را نیز دانلود کنید.

ساختن پروژه

کار را با dot net CLI آغاز می کنیم. لطفاً، یک فولدر با نام unit-testing-using-mstest برای قرار دادن solution در آن ایجاد کنید. در این فولدر دستور dotnet new sln را اجرا کنید تا یک فایل solution جدید ایجاد شود. این فایل solution در ادامه حاوی یک class library و یک test project خواهد بود. پس از آن یک فولدر با نام PrimeService ایجاد کنید. در حال حاضر ساختار فایل ها و فولدرهایی که تا اینجا ایجاد کرده اید را مشاهده می کنید.

solution-structure

فولدر PrimeService را به عنوان current directory تنظیم کرده و دستور dotnet new classlib را اجرا کنید. این دستور باعث ساخته شدن یک class library جدید می شود. فایل Class1.cs را به PrimeService.cs تغییر نام دهید. خب، اگر با مفاهیم test-driven development آشنا باشید، می دانید که در ابتدا باید test ای را بنویسیم که fail شود، پس از آن با پیاده سازی logic مورد نظر کاری کنیم که آن تست pass شود و بعد از نیز refactoring هایی را بر روی logic پیاده سازی شده انجام دهیم. برای اطلاعات بیشتر در مورد ریفکتورینگ توصیه می کنیم که از آموزش ریفکتورینگ Refactoring در سی شارپ استفاده کنید. ضمناً، برای اطلاعات بیشتر در مورد unit testing و test-driven development می توانید از آموزش تست واحد Unit Testing در سی شارپ و همچنین آموزش توسعه تست محور Test First Development در سی شارپ سری اول و آموزش توسعه تست محور Test First Development در سی شارپ سری دوم استفاده کنید.

خب، کدی که در قسمت زیر مشاهده می کنید محتویات کلاس PrimeService را نشان می دهد.

 
using System;

namespace Prime.Services
{
    public class PrimeService
    {
        public bool IsPrime(int candidate) 
        {
            throw new NotImplementedException("Please create a test first");
        } 
    }
}

همانطور که مشاهده می کنید برای متد IsPrime که یک پارامتر ورودی از نوع int دریافت کرده است هیچ logic ای در نظر گرفته نشده است. این موضوع بدون شک باعث fail شدن اولین test ما خواهد شد. اما نگران نباشید. با استفاده از همان سیکل سه مرحله ای که در قسمت بالا نیز به آن اشاره کردیم و تحت عنوان Red-Green-Refactor نیز شناخته می شود، پیاده سازی مناسبی را برای بدنه ی این متد در نظر خواهیم گرفت.

با استفاده از CLI به فولدر unit-testing-using-mstest بروید و دستور dotnet sln add PrimeService/PrimeService.csproj را اجرا کنید.

این دستور باعث می شود که پروژه ی class library ای که ایجاد کردیم به solution اضافه شود.

ساخت پروژه ی unit test

در ابتدا یک فولدر با نام PrimeService.Tests ایجاد کنیم. در حال حاضر ساختار پروژه و فایل های آن شبیه به ساختار زیر می باشد.

solution-structure

این فولدر ساخته شده را به عنوان current directory تنظیم کنید و با استفاده از دستور dotnet new mstest یک پروژه ی تست جدید بسازید. این دستور باعث ساخته شدن یک پروژه ی test جدید می شود که از MStest به عنوان test library استفاده می کند. ضمناً، اگر نگاهی به فایل PrimeServiceTests.csproj در یک xml editor بیندازید می بینید که به صورت خودکار test runner نیز برای ما پیکربندی شده است. این موضوع در کد زیر نشان داده شده است.

 

  
  
  

خب، پروژه ی test ای که تا به اینجا ایجاد کرده ایم نیاز به پکیج های دیگری نیز دارد تا بتواند به درستی کار کند. خب، در قسمت قبل با استفاده از دستور dotnet new توانستیم مواردی از قبیل MSTest SDK، MSTest test framework و همچنین MSTest runner را به پروژه اضافه کنیم. در این قسمت باید پروژه ی PrimeService را به عنوان یک dependency به پروژه ی test اضافه کنیم. اگر مایل باشید می توانید از آموزش معکوس سازی کنترل Inversion of Control در سی شارپ وبسایت پرووید که در رابطه با یک از مهمترین موضوع ها در توسعه ی نرم افزار تنظیم شده اند استفاده کنید.

به منظور اضافه کدرن پروژه ی PrimeService به پروژه ی test به عنوان یک dependency از دستور dotnet add reference ../PrimeService/PrimeService.csproj را استفاده می کنیم. ساختار زیر نشان دهنده ی ساختار فایل ها و فولدرهای پروژه تا اینجای کار می باشد. دستور زیر را در فولدر unit-testing-using-dotnet-test اجرا کنید.

solution-structure

افزودن قابلیت های دیگر

حال که اولین test برنامه را نوشتیم، می توانیم به سناریوهای دیگری نیز فکر کنیم و test های دیگری نیز پیاده سازی کنیم. برای مثال، برای اعداد اول که پروژه ی ما در مورد آنها می باشد (دقت کنید که کلمه ی انگلیسی Prime Number به معنی عدد اول است.)، موارد دیگری مثل 1 و -1 نیز وجود دارد.

خب ممکن است فکر کنید که سریعاً برای این دو مورد نیز تعدادی test method اضافه کنیم. این کار شدنی است ولی مشکلی که ایجاد می کنید حجم بالای کدهای درون test class مان می باشد. ما می توانیم با قابلیت های فریم ورک MSTest اقدام به نوشتن test دو مورد از attribute هایی که در این شرایط می توانیم استفاده کنیم [DataTestMethod] و [DataRow] می باشند.

به بیان ساده [DataTestMethod] به منظور نوشتن test method هایی است که یک کد یکسان را test می کنند و [DataRow] به منظور مشخص کردن پارامترهای ورودی آن test method ها می باشد.

پس می توانیم به جای نوشتن test method های اضافه این دو attribute را به یک test تک اعمال کنیم. به این نوع test ها اصطلاحاً data driven test می گوییم. دقت کنید که پیاده سازی همین موضوع با استفاده از فریم ورک xUnit هم پیش از این بر روی وبسایت پرووید منتشر شده است. کدی که در قسمت زیر آمده است را مشاهده کنید.

 
[DataTestMethod]
[DataRow(-1)]
[DataRow(0)]
[DataRow(1)]
public void ReturnFalseGivenValuesLessThan2(int value)
{
    var result = _primeService.IsPrime(value);

    Assert.IsFalse(result, $"{value} should not be prime");
}

این data driven test سه مقدار یعنی 0 و 1 و -1 را بر روی متد IsPrime تست می کند. به attribute های [DataTestMethod] و [DataRow] دقت کنید. با استفاده از دستور dotnet test اقدام به run کردن این test ها کنید. خواهید دید که دو مورد از این test ها fail می شوند. برای اینکه هر سه test نوشته شده pass شوند کافی دستور if ای که در ابتدای متد IsPrime آمده است را با دستور if (candidate < 2) جایگزین کنید.

توصیه می کنیم حتماً از آموزش تست واحد Unit Testing در سی شارپ از وبسایت پرووید استفاده کنید. ضمناً، کد کامل مربوط به این آموزش را نیز برای شما در نظر گرفته ایم. امیدواریم که این آموزش از وبسایت پرووید نیز مورد توجه تمامی دوستان عزیر قرار گرفته باشد.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *