How to run PHPUnit with a database via GitHub Actions

As of March 2020, GitHub seems to remove the default MySQL installation from its ubuntu-latest container. Now it’s required to set up the database service in order to use it.

Because we at BracketSpace are testing our WordPress plugins with PHPUnit it’s required to run them along with the database.

Let me show you how to set up the GitHub workflow file to use multiple PHP versions.

name: Test

on: push

jobs:
  phpunit:
    name: PHPUnit
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php: ['7.0', '7.1', '7.2', '7.3', '7.4']
    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        ports:
          - 3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
    steps:
    - name: Checkout
      uses: actions/[email protected]
    - name: Install Composer dependencies
      run: composer install -o --no-progress
    - name: Setup PHP
      uses: shivammathur/[email protected]
      with:
        php-version: ${{ matrix.php }}
        extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, mysql, mysqli, pdo_mysql, bcmath, soap, intl, gd, exif, iconv, imagick
        coverage: none
    - name: PHPUnit
      run: |
        bin/install-wp-tests.sh wordpress_test root root 127.0.0.1:${{ job.services.mysql.ports['3306'] }} latest true
        vendor/bin/phpunit

A couple of things to keep in mind:

  • MYSQL_DATABASE env variable will setup the database on startup
  • You have to install Composer dependencies before setting the PHP version or extract the build process to a separate job. Otherwise, make sure the Composer will install or add --ignore-platform-reqs
  • You have to connect to MySQL at 127.0.0.1 instead localhost. Otherways it may try to connect via socket, which won’t be available
  • GitHub randomly assigns the external port for services, access it with ${{ job.services.mysql.ports['3306'] }}

6 Comments

  • Thanks for the post, but I am getting this error on GitHub, not sure yet why:
    “The workflow is not valid. The workflow must contain at least one job with no dependencies.”

    • I fixed commenting the `needs: build` line. But then I got a different error on PHPUnit: `vendor/bin/phpunit: No such file or directory`. That’s because this line tells composer to run on production mode ignoring dev dependencies, but the problem is that phpunit is a “dev” dependency, rendering to not being installed. To fix it, I changed the composer line to: `composer install -o –no-progress`.

      Please note that having phpunit as a production dependency and sending it to WP’s directory leads to a huge security vulnerability, as it contains files that allow remote execution. Not saying is the case here, just a heads up to readers.

  • Do you maybe also have a sample plugin where this is all been setup correctly. I’m trying to get a head start reviving my old svrooij/rest-api-filter-fields plugin on github. Going forward and adding automated tests seems like a good thing to do.

  • Hello,
    I’m trying to implement tests and I’m stuck with:
    “`
    Warning: arning] Using a password on the command line interface can be insecure.
    ERROR 2003 (HY000): Can’t connect to MySQL server on ‘localhost:3306’ (111)
    + ‘[‘ ‘]’
    + create_db
    + mysqladmin create wordpress_test –user=root –*** –host=localhost –protocol=tcp
    Warning: n: [Warning] Using a password on the command line interface can be insecure.
    mysqladmin: connect to server at ‘localhost’ failed
    error: ‘Can’t connect to MySQL server on ‘localhost:3306′ (111)’
    Check that mysqld is running on localhost and that the port is 3306.
    You can check this by doing ‘telnet localhost 3306’
    Error: The operation was canceled.
    “`
    Do you have any idea to help me solving this?

    Thank you.

Your email address will not be published.