Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Testing Framework #24

Merged
merged 4 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .env.dist.testing
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
TEST_SITE_DB_DSN=mysql:host=localhost;dbname=test
TEST_SITE_DB_HOST=localhost
TEST_SITE_DB_NAME=test
TEST_SITE_DB_USER=root
TEST_SITE_DB_PASSWORD=root
TEST_SITE_TABLE_PREFIX=wp_
TEST_SITE_ADMIN_USERNAME=admin
TEST_SITE_ADMIN_PASSWORD=password
TEST_SITE_WP_ADMIN_PATH=/wp-admin
WP_ROOT_FOLDER="/home/runner/work/convertkit-membermouse/convertkit-membermouse/wordpress"
TEST_DB_NAME=test
TEST_DB_HOST=localhost
TEST_DB_USER=root
TEST_DB_PASSWORD=root
TEST_TABLE_PREFIX=wp_
TEST_SITE_WP_URL=http://127.0.0.1
TEST_SITE_WP_DOMAIN=127.0.0.1
[email protected]
TEST_SITE_HTTP_USER_AGENT=HeadlessChrome
TEST_SITE_HTTP_USER_AGENT_MOBILE=HeadlessChromeMobile
24 changes: 24 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
TEST_SITE_DB_DSN=mysql:host=localhost;dbname=test
TEST_SITE_DB_HOST=localhost
TEST_SITE_DB_NAME=test
TEST_SITE_DB_USER=root
TEST_SITE_DB_PASSWORD=root
TEST_SITE_TABLE_PREFIX=wp_
TEST_SITE_ADMIN_USERNAME=admin
TEST_SITE_ADMIN_PASSWORD=password
TEST_SITE_WP_ADMIN_PATH=/wp-admin
WP_ROOT_FOLDER="/Users/tim/Local Sites/convertkit-github/app/public"
TEST_DB_NAME=test
TEST_DB_HOST=localhost
TEST_DB_USER=root
TEST_DB_PASSWORD=root
TEST_TABLE_PREFIX=wp_
TEST_SITE_WP_URL=http://convertkit.local
TEST_SITE_WP_DOMAIN=convertkit.local
[email protected]
TEST_SITE_HTTP_USER_AGENT=HeadlessChrome
TEST_SITE_HTTP_USER_AGENT_MOBILE=HeadlessChromeMobile
CONVERTKIT_API_KEY_NO_DATA=
CONVERTKIT_API_SECRET_NO_DATA=
CONVERTKIT_API_KEY=
CONVERTKIT_API_SECRET=
5 changes: 5 additions & 0 deletions .github/workflows/coding-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ jobs:
working-directory: ${{ env.PLUGIN_DIR }}
run: composer dump-autoload

# Run Coding Standards on Tests.
- name: Run Coding Standards on Tests
working-directory: ${{ env.PLUGIN_DIR }}
run: php vendor/bin/phpcs -q --standard=phpcs.tests.xml --report=checkstyle ./tests | cs2pr

# Run WordPress Coding Standards on Plugin.
- name: Run WordPress Coding Standards
working-directory: ${{ env.PLUGIN_DIR }}
Expand Down
208 changes: 208 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
name: Run Tests

# When to run tests.
on:
pull_request:
types:
- opened
- synchronize
push:
branches:
- main

jobs:
tests:
# Name.
name: ${{ matrix.test-groups }} / WordPress ${{ matrix.wp-versions }} / PHP ${{ matrix.php-versions }}

# Virtual Environment to use.
# @see: https://github.com/actions/virtual-environments
runs-on: ubuntu-20.04

