Welcome to Abdul Malik Ikhsan's Blog

How to Avoid –stderr When Running phpunit for Functional/Integration Testing

Posted in Teknologi, testing by samsonasik on March 3, 2020

When you do a Functional/Integration test with session and/or header relation. It will force you to use --stderr when running phpunit, or it will got error, eg: you’re testing that on logout when session exists as user, page will be redirected to login page with status code 302, and it got the following error:

$ vendor/bin/phpunit test/Integration/LogoutPageTest.php
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

Logout Page (AppTest\Integration\LogoutPage)
 ✘ Open logout page as auser redirect to login page
   ├ Failed asserting that 500 matches expected 302.
   ╵ /Users/samsonasik/www/mezzio-authentication-with-authorization/test/Integration/LogoutPageTest.php:36

Time: 155 ms, Memory: 10.00 MB

Tests: 1, Assertions: 1, Failures: 1.

You can use --stderr option on running it:

$ vendor/bin/phpunit test/Integration/LogoutPageTest.php --stderr
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

Logout Page (AppTest\Integration\LogoutPage)
 √ Open logout page as auser redirect to login page

Time: 150 ms, Memory: 8.00 MB

OK (1 test, 2 assertions)

or define stderr=true in phpunit.xml configuration:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    <!-- testsuites, filter, etc config -->   


Marking all test to be using stderr is a workaround, as not all tests actually require that, eg: unit test doesn’t need that. To avoid it, we can define @runTestsInSeparateProcesses and @preserveGlobalState disabled in the controller class that require that, so, the test class will be like the following:



namespace AppTest\Integration;

use Laminas\Diactoros\ServerRequest;
use Laminas\Diactoros\Uri;
use Mezzio\Authentication\UserInterface;
use PHPUnit\Framework\TestCase;

 * @runTestsInSeparateProcesses
 * @preserveGlobalState disabled
class LogoutPageTest extends TestCase
    private $app;

    protected function setUp(): void
        $this->app = AppFactory::create();

    public function testOpenLogoutPageAsAuserRedirectToLoginPage()
        $sessionData                    = [
            'username' => 'samsonasik',
            'roles'    => [
        $_SESSION[UserInterface::class] = $sessionData;

        $uri           = new Uri('/logout');
        $serverRequest = new ServerRequest([], [], $uri);

        $response = $this->app->handle($serverRequest);
        $this->assertEquals(302, $response->getStatusCode());
        $this->assertEquals('/login', $response->getHeaderLine('Location'));

That’s it!

Publish Test Coverage to Codecov from Github Actions

Posted in testing by samsonasik on February 26, 2020

Code Coverage

Github Actions is one of ways to run Continues Integration. For Coverage report, we can use Codecov to publish the coverage result after running and generating test coverage.

For example, you have a Github Repository. You can open https://codecov.io/login and choose “Github”:

After you logged in, you can choose repository, or directly access https://codecov.io/gh/{your github user}/{your github repo}, for example, I use “samsonasik” as user, and “mezzio-authentication-with-authorization” as repository name:


On very first, we need to activate Webhook by open https://codecov.io/gh/gh/{your github user}/{your github repo}/settings, for example:


Then, we click “Create new webhook” under Github Webhook:

After it done, we can copy “Repository Upload Token”:

by click “Copy” after then token, and back to Github, and save to Secrets section under Your Github Repository Settings with click “Add a new secret”, with eg: named: CODECOV_TOKEN, fill the value with your copied token, and click “Add secret” to save it to be like as follow:

The preparation is done. Now, time to add the github workflow, eg: “.github/workflows/ci-build.yml” at your repository, eg for php package/project and use phpunit, the workflow can be like the following:

name: "ci build"

      - "master"

    name: PHP ${{ matrix.php-versions }}
    runs-on: ubuntu-latest
      fail-fast: false
        php-versions: ['7.2', '7.3', '7.4']
      - name: Setup PHP Action
        uses: shivammathur/setup-php@1.8.2
          extensions: intl
          php-version: "${{ matrix.php-versions }}"
          coverage: pcov
      - name: Checkout
        uses: actions/checkout@v2
      - name: "Validate composer.json and composer.lock"
        run: "composer validate"
      - name: "Install dependencies"
        run: "composer install --prefer-dist --no-progress --no-suggest && composer development-enable"
      - name: "Run test suite"
        run: "vendor/bin/phpunit --coverage-clover=coverage.xml"
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v1
          token: ${{ secrets.CODECOV_TOKEN }}
          file: ./coverage.xml
          flags: tests
          name: codecov-umbrella
          yml: ./codecov.yml
          fail_ci_if_error: true

That’s it. To trigger the Continues Integration, we can push a commit to the repository.

When its succeed (ci build green), we can then display coverage badge, eg at README.md like the following:

[![Code Coverage](https://codecov.io/gh/{your github user}/{your github repo}/branch/master/graph/badge.svg)](https://codecov.io/gh/{your github user}/{your github repo})

that will show:

Code Coverage