Laravel - Test code execution results depend on how you handle the cache.
Tags: laravel
Published: 2022-03-20 12:50:05

To execute test code in Laravel, those are essential that you have to know about otherwise, you might waste your time.  
"Referencing values from '.env' when the config is cached before test execution."  
"Referencing values from 'phpunit.xml' when the config isn't cached before test execution."  

Here is the example.  

### tests/Sample01Test.php
This is a test code.  
```php
    public function testPrueba01()
    {
        $token = config('docurain.token');
        echo "===================================" . PHP_EOL;
        echo "token:{$token}" . PHP_EOL;
        echo "===================================" . PHP_EOL;
    }
```

### config/docurain.php
This is the config file that is loading .env.  
```php
return [
    'token' => env('DOCURAIN_TOKEN'),
];
```

### .env
DOCURAIN_TOKEN is an access token. By the way, it is a value prepared randomly.  
```.env
DOCURAIN_TOKEN=FohVai3zei7dei8zainanuaphohqu5uz1Goh9aiy
```

### phpunit.xml
```xml
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="MAIL_MAILER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="TELESCOPE_ENABLED" value="false"/>
    </php>
```

When you execute this code, the result depends on whether config is cached before execution or not.  


## When cache the config
Execution command  
```
php artisan config:clear | php artisan config:cache
php artisan test tests/Sample01Test.php
```
Execution result  
```
===================================
token:FohVai3zei7dei8zainanuaphohqu5uz1Goh9aiy
===================================
```

## When not cache the config
Execution command  
```
php artisan config:clear
php artisan test tests/Sample01Test.php
```
Execution result  
```
===================================
token:
===================================
```

## What's happened
When caching the config, it is referring to the value of 'DOCURAIN_TOKEN' in .env.  

When the config is not cached, it is referring to the value of 'server name ="DOCURAIN_TOKEN"' in phpunit.xml  
However, in the above case, there is no such value in phpunit.xml, so, an empty value is output.  

## solution 1. Add to phpunit.xml　
For example, like this.  
```xml
    <php>
        <server name="DOCURAIN_TOKEN" value="FohVai3zei7dei8zainanuaphohqu5uz1Goh9aiy"/>
    </php>
```
There is no problem if the information is not important.  
However, sensitive information such as access tokens should not be included.  

First of all, the token is duplicated in two places. From that point of view, this is not a good method.  

It can be solved, but it is uncomfortable.  
I would prefer different method.  

Another idea is to "always cache the config and set the value of .env when running the test".  
It is nonsense not to refer to the data in phpunit.xml when running the test.  


## solution 2. Limit the scope of test code execution.(Separate from CI/CD)
If the test code is embedded in CI/CD and executed, the execution command would look like this.  
```
php artisan test
```
When dividing by unit test and functional test, it looks like this.  
```
php artisan test tests/Unit
php artisan test tests/Feature
```

phpunit.xml looks like this.  

### phpunit.xml
```xml
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
```

In this case, the target of test code execution is the following directory.  
```
/tests/Unit/*  
/tests/Feature/*  
```

Tests that require some values that you need to get from .env but don't want to include them in phpunit.xml(Access token for service, etc.) should be saved in a location separate from the above directories.   
For example:
```
/tests/Docurain/EstimateTestExtra.php  
```

The only case you have to be aware of these is when you need access to an external service and need information such as tokens and secret keys.  

However, there are many cases where it is better to be careful when integrating them into CI/CD, because the number of accesses is limited and the amount price depends on the number of accesses.  

So, it's better to separate it from CI/CD and run the test manually or run it in a different section from the normal flow.

## Remark
Japanese version　　
https://kaki-engine.com/laravel-test-code-execution-results-depend-on-how-you-handle-the-cache/