# Environment Variables.
# Accessible by using ${{ env.NAME }}
# Use ${{ secrets.NAME }} to include any GitHub Secrets in ${{ env.NAME }}
# The base folder will always be /home/runner/work/github-repo-name/github-repo-name
env:
ROOT_DIR: /home/runner/work/convertkit-membermouse/convertkit-membermouse/wordpress
PLUGIN_DIR: /home/runner/work/convertkit-membermouse/convertkit-membermouse/wordpress/wp-content/plugins/convertkit-membermouse
DB_NAME: test
DB_USER: root
DB_PASS: root
DB_HOST: localhost
INSTALL_PLUGINS: "https://hub.membermouse.com/download.php" # Don't include this repository's Plugin here.
CONVERTKIT_API_KEY: ${{ secrets.CONVERTKIT_API_KEY }} # ConvertKit API Key, stored in the repository's Settings > Secrets
CONVERTKIT_API_SECRET: ${{ secrets.CONVERTKIT_API_SECRET }} # ConvertKit API Secret, stored in the repository's Settings > Secrets
CONVERTKIT_API_KEY_NO_DATA: ${{ secrets.CONVERTKIT_API_KEY_NO_DATA }} # ConvertKit API Key for ConvertKit account with no data, stored in the repository's Settings > Secrets
CONVERTKIT_API_SECRET_NO_DATA: ${{ secrets.CONVERTKIT_API_SECRET_NO_DATA }} # ConvertKit API Secret for ConvertKit account with no data, stored in the repository's Settings > Secrets

# Defines the WordPress and PHP Versions matrix to run tests on
# WooCommerce 5.9.0 requires WordPress 5.6 or greater, so we do not test on earlier versions
# If testing older WordPress versions, ensure they are e.g. 5.7.4, 5.6.6 that have the X3 SSL fix: https://core.trac.wordpress.org/ticket/54207
# For PHP, make sure that an nginx configuration file exists for the required PHP version in this repository at tests/nginx/php-x.x.conf
strategy:
fail-fast: false
matrix:
wp-versions: [ 'latest' ] #[ 'latest' ]
php-versions: [ '7.4', '8.0', '8.1', '8.2', '8.3' ] #[ '7.3', '7.4', '8.0', '8.1' ]

# Folder names within the 'tests' folder to run tests in parallel.
test-groups: [
'acceptance/general',
]

# Steps to install, configure and run tests
steps:
- name: Define Test Group Name
id: test-group
uses: mad9000/actions-find-and-replace-string@5
with:
source: ${{ matrix.test-groups }}
find: '/'
replace: '-'
replaceAll: true

- name: Start MySQL
run: sudo systemctl start mysql.service

- name: Create MySQL Database
run: |
mysql -e 'CREATE DATABASE test;' -u${{ env.DB_USER }} -p${{ env.DB_PASS }}
mysql -e 'SHOW DATABASES;' -u${{ env.DB_USER }} -p${{ env.DB_PASS }}

# WordPress won't be able to connect to the DB if we don't perform this step.
- name: Permit MySQL Password Auth for MySQL 8.0
run: mysql -e "ALTER USER '${{ env.DB_USER }}'@'${{ env.DB_HOST }}' IDENTIFIED WITH mysql_native_password BY '${{ env.DB_PASS }}';" -u${{ env.DB_USER }} -p${{ env.DB_PASS }}

# Some workflows checkout WordPress from GitHub, but that seems to bring a bunch of uncompiled files with it.
# Instead download from wordpress.org stable.
- name: Download WordPress
run: wget https://wordpress.org/wordpress-${{ matrix.wp-versions }}.tar.gz

- name: Extract WordPress
run: tar xfz wordpress-${{ matrix.wp-versions }}.tar.gz

# Checkout (copy) this repository's Plugin to this VM.
- name: Checkout Plugin
uses: actions/checkout@v4
with:
path: ${{ env.PLUGIN_DIR }}

# We install WP-CLI, as it provides useful commands to setup and install WordPress through the command line.
- name: Install WP-CLI
run: |
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp-cli

- name: Setup wp-config.php
working-directory: ${{ env.ROOT_DIR }}
run: wp-cli config create --dbname=${{ env.DB_NAME }} --dbuser=${{ env.DB_USER }} --dbpass=${{ env.DB_PASS }} --dbhost=${{ env.DB_HOST }} --locale=en_DB

- name: Install WordPress
working-directory: ${{ env.ROOT_DIR }}
run: wp-cli core install --url=127.0.0.1 --title=ConvertKit --admin_user=admin --admin_password=password [email protected]

