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
Configure and Test Laravel Task Scheduling
提问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:run
and 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\Event
to 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());
}
}