فصل 39 از 40 درس 1 از 1

Unit Testing مقدماتی

Unit Testing مقدماتی

بخشی از آموزش جامع C# و .NET 10

محتوای درس Unit Testing مقدماتی

Unit Test رفتار یک واحد کوچک از کد را به‌صورت خودکار بررسی می‌کند و امکان Refactoring امن‌تر و تشخیص Regression را فراهم می‌سازد. تست خوب سریع، مستقل و قابل تکرار است.

۱. Arrange, Act, Assert

در الگوی AAA ابتدا داده و وابستگی‌ها آماده، سپس رفتار اجرا و در پایان نتیجه بررسی می‌شود.

مثال

static int Add(int a,int b)=>a+b;
         int actual=Add(2,3);
         Console.WriteLine(actual==5);

در این مثال، مفهوم «Arrange, Act, Assert» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۲. xUnit

xUnit یکی از Frameworkهای رایج تست در .NET است و Fact و Theory را برای تست ثابت و پارامتری ارائه می‌کند.

مثال

// [Fact]
         // public void Add_Returns5() => Assert.Equal(5, Add(2,3));

در این مثال، مفهوم «xUnit» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۳. تست رفتار

بهتر است تست روی رفتار عمومی متمرکز باشد نه جزئیات داخلی Implementation.

مثال

static bool IsAdult(int age)=>age>=18;
         Console.WriteLine(IsAdult(18));

در این مثال، مفهوم «تست رفتار» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۴. Theory و InlineData

برای چند ورودی مشابه می‌توان از Theory و داده پارامتری استفاده کرد.

مثال

// [Theory]
         // [InlineData(18,true)]
         // [InlineData(17,false)]

در این مثال، مفهوم «Theory و InlineData» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۵. نام‌گذاری تست

نام تست باید شرایط، رفتار و انتظار را تا حد امکان روشن کند.

مثال

// Method_Scenario_ExpectedResult
         // Withdraw_InsufficientBalance_Throws

در این مثال، مفهوم «نام‌گذاری تست» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۶. مثال‌های عملی

public class PriceCalculatorTests
         {
             [Fact]
             public void ApplyDiscount_ReturnsDiscountedPrice()
             {
                 decimal result = PriceCalculator.ApplyDiscount(100m, 10m);
                 Assert.Equal(90m, result);
             }
         }

این نمونه عملی چند مفهوم فصل را در کنار هم قرار می‌دهد و برای مشاهده رفتار واقعی کد قابل اجرا و تغییر است.

[Theory]
         [InlineData(100, 10, 90)]
         [InlineData(200, 25, 150)]
         public void ApplyDiscount_Works(decimal price, decimal rate, decimal expected)
         {
             Assert.Equal(expected, PriceCalculator.ApplyDiscount(price, rate));
         }

این نمونه عملی چند مفهوم فصل را در کنار هم قرار می‌دهد و برای مشاهده رفتار واقعی کد قابل اجرا و تغییر است.

۷. خطاهای رایج

• تست چند رفتار مستقل در یک Test

• وابستگی Unit Test به فایل، شبکه یا زمان واقعی بدون کنترل

• تست مستقیم Private Method به‌جای رفتار عمومی

۸. نکات اجرایی

• نام‌ها، Typeها و Methodها را متناسب با مفهوم دامنه و بدون ابهام انتخاب کنید.

• هشدارهای کامپایلر و Nullable را بدون بررسی خاموش نکنید.

• منطق هر بخش را تا حد امکان کوچک، قابل تست و مستقل از I/O غیرضروری نگه دارید.

۹. تمرین عملی

برای کلاس BankAccount تست‌های Deposit، Withdraw، جلوگیری از مبلغ منفی و کسری موجودی بنویسید.

۱۰. جمع‌بندی

در این فصل، مبانی «Unit Testing مقدماتی» با تمرکز بر ساختارهای اصلی زبان، الگوهای صحیح استفاده و خطاهای رایج بررسی شد. تسلط بر این مفاهیم زمینه لازم برای اتصال موضوع به فصل‌های بعدی و طراحی کدهای خواناتر، قابل نگهداری و قابل تست را فراهم می‌کند.