# env.INSTALL_PLUGINS is a list of Plugin slugs, space separated e.g. contact-form-7 woocommerce.
- name: Install Free Third Party WordPress Plugins
working-directory: ${{ env.ROOT_DIR }}
run: wp-cli plugin install ${{ env.INSTALL_PLUGINS }}

# WP_DEBUG = true is required so all PHP errors are output and caught by tests (E_ALL).
- name: Enable WP_DEBUG
working-directory: ${{ env.ROOT_DIR }}
run: |
wp-cli config set WP_DEBUG true --raw

# FS_METHOD = direct is required for WP_Filesystem to operate without suppressed PHP fopen() errors that trip up tests.
- name: Enable FS_METHOD
working-directory: ${{ env.ROOT_DIR }}
run: |
wp-cli config set FS_METHOD direct

# This step is deliberately after WordPress installation and configuration, as enabling PHP 8.x before using WP-CLI results
# in the workflow failing due to incompatibilities between WP-CLI and PHP 8.x.
# By installing PHP at this stage, we can still run our tests against e.g. PHP 8.x.
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: xdebug

# Make sure that an nginx configuration file exists in this repository at tests/nginx/php-x.x.conf.
# Refer to an existing .conf file in this repository if you need to create a new one e.g. for a new PHP version.
- name: Copy nginx configuration file
run: sudo cp ${{ env.PLUGIN_DIR }}/tests/nginx/php-${{ matrix.php-versions }}.conf /etc/nginx/conf.d/php-${{ matrix.php-versions }}.conf

- name: Test nginx
run: sudo nginx -t

- name: Start nginx
run: sudo systemctl start nginx.service

- name: Install chromedriver
uses: nanasess/setup-chromedriver@master

- name: Start chromedriver
run: |
export DISPLAY=:99
chromedriver --url-base=/wd/hub &
sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 & # optional

# Write any secrets, such as API keys, to the .env.dist.testing file now.
# Make sure your committed .env.dist.testing file ends with a newline.
# The formatting of the contents to include a blank newline is deliberate.
- name: Define GitHub Secrets in .env.dist.testing
uses: DamianReeves/[email protected]
with:
path: ${{ env.PLUGIN_DIR }}/.env.dist.testing
contents: |

CONVERTKIT_API_KEY=${{ env.CONVERTKIT_API_KEY }}
CONVERTKIT_API_SECRET=${{ env.CONVERTKIT_API_SECRET }}
CONVERTKIT_API_KEY_NO_DATA=${{ env.CONVERTKIT_API_KEY_NO_DATA }}
CONVERTKIT_API_SECRET_NO_DATA=${{ env.CONVERTKIT_API_SECRET_NO_DATA }}
write-mode: append

# Installs wp-browser, Codeception, PHP CodeSniffer and anything else needed to run tests.
- name: Run Composer
working-directory: ${{ env.PLUGIN_DIR }}
run: composer update

- name: Build PHP Autoloader
working-directory: ${{ env.PLUGIN_DIR }}
run: composer dump-autoload

# This ensures the Plugin's log file can be written to.
# We don't recursively do this, as it'll prevent Codeception from writing to the /tests/_output directory.
- name: Set Permissions for Plugin Directory
run: |
sudo chmod g+w ${{ env.PLUGIN_DIR }}
sudo chown www-data:www-data ${{ env.PLUGIN_DIR }}

# Build Codeception Tests.
- name: Build Tests
working-directory: ${{ env.PLUGIN_DIR }}
run: php vendor/bin/codecept build

# Run Codeception Acceptance Tests.
- name: Run tests/${{ matrix.test-groups }}
working-directory: ${{ env.PLUGIN_DIR }}
run: php vendor/bin/codecept run tests/${{ matrix.test-groups }} --fail-fast

# Artifacts are data generated by this workflow that we want to access, such as log files, screenshots, HTML output.
# The if: failure() directive means that this will run when the workflow fails e.g. if a test fails, which is needed
# because we want to see why a test failed.
- name: Upload Test Results to Artifact
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ steps.test-group.outputs.value }}-${{ matrix.php-versions }}
path: ${{ env.PLUGIN_DIR }}/tests/_output/

