WebPajooh
WebPajooh
خواندن ۲ دقیقه·۳ سال پیش

قابلیت کرم‌چاله در تست لاراول

کرم‌چاله را می‌توان به صورت تونلی تصور کرد که پایانه‌های آن در نقاط مجزایی از فضا-زمان قرار دارند.

صورت مسئله

در حال ساختن وب‌سایت برای یک رویداد خیلی مهم هستیم. افراد برای این رویداد خیلی مهم صندلی رزرو می‌کنند و مهلت رزرو بلیت تا آخر ماه آوریل است. کد زیر یک مثال برای کنترل این وضعیت است:

کد رزرواسیون
کد رزرواسیون

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

نوشتن تست و مشکل زمان

با صرف نظر از Validation، دو حالت قابل تصور است:

  • تاریخ امروز قبل از سی‌ام آوریل است و یک id در پاسخ برگردانده می‌شود.
  • تاریخ امروز بعد از سی‌ام آوریل است و پیام خطا مشاهده می‌شود.

پس ما باید زمان فعلی را اصطلاحاً fake کنیم تا بتوانیم برای این دو حالت فرضی تست بنویسیم، وگرنه زمان فعلی، همان زمان اجرای تست در نظر گرفته خواهد شد و باید تا روز اول ماه می صبر کنیم و بعد دوباره تست را اجرا کنیم تا مطمئن شویم که سناریوی دوم درست کار می‌کند! (چه احمقانه)

استفاده از متد setTestNow

کتابخانۀ Carbon یک static method به نام setTestNow به این منظور نوشته بود که قبلاً استفاده می‌شد. با همین روش دو تست برای حالت‌های اول و دوم می‌نویسیم:

public function test_people_can_reserve_before_the_deadline() { $data = [ 'email' => 'alireza@gmail.com', 'age' => 25, ]; Carbon::setTestNow(Carbon::createFromDate(2022, 04, 29)); $this->post('/api/reservations', $data) ->assertJsonStructure(['id']); }
public function test_people_can_reserve_after_the_deadline() { $data = [ 'email' => 'parsa@gmail.com', 'age' => 23, ]; Carbon::setTestNow(Carbon::createFromDate(2022, 04, 30)); $this->post('/api/reservations', $data) ->assertJson(['error' => &quotIt's too late!&quot]); }

کرم‌چالۀ لاراول

در لاراول 8 قابلیتی اضافه شد که سفر در زمان را آسان‌تر کرد. کلاس TestCase از تریت Concerns\InteractsWithTime استفاده می‌کند که متدهایی را برای تغییر زمان پیاده کرده‌اند. اکنون به جای متد setTestNow به صورت زیر عمل می‌کنیم:

$this->travelTo(Carbon::createFromDate(2022, 04, 29));

گاهی نیاز داریم که زمان را به طور نسبی تغییر دهیم، مثلاً پنج ساعت قبل را شبیه‌سازی کنیم. در اینجا از متد travel استفاده می‌کنیم که عددی را به عنوان ورودی می‌گیرد و آبجکت Wormhole را برمی‌گرداند که متدهای جالبی روی آن پیاده شده است:

$this->travel(-5)->hours();

اگر بخواهیم به زمان حال برگردیم، از متد travelBack استفاده می‌کنیم:

$this->travelBack();

همچنین اگر بخواهیم که زمان را در هنگام اجرای تعدادی از دستورات متوقف کنیم، متد freezeTime را استفاده می‌کنیم که یک closure به عنوان آرگومان می‌پذیرد.


انتخاب عنوان‌هایی مثل travel یا Wormhole که بیشتر از انتزاع به واقعیت نزدیک است می‌تواند ایدۀ جالبی باشد و حتی خوانایی کدها را به نحوی بالاتر ببرد. چنین قابلیت‌هایی نوشتن تست را آسان‌تر کرده و به گسترش فرهنگ تست‌نویسی کمک می‌کنند.


برای مطالعۀ بیشتر، به مستندات رسمی لاراول مراجعه کنید:

https://laravel.com/docs/9.x/mocking#interacting-with-time

لاراولتست نویسیmockingآموزش لاراولآموزش ماک کردن
توسعه‌دهندۀ بک‌اند، امیدوار، خیال‌باف، علاقه‌مند به خواندن و نوشتن
شاید از این پست‌ها خوشتان بیاید