Sturm's avatar
Level 5

Custom Artisan Command Not Acknowledging Argument

I'm attempting to create a custom artisan command that calls another artisan command with specific arguments. However, it is ignoring one of the arguments.

    public function handle(): void
    {
        $this->call('test', ['--compact' => true, '--exclude-testsuite' => 'Integration']);
    }

This does call artisan test with the --compact switch, but it does not exclude the Integration test suite.

Calling sail artisan test --compact --exclude-testsuite=Integration does work just fine, so why is it ignoring that argument when I'm calling it from my custom command? Do I have the syntax wrong or something?

0 likes
12 replies
martinbean's avatar

@sturm Why not just use original command with the argument? Why do you need to create a “wrapping” command?

Sturm's avatar
Level 5

@martinbean It's a convenience command, to allow our developers to run sail artisan app:test without typing in those long switches and without making them create a shell alias.

martinbean's avatar

@Sturm Is that really the biggest issue your development team has? You could just as easily add an entry to your composer.json file’s scripts section.

But this really is a non-issue where the effort to “solve” it just far outweighs the problem itself.

1 like
Snapey's avatar

have you tried

Alternatively, you may pass the entire Artisan command to the call method as a string:

eg Artisan::call('test --compact --exclude-testsuite=Integration');

My only thought is if the hyphen in the exclude-testsuite is messing it up in some way

Sturm's avatar
Level 5

@Snapey Hmmm, doesn't seem to work:

 ERROR  Command "test --compact --exclude-testsuite=Integration" is not defined.
Tray2's avatar

Another way would do be create small sh files for the commands.

echo '!#/usr/bin/bash \nphp artisan <the desired command here>' >> a.sh && chmod +x a.sh && mv a.sh /usr/local/bin

Sturm's avatar
Level 5

Truth be told, I'd rather have an artisan command that runs ./vendor/bin/phpunit --no-coverage --exclude-testsuite Integration, but I cannot find a good way to run a shell command like that and get real-time results with the built-in ANSI coloring.

Sturm's avatar
Level 5

@Snapey I have tried, but it does not provide real-time feedback. We don't see the dots traversing across the screen or, for that matter, any output at all. The closest I can come is one of two approaches:

exec('./vendor/bin/phpunit --no-coverage --exclude-testsuite=Integration', $output);
$this->comment(implode(PHP_EOL, $output));

This 'exec' approach runs blindly, then spits out the results only after it's complete. It also doesn't include any coloring the way a normal ./vendor/bin/phpunit run would.

$process = new Process(['./vendor/bin/phpunit', '--no-coverage', '--exclude-testsuite=Integration']);
$process->run(function ($type, $buffer) {
    echo $buffer;
});

This approach, using Symfony\Component\Process\Process, is a little better. It does return real-time results, but no colors.

In both cases, most of the tests are either failing or erroring and I cannot figure out why. There's nothing wrong with the tests inherently, since the Artisan version, sail artisan test --compact --exclude-testsuite=Integration, works fine with all tests passing.

Oh, and if I try to skip Sail and just run ./vendor/bin/phpunit --no-coverage --exclude-testsuite=Integration, every single test errors with a PDOException: could not find driver:

Illuminate\Database\QueryException: could not find driver (Connection: pgsql, SQL: select tablename, concat('"', schemaname, '"."', tablename, '"') as qualifiedname from pg_catalog.pg_tables where schemaname in ('public'))
Snapey's avatar

@Sturm running test is not the same as other commands since most parameters are passed to php_unit and not parsed by the called command itself, so perhaps call with

 '--exclude-testsuite Integration' => true]
Sturm's avatar
Level 5

@Snapey Unfortunately, that doesn't work, either. So I think I will go with a non-artisan-command approach that seems to work okay. See below.

Sturm's avatar
Sturm
OP
Best Answer
Level 5

After spending far too much time on trying to move our Lando tooling over to Artisan, I've decided that probably the best approach is to use shell aliases. So I'll put these in our repo's README and recommend that our developers put this in there .bashrc, .zshrc, .aliases, or whatever file they prefer, as long as it is sourced upon login.

# Development Aliases

alias lint='[ -f ./vendor/bin/duster ] && ./vendor/bin/duster lint'
alias lint-fix='[ -f ./vendor/bin/duster ] && ./vendor/bin/duster fix'
alias testcov='[ -f sail ] && sail artisan test --compact --exclude-testsuite=Integratio>
alias test='[ -f sail ] && sail artisan test --compact --no-coverage --exclude-testsuite>
alias testint='[ -f sail ] && sail artisan test --compact --testsuite=Integration'
alias stan='[ -f ./vendor/bin/phpstan ] && ./vendor/bin/phpstan analyze'

alias precommit='lint-fix && lint && stan && testcov'

Please or to participate in this conversation.