Skip to content

Commit c8b8af7

Browse files
authored
Add initial PHPUnit test infrastructure. (#60)
Signed-off-by: costdev <79332690+costdev@users.noreply.github.com>
1 parent 1469385 commit c8b8af7

14 files changed

Lines changed: 745 additions & 3 deletions

.distignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
.github/
44
bin/
55
node_modules/
6+
tests/
7+
phpunit.xml.dist
8+
wp-tests-config-sample.php
9+
composer.json
10+
composer.lock
611
.gitignore
712
.distignore
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
name: Run PHPUnit Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
workflow_dispatch:
11+
12+
# Cancels all previous workflow runs for pull requests that have not completed.
13+
concurrency:
14+
# The concurrency group contains the workflow name and the branch name for pull requests
15+
# or the commit hash for any other events.
16+
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
17+
cancel-in-progress: true
18+
19+
permissions:
20+
contents: read
21+
22+
jobs:
23+
# Runs the PHPUnit tests for FAIR.
24+
#
25+
# Performs the following steps:
26+
# - Checks out the repository.
27+
# - Sets up PHP.
28+
# - Installs Composer dependencies.
29+
# - Installs SVN.
30+
# - Installs the test suite.
31+
# - Runs the PHPUnit tests.
32+
# - Ensures version-controlled files are not modified.
33+
phpunit:
34+
name: Run tests (WP ${{ matrix.wp-version }}, PHP ${{ matrix.php-version }})
35+
runs-on: ubuntu-latest
36+
strategy:
37+
matrix:
38+
php-version: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ]
39+
wp-version: [ '5.4', '5.5', '5.6', '5.7', '5.8', '5.9', '6.0', '6.1', '6.2', '6.3', '6.4', '6.5', '6.6', '6.7' ]
40+
exclude:
41+
# PHP 8.4 exclusions
42+
- wp-version: '6.6'
43+
php-version: '8.4'
44+
- wp-version: '6.5'
45+
php-version: '8.4'
46+
- wp-version: '6.4'
47+
php-version: '8.4'
48+
- wp-version: '6.3'
49+
php-version: '8.4'
50+
- wp-version: '6.2'
51+
php-version: '8.4'
52+
- wp-version: '6.1'
53+
php-version: '8.4'
54+
- wp-version: '6.0'
55+
php-version: '8.4'
56+
- wp-version: '5.9'
57+
php-version: '8.4'
58+
- wp-version: '5.8'
59+
php-version: '8.4'
60+
- wp-version: '5.7'
61+
php-version: '8.4'
62+
- wp-version: '5.6'
63+
php-version: '8.4'
64+
- wp-version: '5.5'
65+
php-version: '8.4'
66+
- wp-version: '5.4'
67+
php-version: '8.4'
68+
69+
# PHP 8.3 exclusions
70+
- wp-version: '6.3'
71+
php-version: '8.3'
72+
- wp-version: '6.2'
73+
php-version: '8.3'
74+
- wp-version: '6.1'
75+
php-version: '8.3'
76+
- wp-version: '6.0'
77+
php-version: '8.3'
78+
- wp-version: '5.9'
79+
php-version: '8.3'
80+
- wp-version: '5.8'
81+
php-version: '8.3'
82+
- wp-version: '5.7'
83+
php-version: '8.3'
84+
- wp-version: '5.6'
85+
php-version: '8.3'
86+
- wp-version: '5.5'
87+
php-version: '8.3'
88+
- wp-version: '5.4'
89+
php-version: '8.3'
90+
91+
# PHP 8.2 exclusions
92+
- wp-version: '6.0'
93+
php-version: '8.2'
94+
- wp-version: '5.9'
95+
php-version: '8.2'
96+
- wp-version: '5.8'
97+
php-version: '8.2'
98+
- wp-version: '5.7'
99+
php-version: '8.2'
100+
- wp-version: '5.6'
101+
php-version: '8.2'
102+
- wp-version: '5.5'
103+
php-version: '8.2'
104+
- wp-version: '5.4'
105+
php-version: '8.2'
106+
107+
# PHP 8.1 exclusions
108+
- wp-version: '5.8'
109+
php-version: '8.1'
110+
- wp-version: '5.7'
111+
php-version: '8.1'
112+
- wp-version: '5.6'
113+
php-version: '8.1'
114+
- wp-version: '5.5'
115+
php-version: '8.1'
116+
- wp-version: '5.4'
117+
php-version: '8.1'
118+
119+
# PHP 8 exclusions
120+
- wp-version: '5.8' # Should work, currently doesn't.
121+
php-version: '8.0'
122+
- wp-version: '5.7' # Should work, currently doesn't.
123+
php-version: '8.0'
124+
- wp-version: '5.6' # Introduced PHP 8 beta support. Should work, currently doesn't.
125+
php-version: '8.0'
126+
- wp-version: '5.5'
127+
php-version: '8.0'
128+
- wp-version: '5.4'
129+
php-version: '8.0'
130+
131+
steps:
132+
- name: Checkout
133+
uses: actions/checkout@master
134+
135+
- name: Setup MySQL with mysql_native_password
136+
uses: shogo82148/actions-setup-mysql@v1
137+
with:
138+
mysql-version: ${{ matrix.wp-version >= '5.0' && '8.0' || '5.6' }}
139+
my-cnf: |
140+
bind_address=127.0.0.1
141+
default-authentication-plugin=mysql_native_password
142+
root-password: root
143+
144+
- name: Set up PHP
145+
uses: shivammathur/setup-php@v2
146+
with:
147+
php-version: ${{ matrix.php-version }}
148+
coverage: none
149+
extensions: mysql, mysqli
150+
tools: composer, wp-cli, phpunit:${{ matrix.wp-version < '5.1' && '6' || ( matrix.wp-version < '5.9' || matrix.php-version < '8.0' ) && '7' || '9' }}, phpunit-polyfills:^1.1.0
151+
env:
152+
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
153+
154+
- name: Install Composer dependencies
155+
run: composer install --optimize-autoloader --prefer-dist
156+
157+
- name: Install SVN
158+
run: sudo apt-get update && sudo apt-get install -y subversion
159+
160+
- name: Install test suite
161+
run: |
162+
echo "WP_VERSION=${{ matrix.wp-version }}" >> $GITHUB_ENV
163+
echo "TMPDIR=${{ runner.temp }}" >> $GITHUB_ENV
164+
echo "WP_TESTS_DIR=${{ runner.temp }}/wordpress-tests-lib" >> $GITHUB_ENV
165+
echo "WP_CORE_DIR=${{ runner.temp }}/wordpress" >> $GITHUB_ENV
166+
TMPDIR=${{ runner.temp }} bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 ${{ matrix.wp-version }}
167+
168+
- name: Run PHPUnit tests
169+
run: |
170+
echo "define('WP_TESTS_PHPUNIT_POLYFILLS_PATH', '$HOME/.composer/vendor/yoast/phpunit-polyfills');" >> ${{ runner.temp }}/wordpress-tests-lib/wp-tests-config.php
171+
phpunit
172+
173+
- name: Ensure version-controlled files are not modified or deleted
174+
run: git diff --exit-code

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
/node_modules/
22
*.bak
33
/.vscode
4+
/vendor/
5+
.phpunit.result.cache
6+
phpunit.xml
7+
/tests/phpunit/cache
8+
/tests/phpunit/coverage
9+
wp-tests-config.php

