Unit Test #2
در قسمت قبل درباره تست به صورت خلاصه صحبت کردیم و قرار شد در این مقاله در قالب یک مثال آن را پیاده سازی کنیم . تست نویسی محدود به زبان برنامه نویسی یا فریمرک خاصی نمی باشد . شما با هر تکنولوژی که تجربه کاری یا در شرکت استفاده میکنید می توانید تست نویسی داشته باشید . در این مقاله ما از پلتفرم محبوب .netcore و همچنین از ویرایشگر vs code استفاده میکنیم.
برای شروع پیش نیاز های زیر را در سیستم نصب کنید
فریمورک های تست :
بعد از انتخاب زبان برنامه نویسی باید فریمورکی که کار تست را قرار است انجام دهد انتخاب کنیم. برای تست فریمورک های مختلفی وجود دارند که میتوان بسته به نیاز انتخاب کرد
- Nunit
- MbUnit
- CsUnit
- xUnit
- MS Unit Test
فریمورک های بالا خیلی شبیه به هم کار میکنند و اصول مشابهی دارن .ما در این مقاله از xUnit فریمورک محبوبی که توسط مایکروسافت به صورت Open Sourse ایجاد شده است استفاده میکنیم همچنین میتوان برای F#, xamarin, vb هم استفاده کرد.
سناریو :
با یک پروژه web api ساده شروع میکنیم ابتدا به پروژه یک کلاس به اسم calculator با چهار تابع sum div power , inc اضافه میکنیم سپس به صورت مستقل برای هر تابع تست مینویسیم . سپس با استفاده از پترن Repository برای عملیات CRUD کاربر تست مینویسیم.
ساخت پروژه :
برای شروع وارد cmd شوید و با دستو dootnet –version از صحت نصب .netcore اطمینان حاصل فرماید سپس با دستور زیر لیست از Templateهایی که میتوان ایجاد کرد را می توان مشاهده کنید.
1dotnet new --help
ابتدا فایل sln را ایجاد میکنیم بعد دو پروژه webapi، xunit را به فایل sln اضافه خواهیم سپس پروژه apiرا به پروژه تست رفرنس میدهیم.
ساخت پروژه با dotnet cli :
1234567891011121314dotnet new sln mkdir Api cd Api dotnet new webapi cd.. mkdir ApiXUnit cd ApiXUnit dotnet new xunit dotnet add reference ../Api/Api.csproj cd .. dotnet sln add Api/Api.csproj dotnet sln add ApiXUnit/ApiXUnit.csproj dotnet sln list code .
با دستورات بالا ساختار پروژه را ایجاد کردیم و با دستور dotnet sln list لیست پروژه های اضافه شده به solution را میتوان مشاهده کرد همچنین با دستور code . پروژه را در ویرایشگر باز میکنیم.
میتوان گفت به نقطه صفر پروژه رسیدیم و باید وارد کدنویسی شویم ! پروژه را باز کنید و یک کلاس به اسم calculate ایجاد کنید و به صورت زیر کانفیگ کنید.
12345678910111213141516171819public class Calculator { public int Sum(int n1, int n2) { return n1/n2; } public int Sub(int n1, int n2) { return n1-n2; } public int Division(int n1, int n2) { return n1/n2; } public int Multiplication(int n1, int n2) { return n1+n2; } }
کلاس بالا به صورت ساده چهار تابع که عملیات اصلی را انجام میدهند ایجاد کردیم .فرض را بر ان میگیریم برنامه نویس هنگام کد نوشتن دچار خطا شده است . میخواهیم کلاس Calculator را تست کنیم که آیا طبق ورودی هایی که به توابع میدهیم خروجی به صورت صحیح است یا خیر! وارد پروژه تست شوید کلاس پیشفرض را حذف کرده و یک کلاس جدید به نام CalculatorTest به پروژه اضافه کنید و به صورت زیر کانفیگ کنید .قبل از اینکه خروجی را مشاهده کنیم نگاهی به پترن AAA بیندازیم.
1234567891011121314[Fact] public void Calculator_Test_Sum() { //Arrange var _calculator = new Calculator(); int n1, n2, result; n1 = 5; n2 = 6; result = 11; //Act int resultSum = _calculator.Sum(n1, n2); //Assert Assert.Equal(resultSum, result); }
توجه کنید شما مجاز به تست Public Api هستید
سعی کنید به صورت self documented code پیش بروید و نگرانی طولانی بودن اسم ها نباشید
؛AAA متد را به سه قسمت تقسیم میکند که هر قسمت وظیفه خود را انجام میدهند.
؛ Arrange : اولین بخش از پترن AAA می باشد در این قسمت ما instanse ها مقدار دهی ها تنظیمات مربوط به moq ، ورودی ها … را انجام میدهیم به طور خلاصه تمام نیاز هایی که برای ایجاد تست لازم است در این قسمت تعریف میکنیم.
؛ Act : بعد آماده شدن Arrange تست را با ورودی های تعریف شده فراخوانی میکنیم به طور خلاصه ما در Act فراخوانی ها را انجام میدهیم.
؛ Assert : قسمت نهایی خواهد بود . خروجی متد تست را با نتیجه درست که انتظار داریم مقایسه میکنیم اگه به هر دلیلی Assert درست نباشد فریمورک خطایی مبنی به درست نبودن تست نمایش میدهد.Assert میتوان حاوی مقادیر مختلفی جهت تست باشد ! در این لینک میتوان Assertions های مختلف را بسته به نیاز استفاده کنید.
- Arrange. With this action, you prepare all the required data and preconditions.
- Act. This action performs the actual test.
- Assert. This final action checks if the expected result has occurred.
پس از نوشتن تست برای اجرا نیاز به runner داریم که کد ها را کاوش کند. برای شروع از کتاب خانه زیر که به صورت پیش فرض نصب می شود استفاده میکنیم
xunit.runner.visualstudio
برای اینکه متد های تست توسط runner ها شناسایی شوند از اتریبیوت [fact] استفاده می کنیم که میتوان شامل ورودی های مختلفی باشد که در ادامه بیشتر برسی خواهیم کرد . برای شروع تابع sum را با ورودی 5 و 6 را شروع به تست میکنیم و انتظار داریم پیغام موفقیت بودن تست توسط runner نمایش داده شود. وارد پروژه تست شوید و با دستور dotnet test تابع sum را مورد تست قرار دهید.
خروجی حاوی اطلاعات کلی در رابطه تعداد تست ، تعداد تست های fail شده ،اسم تابع ای که در ان تست رخ داده است ، خروجی تست و خروجی که ما انتظار داشتیم و …. است
A total of 1 test files matched the specified pattern. [xUnit.net 00:00:00.84] ApiXUnit.Model.CalculatorTest.Calculator_Test_Sum [FAIL]
X ApiXUnit.Model.CalculatorTest.Calculator_Test_Sum [7ms]
Error Message:
Assert.Equal() Failure
Expected: 0
Actual: 11 Stack Trace:
at ApiXUnit.Model.CalculatorTest.Calculator_Test_Sum() in C:\xxx\CalculatorTest.cs:line 23
Test Run Failed.
Total tests: 1
Failed: 1
Total time: 1.8465 Seconds
با توجه به خروجی بالا میتوان نتیجه گرفت
- تعداد کل تست ها 1بوده
- تعداد تست های fail شده 1بوده
- خروجی مورد نظر ما 11 بوده ولی 0 برگشت داده شده
- اطلاعاتی در مورد آدرس تابع fail شده
- مدت زمان صرف شده میتوان مشاهده کرد.
با توجه به اطلاعات بالا میتوان فهمید درون کلاس Calculator متد sum دچار خطا شده است . وارد تابع sum شوید و n1/n2 که به اشتباه وارد شده است را به n1+n2 تغییر دهید و مجددا dotnet test را اجرا کنید
همانطور که در شکل مشاهده میکنید تست با موفقیت pass شد. برای چهار مدت دیگر هم تست بنویسید و ان را pass کنید. طبق روش بالا برای هر تابع باید یک تست بنویسیم برای اینکه یک تابع با ورودی های مختلف داشته باشیم میتوانیم از اتریبیوت InlineData استفاده کنیم همچنین از Theoryبه جای Fact استفاده می کنیم.
12345678910111213[Theory] [InlineData(5, 4, 9)] [InlineData(9, 4, 13)] [InlineData(5, 8, 9)] public void Calculator_Test_Sum_By_InlineData(int n1 ,int n2,int result) { //Arrange var _calculator = new Calculatr(); //Act int resultSum = _calculator.Sum(n1, n2); //Assert Assert.Equal(resultSum, result); }
تا اینجا کار به ساده ترین شکل برای کلاسمان تست نوشتیم در مقاله بعدی سعی میکنیم به صورت جزئی تر وارد کد نویسی شویم
اگه از مقاله راضی بودید میتونید از لینک زیر برام قهوه بخرید : )