Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Setup PHPUnit for use in the Local by Flywheel app
#!/usr/bin/env bash
# ===============================================================================
# Script to install PHPUnit in the Local by Flywheel Mac app
# These packages are installed
#
# PHPUnit, curl wget, rsync, git, subversion and composer.
#
# WordPress is installed in the `/tmp/wordpress` directory for use by PHPUnit.
# The WordPress test suite is installed in the `/tmp/wordpress-tests-lib` directory.
#
# The WordPress and WP Test Suite paths are added to the ~/.bashrc file as environment
# variables $WP_CORE_DIR and $WP_TESTS_DIR.
#
# That way plugins can make use of them for unit testing. Plugins that have their
# tests scaffolded by WP-CLI also makes use of them. VVV also adds these enviroment
# variables to the ~/.bashrc file by default.
#
# You only have to run this script once. PHPUnit (and the other packages) are
# still available next time you ssh into your site.
#
# To update WordPress and the WP Test Suite re-run this script.
# Use options to install specific versions for PHPUnit, WordPress or the WP_UnitTestCase.
#
# Note: This script doesn't install the packages globally in the Local by Flywheel app
# Packages are only installed for the site where you've run this script.
# ===============================================================================
# ===============================================================================
# Instructions
#
# 1 - Download this file (setup-phpunit.sh) inside your site's /app folder
# curl -o setup-phpunit.sh https://gist.githubusercontent.com/keesiemeijer/a888f3d9609478b310c2d952644891ba/raw/
#
# 2 - Right click your site in the Local App and click Open Site SSH
# A new terminal window will open
#
# 3 - Go to your site's /app folder:
# cd /app
#
# 4 - Run this script
# bash setup-phpunit.sh
#
# 5 - Reload the .bashrc file
# source ~/.bashrc
#
# 6 - Check if PHPUnit is installed
# phpunit --version
#
# ===============================================================================
# ===============================================================================
# Options
#
# Without options this script installs/updates PHPUnit, WordPress and the WP test suite.
#
# Install a specific PHPUnit version with the --phpunit-version option.
#
# bash setup-phpunit.sh --phpunit-version=7
#
# Install a specific WordPress version with the --wp-version option. This option
# accepts a version number, 'latest', 'trunk' or 'nightly'. Default 'latest'
#
# bash setup-phpunit.sh --wp-version=5.0
#
# Install a specific WordPress Test Suite with the --wp-ts-version option. This option
# accepts a version number, 'latest', 'trunk' or 'nightly'. Default 'latest'
#
# bash setup-phpunit.sh --wp-ts-version=trunk
#
# Update all packages (wget, curl etc) installed by this script with the --update-packages option.
#
# bash setup-phpunit.sh --update-packages
#
# Use the --help or -? option to see more information about this script.
#
# bash setup-phpunit.sh --help
#
# ===============================================================================
# ===============================================================================
# Default PHPUnit version
#
# PHPUnit version 6 is installed for PHP version 7.*
# PHPUnit version 4 for all other PHP versions
#
# See ticket https://core.trac.wordpress.org/ticket/39822
# See ticket https://core.trac.wordpress.org/ticket/43218
#
# Run the command with a version if you need to test with a specific PHPUnit version
#
# bash setup-phpunit.sh --phpunit-version=7
#
# This example will install the latest PHPUnit from version 7 (e.g. 7.5.3)
# Available versions can be found here: https://phar.phpunit.de
#
# ===============================================================================
# Strings used in error messages.
readonly QUIT="Stopping script..."
readonly CONNECTION="Make sure you're connected to the internet."
readonly RED='\033[0;31m' # Red color.
readonly RESET='\033[0m' # No color.
# Functions
function download() {
download=false
if wget --spider "$1" >/dev/null 2>&1; then
wget -q --show-progress -O "$2" "$1" && download=true
# Check if file exists.
if [[ -f "$2" && "$download" = true ]]; then
return 0
fi
fi
printf "${RED}WARNING${RESET} Could not download %s %s\n" "$1" "$CONNECTION"
return 1
}
function download_test_suite() {
local exit=0
if wget --spider "https://develop.svn.wordpress.org/$1/tests/phpunit/includes/" >/dev/null 2>&1; then
svn export --quiet --force "https://develop.svn.wordpress.org/$1/tests/phpunit/includes/" "/tmp/tmp-wordpress-tests-lib/includes/"
svn export --quiet --force "https://develop.svn.wordpress.org/$1/tests/phpunit/data/" "/tmp/tmp-wordpress-tests-lib/data/"
svn export --quiet --force "https://develop.svn.wordpress.org/$1/wp-tests-config-sample.php" "/tmp/tmp-wordpress-tests-lib/wp-tests-config.php"
for path in includes data wp-tests-config.php; do
# Check if path exists.
[[ ! -e "/tmp/tmp-wordpress-tests-lib/$path" ]] && exit=1
done
if [[ 0 = "$exit" ]]; then
return 0
fi
fi
printf "${RED}WARNING${RESET} Could not download %s Test Suite. %s\n" "$2" "$CONNECTION"
return 1
}
function packages_installed() {
for file in /usr/bin/wget /usr/bin/curl /usr/bin/svn /usr/bin/rsync /usr/local/bin/composer /usr/bin/git; do
# Check if executable file.
if ! [[ -f "$file" && -x "$file" ]]; then
return 1
fi
done
return 0
}
function clean_up_temp_files() {
# Clean up files added by this script.
[[ -d "/tmp/tmp-wordpress/" ]] && rm -rf "/tmp/tmp-wordpress/"
[[ -d "/tmp/tmp-wordpress-tests-lib/" ]] && rm -rf "/tmp/tmp-wordpress-tests-lib/"
[[ -f "/tmp/my.cnf" ]] && rm -f "/tmp/my.cnf"
}
function exit_script() {
clean_up_temp_files
exit 1
}
# Get arguments.
for arg in "$@"
do
if [[ "$arg" =~ ^- ]]; then
# Argument start with a dash.
case "$arg" in
--phpunit-version=*) PHPUNIT_VERSION=${arg#"--phpunit-version="};;
--wp-version=*) WP_VERSION=${arg#"--wp-version="};;
--wp-ts-version=*) WP_TS_VERSION=${arg#"--wp-ts-version="};;
--update-packages*) UPDATE_PACKAGES=true;;
-?|--help)
printf "Install PHPUnit in the Local by Flywheel Mac app\n\n"
printf "Usage:\n"
printf "\tbash setup-phpunit.sh [option...]\n\n"
printf "Example:\n"
printf "\tbash setup-phpunit.sh --phpunit-version=6 --wp-version=trunk\n\n"
printf "Options:\n"
printf -- "\t--phpunit-version PHPUnit version to install\n"
printf -- "\t--wp-version WordPress version to install\n"
printf -- "\t Accepts a version number, 'latest', 'trunk' or 'nightly'. Default 'latest'\n"
printf -- "\t--wp-ts-version WordPress Test Suite version to install\n"
printf -- "\t Accepts a version number, 'latest', 'trunk' or 'nightly'. Default --wp-version option\n"
printf -- "\t--update-packages Update all packages installed by this script\n"
printf -- "\t Updates curl wget, rsync, git, subversion and composer\n"
printf -- "\t-?|--help Display information about this script\n\n"
exit 0
;;
*)
printf "Unknown option: %s.\nUse \"bash setup-phpunit.sh --help\" to see all options\n%s\n" "$arg" "$QUIT_MSG"
exit_script
;;
esac
else
# Argument doesn't start with a dash.
printf "Unknown option: %s.\nUse \"bash setup-phpunit.sh --help\" to see all options\n%s\n" "$arg" "$QUIT_MSG"
exit_script
fi
done
INSTALL_PACKAGES=false
if ! packages_installed; then INSTALL_PACKAGES=true; fi
[[ -z "$UPDATE_PACKAGES" ]] && UPDATE_PACKAGES=false
if [[ "$INSTALL_PACKAGES" = true || "$UPDATE_PACKAGES" = true ]]; then
[[ "$INSTALL_PACKAGES" = true ]] && printf "Installing packages...\n" || printf "Updating packages...\n"
# Re-synchronize the package index files from their sources.
apt-get update -y
# Install packages.
apt-get install -y wget subversion curl git rsync
# Install composer.
if [[ -f "/usr/bin/curl" && ! -f "/usr/local/bin/composer" ]]; then
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer || exit
if [[ -f "$HOME/.bashrc" ]]; then
printf "Adding .composer/vendor/bin to the PATH\n"
echo 'export PATH="$PATH:$HOME/.composer/vendor/bin"' >> "$HOME/.bashrc"
fi
else
if [[ -f "/usr/local/bin/composer" ]]; then
printf "Updating composer...\n"
composer self-update || printf "${RED}WARNING${RESET} Could not update composer. %s\n" "$CONNECTION"
fi
fi
fi
# Re-check if all packages are installed.
if ! packages_installed; then
printf "${RED}ERROR${RESET} Missing packages. %s\n%s\n" "$CONNECTION" "$QUIT"
exit_script
fi
# Get the current PHP version.
readonly PHP_VERSION=$(php -r "echo PHP_VERSION;")
# Set the PHPUnit version if needed.
if [[ -z "$PHPUNIT_VERSION" ]]; then
# PHPUnit version 6 for PHP version 7+
PHPUNIT_VERSION=6
if [[ ${PHP_VERSION:0:2} = "5." ]]; then
# PHPUnit version 4 for PHP version lower than 7.
PHPUNIT_VERSION="4"
fi
fi
readonly PHPUNIT_VERSION="$PHPUNIT_VERSION"
# Install PHPUnit.
printf "Installing PHPUnit %s... \n" "$PHPUNIT_VERSION"
if download "https://phar.phpunit.de/phpunit-$PHPUNIT_VERSION.phar" "phpunit-$PHPUNIT_VERSION.phar"; then
chmod +x "phpunit-$PHPUNIT_VERSION.phar"
mv "phpunit-$PHPUNIT_VERSION.phar" /usr/local/bin/phpunit
else
printf "%s\n" "$QUIT"
exit_script
fi
# Set WordPress environment variables.
if [[ -f "$HOME/.bashrc" ]]; then
# Get the variables.
source "$HOME/.bashrc"
if [[ -z "${WP_TESTS_DIR}" ]]; then
printf "Setting WP_TESTS_DIR environment variable\n"
echo 'export WP_TESTS_DIR=/tmp/wordpress-tests-lib' >> "$HOME/.bashrc"
fi
if [[ -z "${WP_CORE_DIR}" ]]; then
printf "Setting WP_CORE_DIR environment variable\n"
echo 'export WP_CORE_DIR=/tmp/wordpress' >> "$HOME/.bashrc"
fi
# Get the new variables.
source "$HOME/.bashrc"
fi
if [[ -z "$WP_CORE_DIR" || -z "$WP_TESTS_DIR" ]]; then
printf "${RED}ERROR${RESET} The WordPress directories for PHPUnit are not set\n%s\n" "$QUIT"
exit_script
fi
# Delete tmp files (if they exist).
clean_up_temp_files
# Create tmp directories.
mkdir "/tmp/tmp-wordpress/" || exit
mkdir "/tmp/tmp-wordpress-tests-lib/" || exit
# Create core and tests directories (if needed).
[[ -d "$WP_CORE_DIR" ]] || mkdir "$WP_CORE_DIR" || exit
[[ -d "$WP_TESTS_DIR" ]] || mkdir "$WP_TESTS_DIR" || exit
cd "$WP_CORE_DIR" || exit
# Set default WordPress version.
[[ -z "$WP_VERSION" ]] && WP_VERSION='latest'
# Get the latest WordPress version from API.
readonly WP_LATEST=$(wget -q -O - "http://api.wordpress.org/core/version-check/1.5/" | head -n 4 | tail -n 1);
if [[ 'latest' = "$WP_VERSION" ]]; then
WP_VERSION="$WP_LATEST"
if [[ -z "$WP_LATEST" ]]; then
printf "${RED}ERROR${RESET} Could not get latest WordPress version from api.wordpress.org. %s\n%s\n" "$CONNECTION" "$QUIT"
exit_script
fi
fi
# Set WordPress version.
readonly WP_VERSION="$WP_VERSION"
# Set default test suite version.
[[ -z "$WP_TS_VERSION" ]] && WP_TS_VERSION="$WP_VERSION"
# Install WordPress.
if [[ 'trunk' = "$WP_VERSION" ]]; then
printf "Installing WordPress trunk... \n"
svn export --quiet --force "https://develop.svn.wordpress.org/trunk/src/" "/tmp/tmp-wordpress/"
rsync -a --delete "/tmp/tmp-wordpress/" "$WP_CORE_DIR"
elif [[ 'nightly' = "$WP_VERSION" ]]; then
printf "Installing WordPress nightly... \n"
if download "https://wordpress.org/nightly-builds/wordpress-latest.zip" "/tmp/wordpress-latest.zip"; then
unzip -o -q "/tmp/wordpress-latest.zip" -d "/tmp/tmp-wordpress/"
rsync -a --delete "/tmp/tmp-wordpress/wordpress/" "$WP_CORE_DIR"
fi
else
printf "Installing WordPress %s... \n" "$WP_VERSION"
if download "https://wordpress.org/wordpress-$WP_VERSION.tar.gz" "/tmp/wordpress.tar.gz"; then
tar --strip-components=1 -zxmf "/tmp/wordpress.tar.gz" -C "/tmp/tmp-wordpress/"
rsync -a --delete "/tmp/tmp-wordpress/" "$WP_CORE_DIR"
fi
fi
if [[ 'trunk' = "$WP_TS_VERSION" || 'nightly' = "$WP_TS_VERSION" ]]; then
TS_ARCHIVE="trunk"
elif [[ $WP_TS_VERSION = 'latest' ]]; then
TS_ARCHIVE="tags/$WP_LATEST"
WP_TS_VERSION="$WP_LATEST"
else
TS_ARCHIVE="tags/$WP_TS_VERSION"
fi
# Install WP test suite.
printf "Installing WordPress %s Test Suite...\n" "$WP_TS_VERSION"
if download_test_suite "$TS_ARCHIVE" "$WP_TS_VERSION"; then
rsync -a --delete "/tmp/tmp-wordpress-tests-lib/" "$WP_TESTS_DIR"
else
if [[ 'trunk' = "$TS_ARCHIVE" ]]; then
printf "%s\n" "$QUIT"
exit_script
fi
printf "Installing Test Suite from trunk...\n"
if download_test_suite "trunk" "trunk"; then
rsync -a --delete "/tmp/tmp-wordpress-tests-lib/" "$WP_TESTS_DIR"
else
printf "%s\n" "$QUIT"
exit_script;
fi
fi
# Update credentials in the wp-tests-config.php file.
if [[ -f "$WP_TESTS_DIR/wp-tests-config.php" ]]; then
printf "Updating wp-tests-config-sample.php...\n"
if [[ $(uname -s) == 'Darwin' ]]; then
ioption='-i .bak'
else
ioption='-i'
fi
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR/wp-tests-config.php"
sed $ioption "s/youremptytestdbnamehere/wordpress_test/" "$WP_TESTS_DIR/wp-tests-config.php"
sed $ioption "s/yourusernamehere/root/" "$WP_TESTS_DIR/wp-tests-config.php"
sed $ioption "s/yourpasswordhere/root/" "$WP_TESTS_DIR/wp-tests-config.php"
fi
# Install database if it doesn't exist.
printf "Checking if database wordpress_test exists\n"
# Suppress password warnings. It silly I know :-)
printf "[client]\npassword=root\nuser=root" > "/tmp/my.cnf"
database=$(mysqlshow --defaults-file="/tmp/my.cnf" wordpress_test | grep -v Wildcard | grep -o wordpress_test)
if ! [[ "wordpress_test" = "$database" ]]; then
printf "Creating database wordpress_test\n"
mysqladmin --defaults-file="/tmp/my.cnf" create "wordpress_test" --host="localhost"
else
printf "Database wordpress_test already exists\n"
fi
if [[ -f "$WP_TESTS_DIR/wp-tests-config.php" ]]; then
# VVV has the tests config outside the $WP_TESTS_DIR dir.
cp "$WP_TESTS_DIR/wp-tests-config.php" "/tmp/wp-tests-config.php"
fi
# Cleanup files.
clean_up_temp_files
printf "\nFinished setting up packages\n\n"
@tarecord

