php 配置和测试 Laravel 任务调度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40161679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:07:59  来源:igfitidea点击:

Configure and Test Laravel Task Scheduling

phplaravellaravel-5

提问by cyber8200

Environment

环境

  • Laravel Version : 5.1.45 (LTS)

  • PHP Version : 5.6.1

  • Laravel 版本:5.1.45 (LTS)

  • PHP 版本:5.6.1



Description

描述

I'm trying to run a command every 1 minute using Laravel Task Scheduling.

我正在尝试使用 Laravel Task Scheduling每 1 分钟运行一次命令。



Attempt

试图

I've added this line to my cron tab file

我已将此行添加到我的 cron 选项卡文件中

* * * * * php artisan schedule:run >> /dev/null 2>&1

* * * * * php artisan schedule:run >> /dev/null 2>&1

Here is my /app/Console/Kernel.php

这是我的/app/Console/Kernel.php

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        \App\Console\Commands\Inspire::class,
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('inspire')->hourly();
        $schedule->command('echo "Happy New Year!" ')->everyMinute(); //<---- ADD HERE        }
}

I've added this line $schedule->command('echo "Happy New Year!" ')->everyMinute();

我已经添加了这一行 $schedule->command('echo "Happy New Year!" ')->everyMinute();



Question

How do I test this ?

我如何测试这个?

How do I trigger my echo to display ?

如何触发我的回声显示?

How do I know if what I did is not wrong ?

我怎么知道我所做的没有错?



I'm opening to any suggestions at this moment.

我现在愿意接受任何建议。

Any hints / suggestions / helps on this be will be much appreciated !

对此的任何提示/建议/帮助将不胜感激!

采纳答案by nXu

command()runs an artisan command. What you're trying to achieve - issuing a command to the OS - is done by exec('echo "Happy New Year!"')

command()运行工匠命令。您要实现的目标 - 向操作系统发出命令 - 由exec('echo "Happy New Year!"')

Testing depends on what you want to test:

测试取决于您要测试的内容:

  • Whether the scheduler (every minute) is working?
  • 调度程序(每分钟)是否在工作?

In this case, you don't have to. It is tested in the original framework code.

在这种情况下,您不必这样做。它在原始框架代码中进行了测试。

  • Whether the command succeeds?
  • 命令是否成功?

Well, you can manually run php artisan schedule:runand see the output.

好吧,您可以手动运行php artisan schedule:run并查看输出。

The scheduler does not produce any output on default (>> /dev/null 2>&1). You can, however, redirect the output of the runned scripts to any file by chaining writeOutputTo()or appendOutputTo()(https://laravel.com/docs/5.1/scheduling#task-output).

调度程序在默认情况下不产生任何输出 ( >> /dev/null 2>&1)。但是,您可以通过链接writeOutputTo()appendOutputTo()( https://laravel.com/docs/5.1/scheduling#task-output)将运行脚本的输出重定向到任何文件。



For more complex logic, write a console command instead (https://laravel.com/docs/5.1/artisan#writing-commands) and use command()- this way you can write nice, testable code.

对于更复杂的逻辑,请改为编写控制台命令 ( https://laravel.com/docs/5.1/artisan#writing-commands) 并使用command()- 这样您就可以编写漂亮的、可测试的代码。

回答by Michiel

If you want to unit test the scheduling of events you can use this example. It is based on the default inspire command:

如果要对事件的调度进行单元测试,可以使用此示例。它基于默认的inspire 命令:

public function testIsAvailableInTheScheduler()
{
    /** @var \Illuminate\Console\Scheduling\Schedule $schedule */
    $schedule = app()->make(\Illuminate\Console\Scheduling\Schedule::class);

    $events = collect($schedule->events())->filter(function (\Illuminate\Console\Scheduling\Event $event) {
        return stripos($event->command, 'YourCommandHere');
    });

    if ($events->count() == 0) {
        $this->fail('No events found');
    }

    $events->each(function (\Illuminate\Console\Scheduling\Event $event) {
        // This example is for hourly commands.
        $this->assertEquals('0 * * * * *', $event->expression);
    });
}

回答by Adam Moore

Building on Michiel's answer, I've used the methods contained in Illuminate\Console\Scheduling\Eventto test if the event is due to run for a given date.

基于 Michiel 的回答,我使用 中包含的方法Illuminate\Console\Scheduling\Event来测试事件是否应在给定日期运行。

I've mocked the current date using Carbon::setTestNow()so that any date based logic in the when()and skip()filters will behave as expected.

我已经使用模拟了当前日期,Carbon::setTestNow()以便when()skip()过滤器中任何基于日期的逻辑都将按预期运行。

use Tests\TestCase;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Console\Scheduling\Event;

use Cron\CronExpression;
use Carbon\Carbon;


class ScheduleTest extends TestCase {


    public function testCompanyFeedbackSchedule()
    {
        $event = $this->getCommandEvent('your-command-signature');

        $test_date = Carbon::now()->startOfDay()->addHours(8);

        for ($i=0; $i < 365; $i++) { 
            $test_date->addDay();
            Carbon::setTestNow($test_date);

            // Run the when() & skip() filters
            $filters_pass = $event->filtersPass($this->app);
            // Test that the Cron expression passes
            $date_passes = $this->isEventDue($event);
            $will_run = $filters_pass && $date_passes;

            // Should only run on first friday of month
            if ($test_date->format('l') === 'Friday' && $test_date->weekOfMonth === 1) {
                $this->assertTrue($will_run, 'Task should run on '. $test_date->toDateTimeString());
            } else {
                $this->assertFalse($will_run, 'Task should not run on '. $test_date->toDateTimeString());
            }
        }
    }


    /**
     * Get the event matching the given command signature from the scheduler
     * 
     * @param  string  $command_signature
     * 
     * @return Illuminate\Console\Scheduling\Event
     */
    private function getCommandEvent($command_signature)
    {
        $schedule = app()->make(Schedule::class);

        $event = collect($schedule->events())->first(function (Event $event) use ($command_signature) {
            return stripos($event->command, $command_signature);
        });

        if (!$event) {
            $this->fail('Event for '. $command_signature .' not found');
        }

        return $event;
    }


    /**
     * Determine if the Cron expression passes.
     * 
     * Copied from the protected method Illuminate\Console\Scheduling\Event@isEventDue
     * 
     * @return bool
     */
    private function isEventDue(Event $event)
    {
        $date = Carbon::now();

        if ($event->timezone) {
            $date->setTimezone($event->timezone);
        }

        return CronExpression::factory($event->expression)->isDue($date->toDateTimeString());
    }
}