ergebnis/environment-variables

Provides an abstraction for environment variables.

1.6.0 2024-11-18 11:43 UTC

README

Integrate Merge Release Renew

Code Coverage

Latest Stable Version Total Downloads Monthly Downloads

This project provides a composer package with an abstraction of environment variables.

Installation

Run

composer require ergebnis/environment-variables

Usage

This package provides the interface Ergebnis\Environment\Variables along with the following production implementations:

This package also provides the following test implementations:

Production Implementation

Ergebnis\Environment\SystemVariables

If you want to read, set, and unset environment variables in an object-oriented way in a production environment, you can use Ergebnis\Environment\SystemVariables:

<?php

declare(strict_types=1);

use Ergebnis\Environment;

final class BuildEnvironment
{
    private Environment\Variables $environmentVariables;

    public function __construct(Environment\Variables $environmentVariables)
    {
        $this->environmentVariables = $environmentVariables;
    }

    public function isGitHubActions(): bool
    {
        return $this->environmentVariables->has('GITHUB_ACTIONS')
            && 'true' === $this->environmentVariables->get('GITHUB_ACTIONS');
    }

    public function isTravisCi(): bool
    {
        return $this->environmentVariables->has('TRAVIS')
            && 'true' === $this->environmentVariables->get('TRAVIS');
    }
}

Test Implementation

Ergebnis\Environment\FakeVariables

If you want to read, set, and unset environment variables in an object-oriented way in a test environment, but do not actually want to modify system environment variables, you can use Ergebnis\Environment\FakeVariables as a test-double:

<?php

declare(strict_types=1);

use Ergebnis\Environment;
use PHPUnit\Framework;

final class BuildEnvironmentTest extends Framework\TestCase
{
    public function testIsGitHubActionsReturnsFalseWhenNoneOfTheExpectedEnvironmentVariablesAreAvailable(): void
    {
        $environmentVariables = Environment\FakeVariables::empty();

        $buildEnvironment = new BuildEnvironment($environmentVariables);

        self::assertFalse($buildEnvironment->isGitHubActions());
    }

    public function testIsGitHubActionsReturnsFalseWhenValueOfGitHubActionsEnvironmentVariableIsNotTrue(): void
    {
        $environmentVariables = Environment\FakeVariables::fromArray([
            'GITHUB_ACTIONS' => 'false',
        ]);

        $buildEnvironment = new BuildEnvironment($environmentVariables);

        self::assertFalse($buildEnvironment->isGitHubActions());
    }

    public function testIsGitHubActionsReturnsTrueWhenValueOfGitHubActionsEnvironmentVariableIsTrue(): void
    {
        $environmentVariables = Environment\FakeVariables::fromArray([
            'GITHUB_ACTIONS' => 'true',
        ]);

        $buildEnvironment = new BuildEnvironment($environmentVariables);

        self::assertTrue($buildEnvironment->isGitHubActions());
    }
}

Ergebnis\Environment\ReadOnlyVariables

If you want to read environment variables in an object-oriented way in a test environment, but neither actually want to modify system environment variables, nor allow modification by the system under test, you can use Ergebnis\Environment\ReadOnlyVariables as a test-double:

<?php

declare(strict_types=1);

use Ergebnis\Environment;
use PHPUnit\Framework;

final class BuildEnvironmentTest extends Framework\TestCase
{
    public function testIsGitHubActionsReturnsFalseWhenNoneOfTheExpectedEnvironmentVariablesAreAvailable(): void
    {
        $environmentVariables = Environment\ReadOnlyVariables::empty();

        $buildEnvironment = new BuildEnvironment($environmentVariables);

        self::assertFalse($buildEnvironment->isGitHubActions());
    }

    public function testIsGitHubActionsReturnsFalseWhenValueOfGitHubActionsEnvironmentVariableIsNotTrue(): void
    {
        $environmentVariables = Environment\ReadOnlyVariables::fromArray([
            'GITHUB_ACTIONS' => 'false',
        ]);

        $buildEnvironment = new BuildEnvironment($environmentVariables);

        self::assertFalse($buildEnvironment->isGitHubActions());
    }

    public function testIsGitHubActionsReturnsTrueWhenValueOfGitHubActionsEnvironmentVariableIsTrue(): void
    {
        $environmentVariables = Environment\ReadOnlyVariables::fromArray([
            'GITHUB_ACTIONS' => 'true',
        ]);

        $buildEnvironment = new BuildEnvironment($environmentVariables);

        self::assertTrue($buildEnvironment->isGitHubActions());
    }
}

💡 The ReadOnlyVariables implementation will throw a ShouldNotBeUsed exception when the system under tests uses any of the following methods:

  • set()
  • unset()

Ergebnis\Environment\TestVariables

If your tests depend on environment variables, you have the following challenges:

  • when you modify environment variables in a test, you want to restore environment variables that have existed before the test run to their original values
  • when you modify environment variables in a test that has not been backed up before, and forget to restore it, it might affect other tests

To solve this problem, you can add the @backupGlobals annotation to your test cases when using phpunit/phpunit, or use Ergebnis\Environment\TestVariables:

<?php

declare(strict_types=1);

use Ergebnis\Environment;
use PHPUnit\Framework;

final class FooTest extends Framework\TestCase
{
    private static Environment\TestVariables $environmentVariables;

    protected function setUp() : void
    {
        // will back up environment variables FOO, BAR, and BAZ
        self::$environmentVariables = Environment\TestVariables::backup(
            'FOO',
            'BAR',
            'BAZ'
        );
    }

    protected function tearDown() : void
    {
        // will restore backed-up environment variables FOO, BAR, and BAZ to their initial state
        self::$environmentVariables->restore();
    }

    public function testSomethingThatDependsOnEnvironmentVariableFooToBeSet(): void
    {
        self::$environmentVariables->set(
            'FOO',
            '9000'
        );

        // ...
    }

    public function testSomethingThatDependsOnEnvironmentVariableFooToBeUnset(): void
    {
        self::$environmentVariables->unset('FOO');

        // ...
    }

    public function testSomethingThatDependsOnEnvironmentVariableQuxToBeSet(): void
    {
        // will throw exception because the environment variable QUX has not been backed up
        self::$environmentVariables->set(
            'QUX',
            '9000'
        );

        // ...
    }

    public function testSomethingThatDependsOnEnvironmentVariableQuxToBeUnset(): void
    {
        // will throw exception because the environment variable QUX has not been backed up
        self::$environmentVariables->unset('QUX');
    }
}

Changelog

The maintainers of this project record notable changes to this project in a changelog.

Contributing

The maintainers of this project suggest following the contribution guide.

Code of Conduct

The maintainers of this project ask contributors to follow the code of conduct.

General Support Policy

The maintainers of this project provide limited support.

You can support the maintenance of this project by sponsoring @localheinz or requesting an invoice for services related to this project.

PHP Version Support Policy

This project supports PHP versions with active and security support.

The maintainers of this project add support for a PHP version following its initial release and drop support for a PHP version when it has reached the end of security support.

Security Policy

This project has a security policy.

License

This project uses the MIT license.

Social

Follow @localheinz and @ergebnis on Twitter.