<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های matin khaje khalili</title>
        <link>https://virgool.io/feed/@matin-kh73</link>
        <description>دارم روش فکر میکنم، به زودی بیو خفنی اینجا نوشته خواهد شد :))</description>
        <language>fa</language>
        <pubDate>2026-04-14 15:25:07</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/28170/avatar/xNurYp.png?height=120&amp;width=120</url>
            <title>matin khaje khalili</title>
            <link>https://virgool.io/@matin-kh73</link>
        </image>

                    <item>
                <title>همه چیز در مورد نحوه استفاده از Repository pattern در فریم ورک Laravel</title>
                <link>https://virgool.io/avasam-laravel-edu/%D9%87%D9%85%D9%87-%DA%86%DB%8C%D8%B2-%D8%AF%D8%B1-%D9%85%D9%88%D8%B1%D8%AF-%D9%86%D8%AD%D9%88%D9%87-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-repository-pattern-%D8%AF%D8%B1-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-laravel-jzajqpddybxt</link>
                <description>به نام ایزد یکتاسلام خدمت همه دوستان عزیزاین مقاله در خصوص یکی از انواع الگوهای طراحی در برنامه نویسی یا به عبارت دیگر Design pattern ها هستش که در اینجا به توضیح یکی این الگوها یعنی Repository pattern میپردازیم.امیدوارم که در انتهای این مطلب تونسته باشم قدمی کوچک در جهت پیشرفت و آگاهی شما عزیزان برداشته باشم.قبل از اینکه به سراغ توضیح این الگو بریم یه نیم نگاهی به تعریف Design pattern داشته باشیم اینکه چیه و چه کاربردی داره و ....چی هست این Design Pattern..؟الگوهای طراحی مثل دستورالعمل‌هایی برای توسعه‌دهندگان در برنامه‌نویسی شی‌گرا، و راه‌حل‌هایی برای حل مشکلات متداول در طراحی نرم‌افزار هستند(چقد سخت شد!!). الگوهای طراحی برای اولین بار توسط یک گروه چهار نفره به نام GOF معرفی شدند. این گروه در کتابی به معرفی 23 الگوی طراحی پرداختند و این 23 الگو را در 3 دسته الگوهای ایجادی(Creational)، الگوهای ساختاری(Structural) و الگوهای رفتاری(Behavioral) قرار دادند.نکته :الگوهای طراحی جزو معماری های نرم افزاری نیستند و فقط شیوه ای صحیح از کدنویسی شی گرا را ارائه میدن. بنابراین این الگوها فقط در قلمرو کدنویسی شی گرا وارد میشن و مستقل از زبان های برنامه نویسی هستند.(در هر زبانی که از شی گرایی پشتیبانی میکنه میشه ازشون استفاده کرد)پیشنهاد میکنم حتماااااااااااااااااااااااااا به عنوان یه برنامه نویس حداقل یکبار هم که شده این الگوهارو مطالعه کرده و با ساختار اونها آشنا بشین.خب حالا بریم سر وقت الگوی طراحی خودمون یعنی Repository patternروالی که توضیح خواهیم به این صورت خواهد بود :1-  یه تعریفی از این الگو میکنیم اینکه چیه و تاریخچش و ... 2- چرایی استفاده ازش 3- انواع پیاده سازیش 4- چالش¬های مطرح در این الگو4- نحوه استفاده ازش رو در فریم روک لاراول توضیح میدیم.معنی لغوی Repository pattern، مخزن یا لایه ای جهت ذخیره کردن اطلاعات میشه.  Repositoryیک لایه میان لایه بیزنس (Business logic layer) و لایه دیتا (Data access layer) در پروژه شما ایجاد میکنه و هدفش جلوگیری از دسترسی مستقیم لایه بیزنس به لایه دیتاتون هستش. در واقع این لایه(Repository) مسئولیت کار با لایه دیتا رو به عهده داره و تمامی کدهای مربوط به کوئری ها و ... در این لایه نوشته میشن که در صورت نبودن این لایه تمامی این کارها بایستی در لایه بیزنس پروژتون انجام بشه.(برای درک بیشتر لایه بیزنس رو کلاس های Controller و لایه دیتا رو Model ها در لاراول در نظر بگیرین!)Repository pattern structureطبق اولین اصل از اصول SOLID، یعنی Single responsibility هر کلاس مسئول انجام یک وظیفه هستش که با این وجود در لایه ای مثل Controller در ساختار MVC نبایستی منطق مربوط به لایه دیتا پیاده سازی بشه. بنابراین در الگوی Repository pattern این لایه(Controller) برای اجرای دستورات و یا فراخوانی داده ها از طریق Repository  مورد نظرش درخواست های خودش رو مطرح میکنه.چرایی استفاده از Repository Patternبه صورت کلی اگر بخوایم مزایای استفاده از این الگو رو بگیم به این صورت میشه :1- از تکرار شدن کوئری ها (مخصوصا کوئری های پیچیده) در سراسر برنامه جلوگیری میکنه و اونهارو در یک جا متمرکز می کنه2- در آینده اگر به هر دلیلی بخواید معماری دسترسی به داده های دیتابیستون(ORM) رو تغییر بدین ،به راحتی میتونین با انجام یکسری تغییرات این کار رو انجام بدین3- در پروژه های بزرگ ممکنه شما از انواع مختلفی از دیتابیس ها در پروژتون استفاده کنید با استفاده از پیاده سازی این الگو میتونید بدون هیچ استرس و تغییرات زیادی این کار رو انجام بدین.4- با توجه به رعایت شدن اصل Single Responsibility ، به راحتی میتونیم برای کلاس هامون Unit Test بنویسیم.انواع پیاده سازیشبرای پیاده سازی این الگو در چارچوب لاراول تفکرات زیادی وجود داره.روش اولیکی از این تفکرات ساخت یک کلاس جامع برای تمامی مدل هامون در پروژه هستش که این کلاس بایستی از یک قانون(contract/interface) به صورت کلی پیروی کنه. عملکردهایی که در ارتباط با دیتابیس(منظور کوئری هایی که داریمه) وجود دارند در این کلاس نوشته میشه. در نهایت با استفاده از Service Container لاراول این دو کلاس عزیزمون رو بهم در هسته لاراول(provider) bind  میکنیم و در آخر هم قانون ساخته شده رو در کنترلر مد نظرمون Inject میکنیم که با اینکار به راحتی میتونیم از قابلیت های کلاس Repository مون استفاده کنیم.مزایا : در این سناریو تمامی متدهای مورد نیازمون در یک کلاس جمع آوری  میشه که با این کار یه جورایی از پراکندگی کدها جلوگیری میشه!(همه نیازمندی¬ها داخل یک کلاس هستند)بر اساس نظر خودم و برخی از اساتید این روش رو معمولا در پروژه هایی به کار میگیرن که عملیات خوندن روی دیتاهاشون زیاد ندارن و بیشتر علاقه به نوشتن دارن.معایب : یکی از بزرگترین معایبی که این سناریو داره محدود کردن مدل¬ها به استفاده از متدهای تعریف شده در کلاس ایجاد شده هستش. همچنین باعث میشه کلاس ساخته شده به شدت بزرگ و شلوغ بشه! چون ممکنه هر مدل سناریو و ساز و کارهای(کوئری) مربوط به خودش رو برای ارتباط با دیتابیس داشته باشه پس در نتیجه منطقی به نظر نمیرسه که برای کلیه مدل هامون از یک کلاس استفاده کنیم. باز بر اساس نظر خودم و برخی دیگر از اساتید، استفاده از این روش رو معمولا در پروژه های با اندازه بزرگ که عملیات خواندن دیتاهاشون زیاده هستش پیشنهاد میدم.روش دومبه ازای هر مدل یک Repository  و حداقل یک قانون(contract/interface) داریم که این کلاس بایستی از یک کلاس انتزاعی(abstract) ارث بری(extend) کند و همچنین این کلاس انتزاعی هم بایستی به صورت جداگانه برای خودش یک قانون رو پیاده سازی کنه.حال به توضیح هر کدام از کارهای گفته شده می¬پردازیم.با کلاس انتزاعی شروع کنیم...(چرا و به چه دلیل؟)این کلاس در واقع یک بیسی برای تمامی کلاس های Repository مون هستش که داخلش عملیات CRUD و همچنین برخی از کوئری های پر تکرار به صورت جامع پیاده سازی میشه.این کلاس همچنین وظیفه ساخت آبجکت از مدل هامون رو هم به عهده داره که در واقع با این کارش هست که میتونه کوئری های مختلف رو داخل خودش هندل کنه.قانونی که این کلاس پیاده سازی میکنه در واقع بدنه متدهای CRUD جهت ارتباط Repository ها با دیتابیس ها هستش.(هر دیتابیسی عملیات CRUD رو برای جداولش داره).گفتیم هر Repository  حداقل یک قانون رو بایستی پیاده سازی کنه که در این قانون عملیات های مختص هر Repository نوشته میشه و بسته به مدلش و دید برنامه نویس میتونه هر چیزی باشه!همچنین این قانون در آخر بایستی در هسته لاراول به کلاس Repository مون bind بشه تا در کانستراکتور Controller مربوطش بتونیم از کلاسش استفاده کنیم.چالش های مطرح در استفاده از این الگو از مباحثی که حین استفاده از این الگو وجود داره موضوع ذخیره دیتاها در دیتابیس های رابطه ای هستش. یکسری از اساتید موافق پیاده سازی متدهای مربوط به ذخیره داده های رابطه ای درون خود کلاس های Repository هستن و برخی این امر رو بیهوده و اشتباه میدونن! حالا چرا؟؟چون زمانیکه بخوایم این متدها رو ایجاد کنیم بایستی از همان روابط پیاده شده در مدل هامون برای ذخیره اطلاعات استفاده کنیم(دوباره کاری میشه، تکرار کد و ...) اگر کسی برای اولین بار بخواد اینکار رو انجام بده احتمالا با یک دیوار فکری مواجه میشه که : هدف از این الگو کاهش کدهای تکراری هستش، پس چرا ما باید این تکرار رو جهت ذخیره داده هامون داشته باشیم؟؟اما موضوع جالبتر اینجاست که ما نخوایم عملیات ذخیره این داده هارو درون کلاسRepository مون انجام بدیم!! خب پس کجا باید بنویسیمشون؟؟! داخل کنترلر!! واقعا؟؟ اینجوری که نمیشه!! ساختار الگو زیر سوال میره!!من هم خودم این موضوع رو مثل شما قبول دارم اما برخی از اساتید استفاده از این الگو رو بیشتر جهت فراخوانی یا Read کردن اطلاعات پیشنهاد میدن تا ذخیره یا Write کردنشون! البته که منظور از ذخیره کردن اینجا بیشتر برای داده هایی که نیاز به استفاده از relation ها برای ذخیره دارند به کار میره.با این تفسیر شما بایستی پروژتون رو از لحاظ  حجم read or write کردن تحلیل کنین و با استفاده از نتیجه به دست اومده تصمیم بگیرین که آیا از این الگو استفاده کنین یا خیر!خب تا اینجا سعی کردیم مباحث تئوری مربوط به این الگو رو براتون توضیح بدم، از اینجا به بعد بایستی دست به کد بشین و کارایی که من انجام میدم رو شما هم مرحله به مرحله انجام بدین.اولین کاری که باید انجام بدیم تنظیم کردن ساختار دایرکتوری هامون برای ساخت کلاس های مربوط به این الگو هستش.- app