.wp-env.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
],
77
"mappings": {
88
"wp-content/plugins/plugin": "."
9+
},
10+
"config": {
11+
"WP_TESTS_PHPUNIT_POLYFILLS_PATH": "./vendor/yoast/phpunit-polyfills"
912
}
1013
}

bin/install-wp-tests.sh

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#!/usr/bin/env bash
2+
3+
if [ $# -lt 3 ]; then
4+
echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]"
5+
exit 1
6+
fi
7+
8+
DB_NAME=$1
9+
DB_USER=$2
10+
DB_PASS=$3
11+
DB_HOST=${4-localhost}
12+
WP_VERSION=${5-latest}
13+
SKIP_DB_CREATE=${6-false}
14+
15+
TMPDIR=${TMPDIR-/tmp}
16+
TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//")
17+
WP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib}
18+
WP_CORE_DIR=${WP_CORE_DIR-$TMPDIR/wordpress}
19+
20+
download() {
21+
if [ `which curl` ]; then
22+
curl -s "$1" > "$2";
23+
elif [ `which wget` ]; then
24+
wget -nv -O "$2" "$1"
25+
fi
26+
}
27+
28+
if [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+\-(beta|RC)[0-9]+$ ]]; then
29+
WP_BRANCH=${WP_VERSION%\-*}
30+
WP_TESTS_TAG="branches/$WP_BRANCH"
31+
32+
elif [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then
33+
WP_TESTS_TAG="branches/$WP_VERSION"
34+
elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then
35+
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then
36+
# version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x
37+
WP_TESTS_TAG="tags/${WP_VERSION%??}"
38+
else
39+
WP_TESTS_TAG="tags/$WP_VERSION"
40+
fi
41+
elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
42+
WP_TESTS_TAG="trunk"
43+
else
44+
# http serves a single offer, whereas https serves multiple. we only want one
45+
download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
46+
grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
47+
LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
48+
if [[ -z "$LATEST_VERSION" ]]; then
49+
echo "Latest WordPress version could not be found"
50+
exit 1
51+
fi
52+
WP_TESTS_TAG="tags/$LATEST_VERSION"
53+
fi
54+
set -ex
55+
56+
install_wp() {
57+
58+
if [ -d $WP_CORE_DIR ]; then
59+
return;
60+
fi
61+
62+
mkdir -p $WP_CORE_DIR
63+
64+
if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
65+
mkdir -p $TMPDIR/wordpress-trunk
66+
rm -rf $TMPDIR/wordpress-trunk/*
67+
svn export --quiet https://core.svn.wordpress.org/trunk $TMPDIR/wordpress-trunk/wordpress
68+
mv $TMPDIR/wordpress-trunk/wordpress/* $WP_CORE_DIR
69+
else
70+
if [ $WP_VERSION == 'latest' ]; then
71+
local ARCHIVE_NAME='latest'
72+
elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+ ]]; then
73+
# https serves multiple offers, whereas http serves single.
74+
download https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json
75+
if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then
76+
# version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x
77+
LATEST_VERSION=${WP_VERSION%??}
78+
else
79+
# otherwise, scan the releases and get the most up to date minor version of the major release
80+
local VERSION_ESCAPED=`echo $WP_VERSION | sed 's/\./\\\\./g'`
81+
LATEST_VERSION=$(grep -o '"version":"'$VERSION_ESCAPED'[^"]*' $TMPDIR/wp-latest.json | sed 's/"version":"//' | head -1)
82+
fi
83+
if [[ -z "$LATEST_VERSION" ]]; then
84+
local ARCHIVE_NAME="wordpress-$WP_VERSION"
85+
else
86+
local ARCHIVE_NAME="wordpress-$LATEST_VERSION"
87+
fi
88+
else
89+
local ARCHIVE_NAME="wordpress-$WP_VERSION"
90+
fi
91+
download https://wordpress.org/${ARCHIVE_NAME}.tar.gz $TMPDIR/wordpress.tar.gz
92+
tar --strip-components=1 -zxmf $TMPDIR/wordpress.tar.gz -C $WP_CORE_DIR
93+
fi
94+
95+
download https://raw.githubusercontent.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
96+
}
97+
98+
install_test_suite() {
99+
# portable in-place argument for both GNU sed and Mac OSX sed
100+
if [[ $(uname -s) == 'Darwin' ]]; then
101+
local ioption='-i.bak'
102+
else
103+
local ioption='-i'
104+
fi
105+
106+
# set up testing suite if it doesn't yet exist
107+
if [ ! -d $WP_TESTS_DIR ]; then
108+
# set up testing suite
109+
mkdir -p $WP_TESTS_DIR
110+
rm -rf $WP_TESTS_DIR/{includes,data}
111+
svn export --quiet --ignore-externals https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
112+
svn export --quiet --ignore-externals https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data
113+
fi
114+
115+
if [ ! -f wp-tests-config.php ]; then
116+
download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
117+
# remove all forward slashes in the end
118+
WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::")
119+
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
120+
sed $ioption "s:__DIR__ . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
121+
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
122+
sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
123+
sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
124+
sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
125+
fi
126+
127+
}
128+
129+
recreate_db() {
130+
shopt -s nocasematch
131+
if [[ $1 =~ ^(y|yes)$ ]]
132+
then
133+
mysqladmin drop $DB_NAME -f --user="$DB_USER" --password="$DB_PASS"$EXTRA
134+
create_db
135+
echo "Recreated the database ($DB_NAME)."
136+
else
137+
echo "Leaving the existing database ($DB_NAME) in place."
138+
fi
139+
shopt -u nocasematch
140+
}
141+
142+
create_db() {
143+
mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
144+
}
145+
146+
install_db() {
147+
148+
if [ ${SKIP_DB_CREATE} = "true" ]; then
149+
return 0
150+
fi
151+
152+
# parse DB_HOST for port or socket references
153+
local PARTS=(${DB_HOST//\:/ })
154+
local DB_HOSTNAME=${PARTS[0]};
155+
local DB_SOCK_OR_PORT=${PARTS[1]};
156+
local EXTRA=""
157+
158+
if ! [ -z $DB_HOSTNAME ] ; then
159+
if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
160+
EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
161+
elif ! [ -z $DB_SOCK_OR_PORT ] ; then
162+
EXTRA=" --socket=$DB_SOCK_OR_PORT"
163+
elif ! [ -z $DB_HOSTNAME ] ; then
164+
EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
165+
fi
166+
fi
167+
168+
# create database
169+
if [ $(mysql --user="$DB_USER" --password="$DB_PASS"$EXTRA --execute='show databases;' | grep ^$DB_NAME$) ]
170+
then
171+
echo "Reinstalling will delete the existing test database ($DB_NAME)"
172+
read -p 'Are you sure you want to proceed? [y/N]: ' DELETE_EXISTING_DB
173+
recreate_db $DELETE_EXISTING_DB
174+
else
175+
create_db
176+
fi
177+
}
178+
179+
install_wp
180+
install_test_suite
181+
install_db

0 commit comments

Comments
 (0)