This comment has been minimized.

Copy link

commented Jan 9, 2018

This is awesome! Thanks!

@JJJ

This comment has been minimized.

Copy link

commented Aug 20, 2018

Still works. Thanks keesiemeijer! 👍

@hazephase

This comment has been minimized.

Copy link

commented Sep 6, 2018

When I run bash setup-phpunit.sh I get

Could not install packages
No network connection detected

@rgadon107

This comment has been minimized.

Copy link

commented Sep 17, 2018

@hazephase In the Terminal, make sure that the shell script ( setup-phpunit.sh) is located in the /app directory. If it's it in a different directory (for example /app/a888f3d9609478b310c2d952644891ba/setup-phpunit.sh, you will not be able to open and execute the target script. It's just a matter of relocating the shell script (once it's been installed to your project) to the root of the /app directory. Then call the script. It should install easily and quickly.

@keesiemeijer

This comment has been minimized.

Copy link
Owner Author

commented Sep 27, 2018

@hazephase I've updated the script (revision 15) to look if packages are installed instead of checking the internet connection. It should work with the Local app version 2.4.2

@iCaspar

This comment has been minimized.

Copy link

commented Sep 28, 2018

Thanks for this @keesiemeijer, 👍 for the fix!

@JJJ

This comment has been minimized.

Copy link

commented Oct 16, 2018

Continues to work with Local Environment 1.3.1. 🤗

@keesiemeijer

This comment has been minimized.

Copy link
Owner Author

commented Feb 2, 2019

revision 17 — The default PHPUnit version is updated to 6 for PHP versions 7+

See ticket https://core.trac.wordpress.org/ticket/43218

@keesiemeijer

This comment has been minimized.

Copy link
Owner Author

commented Feb 4, 2019

Since revision 19 you can use specific options for PHPUnit, WordPress and the WordPress test suite. Use the options
--phpunit-version, --wp-version, --wp-ts-version and --update-packages.

use bash setup-phpunit.sh --help for more information

@DevinWalker

This comment has been minimized.

Copy link

commented Mar 7, 2019

So easy and simple! Thanks @keesiemeijer

@mintplugins

This comment has been minimized.

Copy link

commented Mar 7, 2019

When I try and test with phpunit -version, I am getting this response:

Fatal error: Cannot use PHPUnit\Framework\MockObject\Stub as Stub because the name is already in use in phar:///usr/local/bin/phpunit/phpunit-mock-objects/Builder/InvocationMocker.php on line 16

Does anybody know what might be going on here?

@mintplugins

This comment has been minimized.

Copy link

commented Mar 7, 2019

It must have been an old version of phpUnit already installed. I spun up a new site in LocalByFlywheel and started over, and all is working 👍 Thanks!

On my old LocalByFlywheel site, I uninstalled PHPunit by running this before any of the steps here, and it fixed my issue:

sudo rm -r /usr/local/bin/phpunit

Update: Today I just ran into this again on a separate LocalByFlyWheel, and had to upgrade PHP to 7.2 to fix this.

@kurudrive

This comment has been minimized.

Copy link

commented Apr 23, 2019

Thanks!!!!!!!!!!
I am so happpppppyyyyyyyyyyyy!!!!!!!
Yeahhhhhhhhhhhhhhhhhhhhhhh!!!!!!!!

@DrewAPicture

This comment has been minimized.

Copy link

commented May 11, 2019

@keesiemeijer This is dope. Thank you!

@iamlasse

This comment has been minimized.

Copy link

commented May 23, 2019

This is amazing! Thanks for putting in the work!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.