--- Http
--- Repositories
------ ModelName
--------- ModelRepository.php
--------- Contracts
------------ Interface1.php
------------ Interface2.php
------ RepositoryServiceProvider.php
------ BaseRepositoryInterface.php
------ BaseRepository.phpبحث ساختار دایرکتوریها سلقیه ای هستش اما این ساختاری که اینجا میبینید یه جورایی best practice هستش!کلیت این ساختار هم به این صورت هستش که به ازای هر مدل یک دایرکتوری وجود داره که داخلش یک کلاس Repository  با عنوان ModelRepository هست و همچنین یک دایرکتوری با عنوان Contracts باید داشته باشیم که داخلش قانون های مختص اون ModelRepository وجود داره.3 تا کلاس هم با عناوین BaseRepository  &amp; BaseInterfaceRepository &amp; RepositoryServiceProvier داریم که توضیحات دوتا از این کلاس هارو بالاتر گفتم و فقط توضیح یکیش مونده که اون رو هم در ادامه توضیح خواهم داد.اول از کلاس BaseInterfaceRepository شروع میکنیم  که گفته بودیم داخلش یکسری متدهای ثابت(CRUD) رو مینویسیم.interface BaseRepositoryInterface
{
public function read($id);
public function readAll();
public function add(array $data);
public function update($id);
public function remove($id);
public function removeRange(array $id)
}خب همونجور که میبینید متدهایی رو داخل این کلاس نوشتیم که برای کار با هر دیتابیسی پاسخگوی نیازهامون هستش.کلاس BaseRepository علاوه بر متدهایی که بایستی(مجبورا) پیاده سازی کنه، میتونه هر متد جامع دیگه ای که برای کار با مدل ها نیاز هستش رو داشته باشه.(مثلا متد findBy یا هر متد دیگه ای که فکر میکنید نیاز هستش) .همچنین میتونین متدهای دیگه ای رو مثل paginate یا ... برای زمانیکه که میخواین روی دیتاهاتون فیلتری اعمال کنین در نظر بگیرین.(تمامی عملکردهایی که تا دیروز داخل کنترلرهامون انجام میدادیم میتونیم تحت عنوان یک متد داخل Repository هامون داشته باشیم و هر کدوم رو بسته به نیازمون ازش استفاده کنیم.)abstract class BaseRepository implements BaseRepositoryInterface
{
private $model;
protected function setModel(Model $model)
{
      $this-&gt;model = $model;
      return $this;
}
public function getModel()
{
      return $this-&gt;model;
}
public function read($id){}
public function readAll()
{
      $this-&gt;model-&gt;sortBy(‘created_at’)-&gt;all();
}
public function add(array $data) {}
public function remove($id){}
public function removeRange(array $id) {}
public function update($id){}
}حال به سراغ پیاده سازی یکی از کلاس های Repository مون میریم. من در اینجا مدل فرضی Challenge رو در نظر گرفتم.class ChallengeRepository extends BaseRepository implements ChallengeRepositoryContract
{
public function __construct(Challenge $challenge)
{
    $this-&gt;setModel($challenge);
}
public function getChallengesWithProducts(Request $request){}
public function add(array $data)
{
   parent::add($data);
}
}شما در این کلاس میتونین از متدهای پیاده شده در کلاس والد(BaseRepository) استفاده کنید یا اگر ساز و کار دیگه ای رو از تابع پیاده شده مد نظر دارین میتونین اون متد رو override کنید و بجاش ساز و کار خودتون رو پیاده سازی کنین.در کلاس یک متد نام getChallengesWithProducts  وجود داره که این متد ساخته شده در ChallengeRepositoryContract هستش که بسته به نیاز مدلمون براش در نظر گرفتیم.بعد از ساخت این کلاس و همچنین قانونش کافیه که این دوتارو در هسته لاراول بهم Bind کنیم.کلاس RepositoryServiceProvider در واقع برای انجام همچنین کاری ساخته شده.class RepositoryServiceProvider extends ServiceProvider
{
public function register(){}
public function boot()
{
   $this-&gt;app-&gt;bind(
        ChallengeRepositoryContract::class,
        ChallengeRepository::class);
}
}به ورودی های متد bind دقت کنین، چرا که در صورت جابجا نوشتن کلاس ها با خطای لاراول مواجه میشین.(کلاس اول در واقع abstract class شما هستش و کلاس دوم کلاسی هست که از این abstract class ارث بری کرده!)برای اینکه این موضوع کامل تر براتون جا بیوفته در خصوص Service Container لاراول قشنگ تحقیق کنین. نکته ای که باید بهش توجه بکنین این هستش که بعد از ساخت این ServiceProvider بایستی به لیست سرویس های لاورال اضافش کنین تا حین بوت شدن پروژتون بتونین از این سرویس هم استفاده کنین...(داخل فایل app.php)خب دیگه همه چی اماده هستش برای اینکه ما بتونیم از Repository مون داخل کنترلر استفاده کنیم. فقط کافیست داخل متد کانستراکتور کنترلمون، ChallengeRepositoryContract رو اینجکت کنیم تا به راحتی بتونیم به متدهای مورد نیازمون دسترسی داشته باشیم.ممنون از توجهتون.راستی تا یادم نرفته اینرو هم بگم که برای استفاده از این سناریو من پکیجی رو اماده کردم که پیاده سازی رو براتون راحتتر میکنه و میتونید داخل پروژه هاتون ازش استفاده کنید. https://github.com/matin-kh73/RepositoryPattern موفق باشید.</description>
                <category>matin khaje khalili</category>
                <author>matin khaje khalili</author>
                <pubDate>Tue, 05 Mar 2024 13:39:08 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه برای پروژه های توسعه یافته تست بنویسیم؟</title>
                <link>https://virgool.io/codenevis/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D9%87%D8%A7%DB%8C-%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%DB%8C%D8%A7%D9%81%D8%AA%D9%87-%D8%AA%D8%B3%D8%AA-%D8%A8%D9%86%D9%88%DB%8C%D8%B3%DB%8C%D9%85-k2sstnpuxmmh</link>
                <description>خب قرار هستش در خصوص موضوع جذاب تست نویسی برای پروژه های توسعه یافته(لاراولی) از تجربیات خودم براتون بگم! پس اماده باشید و یه لیوان قهوه ام بزارید کنارتون که یه وقت وسط خوندن این مطالب خوابتون نبره!!بر اساس آمار سایت confidentlaravel از 15000 پروژه ای که با پکیچ shift به ورژنای بالاتر ارتقا پیدا کردن تنها 17% از اونها تست داشتن و خب این یعنی یک فاجعه!!از اکثر برنامه نویسان(سطح متوسط رو به بالا) اگر بپرسید چرا پروژتون تست نداره میگن فرصت لازم برای تست نوشتن نداریم!! از نصف نصفشون میشه این حرفو قبول کرد اما ¾ مابقی نمیدونن دقیقا از کجا باید شروع به نوشتن تست کنند!(البته بنظر من)نوشتن تست برای پروژه هایی که تموم شدن یا پیشرفت زیادی داشتن شاید در نگاه اول سخت و نشدنی به نظر بیاد اما اینجا حکایت همون چشم میبینه و دست میترسه هستش! بزارید برای شروع اول یه سوال مطرح کنیم.سوال : چرا ما برای پروژه هامون تست مینویسیم؟ جواب : برای اینکه از صحت عمکلرد &quot;بخشای مختلف&quot; برناممون مطمئن بشیم.خب شما به عنوان برنامه نویس قطعا باید بدونی پروژه ای که روش کار کردی یا میکنی از چه بخش هایی تشکیل شده.ما اگر یک پروژه لاراولی رو در نظر بگیریم خب این پروژه از یکسری بخش های ثابت که بیسش توسط لاراول نوشته شده مثل : model – controller– event – listener -  middleware – validation– route –و ... تشکیل شده!علاوه بر سرویس ها و ماژول هایی که ما خودمون از بیس  طراحیشون میکنیم از اکثر بخش های بالا(یا بعضا تمامشون) هم ممکنه تو پروژه های لاراولیمون استفاده کنیم.خب اینجا مهم ترین سوال برای کسی که اولین بار میخواد برای یک پروژه تست بنویسه این باشه که از کجا شروع کنم؟ چه تستی بنویسم؟یه آدم خفنی به اسم Jason McCreary تو این زمینه میگه اول ساده ترین قسمت پروژتون رو انتخاب کنید بعد هر نوع تستی که بلد هستین رو براش پیاده کنید! فرق نمیکنه unit test  باشه یا feature test (پایین تر فرق این دوتارو توضیح میدم).حالا بنظرتون دلیل این امر چیه؟آفرین! برای اینه که در انجام هر کاری بایستی اول اعتماد بنفس لازمش رو داشته باشیم، بعد که اعتماد بنفسش رو پیدا کردیم میتونیم خیلی راحتتر اون کار رو انجام بدیم.در ادامه همین آدم خفن میگه از Http test ها شروع کنیم، چرا؟؟چون با Http request ها خیلی از بخش های پروژمون درگیر میشه و با استفاده از ارسال یک درخواست میتونیم صحت خیلی ازاین بخش هارو بررسی کنیم. از اینرو برای شروع میایم انواع درخواست ها رو با توجه به مسیرهایی که برای برناممون در نظر گرفتیم به سرور ارسال میکنیم و بخش های مختلف پروژمون رو باهاش تست میکنیم. در بعضی از درخواست ها نیاز هستش که یکسری داده هم همراه باهاشون به سمت سرور ارسال بشه، مثلا برای ثبت نام یه کاربر باید اطلاعاتش رو خودمون به صورت دستی پر کنیم و ارسال کنیم. روش دیگه ای که وجود داره استفاده از کتابخانه faker هست که به صورت پیشفرض این کتابخانه بر روی لاراول وجود داره. فکر میکنم از روی اسمش بتونید حدس بزنید که ساز و کار این کتابخانه چی هستش!ا Faker یک کتابخانه جهت تولید داده های مصنوعی برای انواع مختلف داده ها هستش.لزوم استفاده از این کتابخانه بیشتر در model factory ها احساس میشه. حالا model factory چیه؟؟اجازه بدین با یک مثال توضیح بدم...فرض کنید جهت انجام یک تستی بایستی حجم زیادی از داده ها رو در جداول دیتابیستون داشته باشین. بدون استفاده از model factoryها شما باید برای داده های هر کدوم از جداولتون یک حلقه به تعداد گام دلخواهتون ایجاد کنید و داخل حلقه عملیات مربوط به ساخت داده ها رو انجام بدین.به دلیل تمیز نبودن روش بالا و همچنین مشکلاتی که برای ما به وجود خواهد آورد لاراول سیستمی رو تحت عنوان model factory  از لاراول 5.1به بعد معرفی کرد model factory . ها جهت ایجاد داده های مصنوعی برای مدل ها به جهت استفاده در  testingو database seeding به وجود اومدن.برای توضیحات بیشتر پیشنهاد میکنم حتما داکیومنت خود لاراول رو مطالعه کنید.خب همون طور که میدونید لاراول یه دستوری داره با عنوان php artisan make:test“ className” که این دستور برای شما یک کلاس تست با نام وارد شده (className) در داخل دایرکتوری tests/Feature ایجاد میکنه. از اونجایی که میدونم تفاوت Unit test  با  Featuer Test رو میدونید اما من باز هم یه توضیح مختصری در این مورد میدم.در unit test ما از دید برنامه نویس به قسمت های مختلف پروژه نگاه میکنیم و صحت یه متد یا قسمتی از یک کلاس رو مورد بررسی قرار میدیم.اما در feature test از دید کاربر نهایی به سیستم نگاه میشه و اطمینان حاصل می­کنیم که سیستم همانطور که کاربران از آن انتظار دارند کار می­کند. در این نوع از تست ها ممکنه بخش های مختلفی از پروژه مثل Database و... درگیر شوند.بزارید با یک مثال براتون توضیح بدم، کلاس مربوط به ثبت نام یک کاربر رو در نظر بگیرید.این کلاس از یک تابع به اسم register تشکیل شده که بدین شکل هستش :در feature test صحت ساز و کار ثبت نام شدن یا نشدن کاربر رو بررسی میکنیم که در صورت موفقیت آمیز بودن ثبت نام کاربر، این تابع باید خروجی با عنوان ok رو به ما برگردونه.اما در unit test میتونیم صحت اعتبار سنجی داده های ارسالیمون رو بررسی کنیم که ببینیم آیا این اعتبار سنجی به درستی عمل میکند یا خیر.در واقع در unit test صحت ساز و کار بخشی از یک روند  کامل رو بررسی می­کنیم.خب حالا با توجه به این توضیحات Http test ها جزو کدوم دسته محسوب میشن؟؟نکته ای که در خصوص نحوه مسیر دهی به کلاس های تست بهتره که رعایت کنیم(best practice) اینه که مثلا اگر قرار هستش برای یک کنترلر که در آدرس Http/Controller/Auth/LoginController قراره داره تستی نوشته بشه، همین آدرس رو برای کلاس تستش هم در نظر بگیریم که تست هامون تفکیک شده باشه و همچنین تشخیص این موضوع که برای چه بخش هایی از پروژه تست نوشته شده راحتتر باشه.خب دیگه توضیح دادن کافیه بریم سراغ یه مثال ساده.مثال :  تستی رو می­نویسیم که صحت روند ثبت نام یک کاربر رو بررسی میکنه.بعد از نوشتن تست مورد نظرمون باید اون رو اجرا کنیم.با استفاده از دستور ./vendor/bin/phpunit میتونید تمامی تست های نوشته شدتون رو اجرا کنید.در این دستور کلمه ای که نیاز به توضیح داره phpunit  هستش که من بسنده میکنم به توضیح خود سایت phpunit که امیدوارم انگلیسیتون خوب باشه و متوجه تعریفش بشین.PHPUnit is a programmer-oriented testing framework for PHP.It is an instance of the xUnit architecture for unit testing frameworks.خب از خط اول اگر بخوایم توضیح بدیم میرسیم به نام تابع! شاید این نوع نام گذاری براتون جدید باشه اما برخلاف نام توابع در کلاس های اصلی، این نوع نام گذاری کمک به فهم تست نوشته شده می­کنه که پیشنهاد میکنم نامگذاری تست هاتون به این صورت باشه.در خط 18 اطلاعات کاربری که قرار هستش ثبت نام بشه رو در نظر گرفتیم.در خط 25 درخواستی رو با متد POSTبه آدرس مربوطش به همراه اطلاعات کاربرمون ارسال کردیم.این درخواست بعد از طی کردن یه مسیری جوابی رو به ما برمیگردونه که میتونه هر چیزی باشه.در خط 26، status code مورد انتظارمون رو بررسی کردیم که بایستی این  statusبا مقدار وارد شده یکی باشد.چیزی که ما از ارسال این درخواست انتظار داریم این هستش که در صورت درست بودن اطلاعات ارسالی، کاربری با این اطلاعات در جدول user وجود داشته باشه که در خط 28 این مورد رو بررسی کردیم.اگر تستی که نوشتین پاس بشه باید در محیطی که دستور اجرای تست هاتون رو نوشتین با این پیغام مواجه بشین :که در اینجا تعداد تست هایی که اجرا شدند و همچنین تعداد assertion(انتظاراتی که داشتین)های نوشته شده  رو براتون مشخص میکنه.اگه خسته نیستین اجازه بدین قبل از تموم کردن بحثمون یه توضیح مختصری در خصوص  assertionها هم بهتون بدم.ما با استفاده از assertion ها صحت تست هامون رو بررسی میکنیم. در واقع اگر بخوایم به زبان خودمون این توابع رو معنی کنیم به این صورت میگیم : من انتظار دارم status code تولید شده برابر باشه با مقداری که من بهت میدم( ()assertStatus )یا مثلا من انتظار دارم در دیتابیس، داده ای که برات مشخص میکنم وجود داشته باشه ( ()assertDatabaseHas )خب دیدید نوشتن یه تست چقدر راحته؟ به همین راحتی برای بقیه بخش های پروژتون هم میتونید تست بنویسید.کلام آخر : تمرکز و هدف اصلیتون، اطمینان پیدا کردن از درست بودن ساز و کار برنامه ای که نوشتین باشه.در تست نوشتن برای پروژه هایی که تموم شدن یا پیشرفت زیادی داشتن باید سعی کنید از ساده ترین بخش های پروژتون شروع کنید و کم کم برید سراغ قسمت های پیچیده پروژتون.شاید اگر بار اولتون باشه که قرار هست برای یک سیستم تست بنویسید، ناخواسته وسواس زیادی به خرج بدین و مثلا قصد داشته باشین پیغام  برگشتی از یک validation error رو هم بررسی کنید اما من بهتون میگم این کار نیاز نیست.منتظر نظراتتون هستم..موفق باشید.</description>
                <category>matin khaje khalili</category>
                <author>matin khaje khalili</author>
                <pubDate>Tue, 05 Mar 2024 13:38:40 +0330</pubDate>
            </item>
            </channel>
</rss>