Running PHPUnit tests in a WordPress plugin with Docker
Tags: wordpress, docker, phpunit, webdev
Published: 2020-04-26 10:38:39

---
title: Running PHPUnit tests in a WordPress plugin with Docker
published: true
date: 2020-04-25 15:16:24 UTC
tags: WordPress,Docker,phpunit,Web Development
canonical_url: https://carlosguzman.dev/running-phpunit-tests-in-a-wordpress-plugin-with-docker/
cover_image: https://carlosguzman.dev/wp-content/uploads/2020/04/running-phpunit-tests-in-a-wordpress-plugin-with-docker.jpg
---

There are several resource about running PHPUnit tests in a WordPress plugin with Docker. Here I want to share how I do it. You can find [the configuration files in Github](https://github.com/c4rlosguzm4n/wordpress-docker-dev-environment).

I explain how to create the development instance in 5 steps:

1. [The folder structure](#the-folder-structure)
2. [Build a docker image to host the WordPress site](#build-docker-image-for-wordpress-site)
3. [Configure the testing environment in your WordPress container](#configure-testing-environment-in-container)
4. [Docker compose to launch the containers](#docker-compose)
5. [Run tests while coding](#run-tests-while-coding)

## 1. The folder structure

Let’s start creating a folder to host all the docker configuration files and the WordPress code including the plugin source files.

[![project folder structure with configuration of wordpress and docker](https://carlosguzman.dev/wp-content/uploads/2020/04/console-project-wp-docker-1024x404.png)](https://carlosguzman.dev/wp-content/uploads/2020/04/console-project-wp-docker.png)<figcaption>How the folder will look at the end</figcaption>

This is a picture of how the folder will look at the end. _my-project_ is the root folder of the project. The _wordpress-image_ folder contains the Dockerfile and an the entry point script for the WordPress environment. The _wordpress_ folder contains the files of WordPress and the plugin to work on.

I use to run the wp-cli tool as the www-data user instead as root. So I assign www-data as group and my user as owner of the _wp-content_ folder inside the _wordpress_ folder. Then I give write access to the group to the _wp-content_ folder. In this way, www-data is able to write on those files without problem and I can edit the files from outside Docker with my user.

## 2. Build a docker image to host the WordPress site

I built a custom Docker image based on [the official Docker image for WordPress](https://hub.docker.com/_/wordpress/). The purpose of this custom image is to setup the development instance to run the unit tests automatically. This file is placed inside the _wordpress-image_ folder. Next is the Dockerfile of the image:

```
#1. Docker base image
FROM wordpress:php7.4-apache

#2. Install WP-cli and dependencies to run it
RUN apt-get update \
    && apt-get install -y \
      less \
      subversion \
      sudo \
      default-mysql-client-core \
    && curl https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar -o /usr/local/bin/wp \
    && chmod +x /usr/local/bin/wp

#3. Create the files for the testing environment
RUN \
    #3.1 Install phpunit
    curl -L https://phar.phpunit.de/phpunit-7.phar -o /tmp/phpunit \
    && chmod a+x /tmp/phpunit \
    #3.2 Install wordpress
    && cp -r /usr/src/wordpress /tmp/wordpress \
    && curl https://raw.github.com/markoheijnen/wp-mysqli/master/db.php -o /tmp/wordpress/wp-content/db.php \
    #3.3 Install the testing libraries
    && svn co --quiet https://develop.svn.wordpress.org/tags/5.3.2/tests/phpunit/includes/ /tmp/wordpress-tests-lib/includes \
    && svn co --quiet https://develop.svn.wordpress.org/tags/5.3.2/tests/phpunit/data/ /tmp/wordpress-tests-lib/data \
    #3.4 set owner and permissions
    && chown -R www-data:www-data /tmp/wordpress \
    && chown -R www-data:www-data /tmp/wordpress-tests-lib

#4. Copy the script to create the testing environment when the container is started
COPY init-testing-environment.sh /usr/local/bin/

#5. Run the script and send as an argument the command to run the apache service
ENTRYPOINT ["init-testing-environment.sh"]
CMD ["apache2-foreground"]

```

The section #1 in the Dockerfile shows the base image used. In this case the container will run WordPress in a Apache web server running PHP 7.4. You can see other options of [images for WordPress in Docker Hub](https://hub.docker.com/_/wordpress/).

The script installs [wp-cli](https://wp-cli.org/) in the section #2 . This tool is required to create the testing environment to run unit tests with WordPress easily. I run the wp-cli as the www-data user using the sudo package. Subversion downloads the testing libraries in the next section of the script. The mysql client package is used to check the connection to the database in the configuration of the testing environment later.

The section #3 creates the files for the testing environment. It is not required to download these files again when the container is started. In this way, there is a saving of data downloaded but mainly the container starts faster. It creates the WordPress instance for testing and download the libraries used by WordPress to run PHPUnit. This section does part of the job of `wp scaffold plugin-tests` which will be invoked when the container is launched.

In sections #4 and #5, the entry point script is copied and its parameters are configured. More about this script follows in the next section.

## 3. Configure the testing environment in your WordPress container

In the Dockerfile above, when the container starts, it runs a custom script instead running the Apache service. This script basically finishes the testing environment if it is not complete yet before launching the Apache service. This script is based on the steps to create [a testing environment in WordPress](https://make.wordpress.org/cli/handbook/plugin-unit-tests/) and it is placed inside the _wordpress-image_ folder.

```
#!/bin/bash

#1. check if the database is ready
cd /var/www/html/
if ! (sudo -u www-data -- wp db check)
then
	# wait a moment for the database container
	sleep 1
	exit 1;
fi

#2. check if wordpress is already installed/configured
if (sudo -u www-data -- wp core is-installed)
then
	#3. init the testing instance
	sudo -u www-data -- wp scaffold plugin-tests $WP_PLUGIN_FOLDER --force
	cd wp-content/plugins/$WP_PLUGIN_FOLDER && sudo -u www-data -- bash -c "./bin/install-wp-tests.sh $WP_TESTS_DB_NAME $WORDPRESS_DB_USER $WORDPRESS_DB_PASSWORD $WORDPRESS_DB_HOST latest true"	
fi

#4. back to the root WP folder
cd /var/www/html/

#5. execute the entrypoint of the parent image
bash docker-entrypoint.sh "$@"

```

In the section #1 of the script, it checks if the WordPress instance have connection to the database. If it is not the case, then it finish with error core but it sleeps for a bit first to give some time to the database to be ready.

The script checks if the WordPress instance is already configured in the section #2. The configuration of the testing environment requires the WordPress site to be already installed.<mark id="annotation-text-9033c2bc-0617-475d-a60a-4b642f573f86"></mark> If it is not active, then it skips the section #3 and launches the container.

The section #3 uses `wp scaffold plugin-tests` to create the configuration for the environment to run PHPUnit. One of the configuration files is install-wp-tests.sh. The install-wp-tests.sh script creates the WordPress instance in the tmp folder by default. I already created this instance in that folder in [the previous step](#build-docker-image-for-wordpress-site). The script doesn’t download the WordPress files again because the WordPress files are already in the folder. The docker compose file, explained in the next step, passes the values for the variables like _WP\_TEST\_DB\_NAME_ or _WORDPRESS\_DB\_USER_.

The last 2 sections in the script just move back to the main folder and executes the default entry point of the WordPress Docker image.

## 4. Docker compose to launch the containers

The next step is to create a docker file to run easily the backend and the database containers.

```
version: '3'

services:
    db:
        image: mysql:5.7
        volumes:
            - db-data:/var/lib/mysql
        ports:
            - "3360:3306"
        environment:
            MYSQL_ROOT_PASSWORD: password
            MYSQL_DATABASE: wordpress
            MYSQL_USER: wordpress
            MYSQL_PASSWORD: password

    wordpress:
        depends_on:
            - db
        build: ./wordpress-image
        ports:
            - 8080:80
        restart: on-failure
        volumes:
            - ./wordpress:/var/www/html
        environment:
            WORDPRESS_DB_HOST: db:3306
            WORDPRESS_DB_USER: wordpress
            WORDPRESS_DB_PASSWORD: password
            WORDPRESS_DB_NAME: wordpres
            WP_TESTS_DB_NAME: wptests
            WP_PLUGIN_FOLDER: my-plugin-folder

volumes:
    db-data:
```

The first service in the docker compose file launches the container for the database. It is based on the MySQL Docker image. The values for passwords, database and user names are values that you configure at your wish.

The second service is used for the WordPress container. It is based on the custom WordPress image that I created in [the step 2 explained previously](#build-docker-image-for-wordpress-site). This container uses a volume for the root folder of the WordPress instance. The values used to configure the database connection of the WordPress instance should match the values used for the database container. The official WordPress Docker image doesn’t use the variables _WP\_TEST\_DB\_NAME_ and _WP\_PLUGIN\_FOLDER_. [The script explained in the step 3](#configure-testing-environment-in-container) uses these custom variables. The first variable is the database name used to run the PHPUnit tests. The second variable is the name of the plugin folder under development and testing.

Last to highlight is the directive _restart_ with value on-failure that allows this container to try to be launched again if the script to create the testing instance fails or if there is another problem starting the container. In example, if the database is not ready as we saw in [the previous step](#configure-testing-environment-in-container).

## 5. Run tests while coding

The development and testing environment is ready after all this configuration. First go to the project folder and lunch the containers using `docker-composer up`. The testing environment will not be configured until you have configured the WordPress site. After lunching the containers by first time, you would need to visit _localhost:8080_ in your browser to setup the WordPress site.

The next time you lunch your container, if you have already setup the WordPress site, then the testing environment will be configured automatically. Then you need a bash session in the WordPress container to run the tests:

![bash session in the docker container](https://carlosguzman.dev/wp-content/uploads/2020/04/docker-wp-plugin-environment-bash-1024x556.png)<figcaption>Bash session in the WordPress container</figcaption>

An alternative is to use composer and install PHPUnit in the plugin’s source code. In the [step 2](#build-docker-image-for-wordpress-site), I already downloaded it and place it in the _tmp_ folder:

![PHPUnit tests in a WordPress plugin with Docker](https://carlosguzman.dev/wp-content/uploads/2020/04/docker-wp-plugin-environment-run-tests-1024x556.png)<figcaption>PHPUnit tests results</figcaption>

If you want to run your tests automatically while you are coding, you could take a look to a previous article where I explain [how to run tests automatically using the bash script watch-and-do](https://carlosguzman.dev/running-phpunit-tests-automatically/).

So this is the way I run PHPUnit tests in a WordPress plugin with Docker. You can find [these configuration files in Github](https://github.com/c4rlosguzm4n/wordpress-docker-dev-environment).

The post [Running PHPUnit tests in a WordPress plugin with Docker](https://carlosguzman.dev/running-phpunit-tests-in-a-wordpress-plugin-with-docker/) appeared first on [Carlos Guzman](https://carlosguzman.dev).