- name: Upload Plugin Log File to Artifact
if: failure()
uses: actions/upload-artifact@v4
with:
name: log-${{ steps.test-group.outputs.value }}-${{ matrix.php-versions }}.txt
path: ${{ env.PLUGIN_DIR }}/log/log.txt
22 changes: 22 additions & 0 deletions codeception.dist.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
actor_suffix: Tester
extensions:
enabled:
- Codeception\Extension\RunFailed
commands:
- Codeception\Command\GenerateWPUnit
- Codeception\Command\GenerateWPRestApi
- Codeception\Command\GenerateWPRestController
- Codeception\Command\GenerateWPRestPostTypeController
- Codeception\Command\GenerateWPAjax
- Codeception\Command\GenerateWPCanonical
- Codeception\Command\GenerateWPXMLRPC
params:
- .env.dist.testing
3 changes: 0 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
"description": "ConvertKit WordPress Plugin",
"type": "project",
"license": "GPLv3",
"require": {
"convertkit/convertkit-wordpress-libraries": "1.4.2"
},
"require-dev": {
"lucatume/wp-browser": "<3.5",
"codeception/module-asserts": "^1.3",
Expand Down
58 changes: 58 additions & 0 deletions phpcs.tests.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PHP_CodeSniffer" xsi:noNamespaceSchemaLocation="phpcs.xsd">
<description>Coding Standards for Tests</description>

<!-- Inspect files in the /tests folder -->
<file>tests</file>

<!-- Run in verbose mode and specify the precise rule that failed in output -->
<arg value="sv"/>
<arg name="colors"/>

<!-- Check that code meets WordPress-Extra standards. -->
<rule ref="WordPress-Extra">
<!-- Don't use yoda conditions -->
<exclude name="WordPress.PHP.YodaConditions" />

<!-- File and variable naming conventions in Codeception differ from WordPress -->
<exclude name="WordPress.NamingConventions" />
<exclude name="WordPress.Files.FileName" />

<!-- Class and function braces and spacing in Codeceptoin differs from WordPress -->
<exclude name="WordPress.WhiteSpace.ControlStructureSpacing.NoSpaceAfterOpenParenthesis" />
<exclude name="WordPress.WhiteSpace.ControlStructureSpacing.ExtraSpaceAfterCloseParenthesis" />
<exclude name="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterOpen" />
<exclude name="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingBeforeClose" />
<exclude name="WordPress.WhiteSpace.ControlStructureSpacing.NoSpaceBeforeCloseParenthesis" />
<exclude name="Generic.Classes.OpeningBraceSameLine.BraceOnNewLine" />
<exclude name="Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine" />
<exclude name="PEAR.Functions.FunctionCallSignature.SpaceBeforeOpenBracket" />
<exclude name="PEAR.Functions.FunctionCallSignature.SpaceAfterOpenBracket" />
<exclude name="PEAR.Functions.FunctionCallSignature.SpaceBeforeCloseBracket" />
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.SpaceAfterFunction" />

<!-- _before() and _passed() must use underscores in Codeception -->
<exclude name="PSR2.Methods.MethodDeclaration.Underscore" />

<!-- Permit [] instead of array() -->
<exclude name="Universal.Arrays.DisallowShortArraySyntax.Found" />

<!-- We might use some datetime functions for tests -->
<exclude name="WordPress.DateTime.RestrictedFunctions" />

<!-- Handles false positives where Coding Standards thinks we did something wrong when we're just checking for e.g. a stylesheet -->
<exclude name="WordPress.WP.EnqueuedResources" />
<exclude name="WordPress.PHP.DiscouragedPHPFunctions" />
<exclude name="WordPress.WP.CapitalPDangit.MisspelledInText" />
</rule>

<!-- Check that code is documented to WordPress Standards. -->
<rule ref="WordPress-Docs">
<!-- File document level comments are useless for tests; we know what a test suite does -->
<exclude name="Squiz.Commenting.FileComment.Missing" />
</rule>

<!-- Add in some extra rules from other standards. -->
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
<rule ref="Generic.Commenting.Todo"/>
</ruleset>
Empty file added tests/_data/.gitkeep
Empty file.
Loading
Loading