paratestphp / paratest

:computer: Parallel testing for PHPUnit
MIT License
2.3k stars 227 forks source link

Environment Variables Not Available #721

Closed clwehunt closed 1 year ago

clwehunt commented 1 year ago
Q A
ParaTest version 6.8.1
PHPUnit version 9.5.28
PHP version 7.4.30

Summary

I am testing out a very simple phpUnit test.

public function testAppEnvVariableIsTest()
    {
        $this->assertEquals($_ENV['APP_ENV'], 'test');
    }

Current behavior

Running phpunit the results are: Environment: test 02/02/2023 11:25:02 pm

PHPUnit 9.5.28 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.4.30
Configuration: /phpunit.xml

.....                                                               5 / 5 (100%)

Time: 00:00.019, Memory: 6.00 MB

OK (5 tests, 5 assertions)

Running paratest via the following command: vendor/bin/paratest --runner WrapperRunner

ParaTest v6.8.1 upon PHPUnit 9.5.28 by Sebastian Bergmann and contributors.

Environment: test
02/02/2023 11:26:08 pm
...E.                                                               5 / 5 (100%)

Time: 00:00.464, Memory: 6.00 MB

There was 1 error:

1) ExampleTest::testAppEnvVariableIsTest
Undefined index: APP_ENV

FAILURES!                          
Tests: 5, Assertions: 4, Errors: 1.

You can see from the output above that paratest loads the same bootstrap file and can access it as the environment is printed correctly.

How to reproduce: command, code and error stack trace

Composer.json require:

"phpunit/phpunit": "^9.5",
"brianium/paratest": "^6.8",
"vlucas/phpdotenv": "^5.5",

Have an .env file with APP_ENV="test"

Have a bootstrap file referenced in phpunit.xml that loads the .env file:

require 'vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

Have a test defined as:

public function testAppEnvVariableIsTest()
    {
        $this->assertEquals($_ENV['APP_ENV'], 'test');
    }

Run vendor/bin/paratest --runner WrapperRunner

Expected behavior

I would expect the output to be the same as phpUnit, the environment variable to be available, and the assertion to be true: ParaTest v6.8.1 upon PHPUnit 9.5.28 by Sebastian Bergmann and contributors.

Environment: test 02/02/2023 11:28:15 pm

....                                                                5 / 5 (100%)

Time: 00:00.429, Memory: 6.00 MB

OK (5 tests, 5 assertions)
steltner commented 1 year ago

Had the same problem, cost me a day of my life, the paratest worker has every ENV-parameter as $_SERVER parameter (I don't know why) and the ServerConstAdapter we use as default adapter by creating Dotenv with Dotenv::createImmutable(__DIR__) will return that every ENV-parameter is externally defined (see ImmutableWriter->isExternallyDefined($parameterName)) and so it will not be loaded from .env and you have no $_ENV parameters in a worker.

You can bypass this problem by not loading the adapter ServerConstAdapter:

        $repository = RepositoryBuilder::createWithNoAdapters()
            ->addAdapter(EnvConstAdapter::class)
            ->immutable()
            ->make();

        $dotenv = Dotenv::create($repository, __DIR__);
        $dotenv->load();
Slamdunk commented 1 year ago

@steltner Would you be able to write a brief paragraph about this issue and propose a PR with it?

clwehunt commented 1 year ago

@steltner Would you be able to write a brief paragraph about this issue and propose a PR with it?

@steltner @Slamdunk Just following up on this issue if you have time. Thanks

clwehunt commented 1 year ago

Had the same problem, cost me a day of my life, the paratest worker has every ENV-parameter as $_SERVER parameter (I don't know why) and the ServerConstAdapter we use as default adapter by creating Dotenv with Dotenv::createImmutable(__DIR__) will return that every ENV-parameter is externally defined (see ImmutableWriter->isExternallyDefined($parameterName)) and so it will not be loaded from .env and you have no $_ENV parameters in a worker.

You can bypass this problem by not loading the adapter ServerConstAdapter:

        $repository = RepositoryBuilder::createWithNoAdapters()
            ->addAdapter(EnvConstAdapter::class)
            ->immutable()
            ->make();

        $dotenv = Dotenv::create($repository, __DIR__);
        $dotenv->load();

@steltner Thanks so much, In the meantime I have this workaround and it seems to be working ok.

leonardoldr23 commented 1 year ago

Any update on this? Due to the recent upgrade on Laravel and using Pest this behavior breaks our CI.

I would lovely send a PR with the fix, but unfortunately I really don't know even where to start here.

Slamdunk commented 1 year ago

but unfortunately I really don't know even where to start here

Without being able to reproduce the big, me neither

leonardoldr23 commented 1 year ago

At least the use case I can provide.

As it works from the common run and not in parallel, we assumed that might be a problem here, but can also be a problem on Pest or phpunit itself.

Slamdunk commented 1 year ago

@leonardoldr23 can you create a dedicated repository with the minimal code needed for the bug to raise, and instructions on how to expose it?

leonardoldr23 commented 1 year ago

@Slamdunk of course, here it is: https://github.com/leonardoldr23/envparatestshowcase

To run, clone/download then:

Afterwards, to reproduce the problem simply run this commands and you will see the issue:

I will send in attachment an image on the problem happening too: paratest-issue

As you can see, when using parallel the output keeps the ansii characters which are very bad on Jenkins (yeah, Jenkins should support them too :D)

Slamdunk commented 1 year ago

How are CLI flags associated with ENV variables?

leonardoldr23 commented 1 year ago

They are passed as $_SERVER variables just as like environments after the reading.

Slamdunk commented 1 year ago

Then that sounds unrelated to ParaTest, which never touches $_SERVER variable

leonardoldr23 commented 1 year ago

I don't remember why I came to relate with this issue exactly, but I showed the issue running at all, if you need I can open a new issue

Slamdunk commented 1 year ago

You showed the issue, but you didn't prove it's ParaTest fault and not, lets say, Pest or Laravel

leonardoldr23 commented 1 year ago

Ok, I really don't know how can I do it in any other way than showing that without paratest it works, and with paratests it not works. Just leave it be then, we will find another way or tool to parallelize the tests. Thanks for your time.

Slamdunk commented 1 year ago

showing that without paratest it works, and with paratests it not works

Pest overwrites many classes of ParaTest, so when you activate the --parallel flag it's not just ParaTest alone involved in the output. I suggest you to raise this issue in Pest.

github-actions[bot] commented 1 year ago

This issue has gone two months without activity. In another two weeks, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Backlog or In Progress, I will leave it alone ... forever!