mirror of https://github.com/FriendsOfTYPO3/tea.git synced 2024-11-15 21:16:12 +01:00
tea/Build/Scripts/runTests.sh
Stefan Bürk 71bc7e137d [TASK] Introduce Build/Scripts/runTests.sh adoption
This change adopts the well known runTests.sh from TYPO3 core
and related extensions as basic scripts and test execution
center. Main benefit of this implemenation is, that these
commands are behaving the same on all systems and ci, thus
increasing interoperability and easier transforming of commands
between systems - which ease the way to rerun or debug failed
tests locally after detected in ci (GitHub Actions, Gitlab CI).

Available suits and options are aligned to this project needs,
and will be updated if needed. To display available commands:

```shell
Build/Scripts/runTests.sh -h
```

Generic tasks and options (incomplete):

* `-s composerInstall` normal install, for code quality checks

* `-s composerInstallLowest` and `-s composerInstallHighest` to
  install dependencies with lowest and highest possibilities for
  all dependencies, based on selected php-version, core-version
  and so on. This helps to build fast a wide range of testing
  matrix for unit- and functional tests

* `-p <7.4|8.0|8.1|8.2>` defines which php version is used for
  executed php and composer scripts, like unit or functional
  tests, composer installs and so on

* ensure support for following databases for functional tests:

  - postgres <10|11|12|13|14> default: 10
  - mysql <5.5|5.6|5.7|8.0> default: 5.5
  - mariadb <10.2|10.3|10.4|10.5|10.6|10.7> default: 10.2
  - sqlite

  This can be controlled with a couple of options:
    -d <sqlite|mariadb|mysql|postgres>
    -a <mysqli|pdo_mysql> (for -d mysql or -d mariadb)
    -i <10.2|10.3|10.4|10.5|10.6|10.7> (for -d mariadb)
    -j <5.5|5.6|5.7|8.0> (for -d mysql)
    -k <10|11|12|13|14> (for -d postgres)

* selection of core can be choosen with the `-t` flag,
  also only v11 currently available. This is already
  a preparation for multi-core testing or for further
  version shiftings.

* included cgl (php cs fixer) with dryrun as suite
* add phpstan and phpstan generate baseline suites

Resolves #94
2022-10-16 03:49:32 +02:00

480 lines
16 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# TYPO3 core test runner based on docker and docker-compose.
#
# Function to write a .env file in Build/testing-docker
# This is read by docker-compose and vars defined here are
# used in Build/testing-docker/docker-compose.yml
setUpDockerComposeDotEnv() {
# Delete possibly existing local .env file if exists
[ -e .env ] && rm .env
# Set up a new .env file for docker-compose
{
echo "COMPOSE_PROJECT_NAME=local"
# To prevent access rights of files created by the testing, the docker image later
# runs with the same user that is currently executing the script. docker-compose can't
# use $UID directly itself since it is a shell variable and not an env variable, so
# we have to set it explicitly here.
echo "HOST_UID=`id -u`"
# Your local user
echo "ROOT_DIR=${ROOT_DIR}"
echo "HOST_USER=${USER}"
echo "TEST_FILE=${TEST_FILE}"
echo "TYPO3_VERSION=${TYPO3_VERSION}"
echo "PHP_XDEBUG_ON=${PHP_XDEBUG_ON}"
echo "PHP_XDEBUG_PORT=${PHP_XDEBUG_PORT}"
echo "DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE}"
echo "EXTRA_TEST_OPTIONS=${EXTRA_TEST_OPTIONS}"
echo "SCRIPT_VERBOSE=${SCRIPT_VERBOSE}"
echo "CGLCHECK_DRY_RUN=${CGLCHECK_DRY_RUN}"
echo "DATABASE_DRIVER=${DATABASE_DRIVER}"
echo "MARIADB_VERSION=${MARIADB_VERSION}"
echo "MYSQL_VERSION=${MYSQL_VERSION}"
echo "POSTGRES_VERSION=${POSTGRES_VERSION}"
echo "USED_XDEBUG_MODES=${USED_XDEBUG_MODES}"
# needed for coveralls upload
echo "COVERALLS_REPO_TOKEN='${COVERALLS_REPO_TOKEN}'"
echo "GITHUB_REF='${GITHUB_REF}'"
echo "GITHUB_ACTIONS='${GITHUB_ACTIONS}'"
echo "GITHUB_RUN_ID='${GITHUB_RUN_ID}'"
echo "GITHUB_EVENT_NAME='${GITHUB_EVENT_NAME}'"
} > .env
}
# Options -a and -d depend on each other. The function
# validates input combinations and sets defaults.
handleDbmsAndDriverOptions() {
case ${DBMS} in
mysql|mariadb)
[ -z "${DATABASE_DRIVER}" ] && DATABASE_DRIVER="mysqli"
if [ "${DATABASE_DRIVER}" != "mysqli" ] && [ "${DATABASE_DRIVER}" != "pdo_mysql" ]; then
echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2
echo >&2
echo "call \"./Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
exit 1
fi
;;
postgres|sqlite)
if [ -n "${DATABASE_DRIVER}" ]; then
echo "Invalid option -a ${DATABASE_DRIVER} with -d ${DBMS}" >&2
echo >&2
echo "call \"./Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
exit 1
fi
;;
esac
}
# Load help text into $HELP
read -r -d '' HELP <<EOF
ttn/tea test runner. Execute unit test suite and some other details.
Also used by github for test execution.
Recommended docker version is >=20.10 for xdebug break pointing to work reliably, and
a recent docker-compose (tested >=1.21.2) is needed.
Usage: $0 [options] [file]
No arguments: Run all unit tests with PHP 7.4
Options:
-s <...>
Specifies which test suite to run
- cgl: cgl test and fix all php files
- clean: clean up build and testing related files
- composer: Execute "composer" command, using -e for command arguments pass-through, ex. -e "ci:php:stan"
- composerInstall: "composer update", handy if host has no PHP
- composerInstallLowest: "composer update", handy if host has no PHP
- composerInstallHighest: "composer update", handy if host has no PHP
- coveralls: Execute coveralls to upload coverage to coveralls
- functional: functional tests
- lint: PHP linting
- phpstan: phpstan analyze
- phpstanGenerateBaseline: regenerate phpstan baseline, handy after phpstan updates
- unit: PHP unit tests
-a <mysqli|pdo_mysql>
Only with -s acceptance,functional
Specifies to use another driver, following combinations are available:
- mysql
- mysqli (default)
- pdo_mysql
- mariadb
- mysqli (default)
- pdo_mysql
-d <sqlite|mariadb|mysql|postgres>
Only with -s acceptance,functional
Specifies on which DBMS tests are performed
- sqlite: (default) use sqlite
- mariadb: use mariadb
- mysql: use mysql
- postgres: use postgres
-i <10.2|10.3|10.4|10.5|10.6|10.7>
Only with -d mariadb
Specifies on which version of mariadb tests are performed
- 10.2 (default)
- 10.3
- 10.4
- 10.5
- 10.6
- 10.7
-j <5.5|5.6|5.7|8.0>
Only with -d mysql
Specifies on which version of mysql tests are performed
- 5.5 (default)
- 5.6
- 5.7
- 8.0
-k <10|11|12|13|14>
Only with -d postgres
Specifies on which version of postgres tests are performed
- 10 (default)
- 11
- 12
- 13
- 14
-p <7.4|8.0|8.1|8.2>
Specifies the PHP minor version to be used
- 7.4 (default): use PHP 7.4
- 8.0: use PHP 8.0
- 8.1: use PHP 8.1
- 8.2: use PHP 8.2
-t <11|12>
Only with -s composerUpdate
Specifies the TYPO3 core major version to be used
- 11 (default): use TYPO3 core v11
- 12: use TYPO3 core v12
-e "<composer, phpunit or codeception options>"
Only with -s functional|unit|composer
Additional options to send to phpunit (unit & functional tests) or codeception (acceptance
tests). For phpunit, options starting with "--" must be added after options starting with "-".
Example -e "-v --filter canRetrieveValueWithGP" to enable verbose output AND filter tests
named "canRetrieveValueWithGP"
-x
Only with -s functional|unit
Send information to host instance for test or system under test break points. This is especially
useful if a local PhpStorm instance is listening on default xdebug port 9003. A different port
can be selected with -y
-y <port>
Send xdebug information to a different port than default 9003 if an IDE like PhpStorm
is not listening on default port.
-z <xdebug modes>
Only with -x and -s functional|unit|acceptance
This sets the used xdebug modes. Defaults to 'debug,develop'
-n
Only with -s cgl
Activate dry-run in CGL check that does not actively change files and only prints broken ones.
-u
Update existing typo3/core-testing-*:latest docker images. Maintenance call to docker pull latest
versions of the main php images. The images are updated once in a while and only the youngest
ones are supported by core testing. Use this if weird test errors occur. Also removes obsolete
image versions of typo3/core-testing-*.
-v
Enable verbose script output. Shows variables and docker commands.
-h
Show this help.
Examples:
# Run unit tests using PHP 7.4
./Build/Scripts/runTests.sh -s unit
EOF
# Test if docker-compose exists, else exit out with error
if ! type "docker-compose" > /dev/null; then
echo "This script relies on docker and docker-compose. Please install" >&2
exit 1
fi
# Go to the directory this script is located, so everything else is relative
# to this dir, no matter from where this script is called.
THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
cd "$THIS_SCRIPT_DIR" || exit 1
# Go to directory that contains the local docker-compose.yml file
cd ../testing-docker || exit 1
# Option defaults
if ! command -v realpath &> /dev/null; then
echo "This script works best with realpath installed" >&2
ROOT_DIR="${PWD}/../../"
else
ROOT_DIR=`realpath ${PWD}/../../`
fi
TEST_SUITE=""
DBMS="sqlite"
PHP_VERSION="7.4"
TYPO3_VERSION="11"
PHP_XDEBUG_ON=0
PHP_XDEBUG_PORT=9003
EXTRA_TEST_OPTIONS=""
SCRIPT_VERBOSE=0
CGLCHECK_DRY_RUN=""
DATABASE_DRIVER=""
MARIADB_VERSION="10.2"
MYSQL_VERSION="5.5"
POSTGRES_VERSION="10"
USED_XDEBUG_MODES="debug,develop"
# Option parsing
# Reset in case getopts has been used previously in the shell
OPTIND=1
# Array for invalid options
INVALID_OPTIONS=();
# Simple option parsing based on getopts (! not getopt)
while getopts ":s:a:d:i:j:k:p:t:e:xy:z:nhuv" OPT; do
case ${OPT} in
s)
TEST_SUITE=${OPTARG}
;;
a)
DATABASE_DRIVER=${OPTARG}
;;
d)
DBMS=${OPTARG}
;;
i)
MARIADB_VERSION=${OPTARG}
if ! [[ ${MARIADB_VERSION} =~ ^(10.2|10.3|10.4|10.5|10.6|10.7)$ ]]; then
INVALID_OPTIONS+=("${OPTARG}")
fi
;;
j)
MYSQL_VERSION=${OPTARG}
if ! [[ ${MYSQL_VERSION} =~ ^(5.5|5.6|5.7|8.0)$ ]]; then
INVALID_OPTIONS+=("${OPTARG}")
fi
;;
k)
POSTGRES_VERSION=${OPTARG}
if ! [[ ${POSTGRES_VERSION} =~ ^(10|11|12|13|14)$ ]]; then
INVALID_OPTIONS+=("${OPTARG}")
fi
;;
p)
PHP_VERSION=${OPTARG}
if ! [[ ${PHP_VERSION} =~ ^(7.4|8.0|8.1|8.2)$ ]]; then
INVALID_OPTIONS+=("p ${OPTARG}")
fi
;;
t)
TYPO3_VERSION=${OPTARG}
if ! [[ ${TYPO3_VERSION} =~ ^(11|12)$ ]]; then
INVALID_OPTIONS+=("p ${OPTARG}")
fi
;;
e)
EXTRA_TEST_OPTIONS=${OPTARG}
;;
x)
PHP_XDEBUG_ON=1
;;
y)
PHP_XDEBUG_PORT=${OPTARG}
;;
z)
USED_XDEBUG_MODES=${OPTARG}
;;
h)
echo "${HELP}"
exit 0
;;
n)
CGLCHECK_DRY_RUN="-n"
;;
u)
TEST_SUITE=update
;;
v)
SCRIPT_VERBOSE=1
;;
\?)
INVALID_OPTIONS+=(${OPTARG})
;;
:)
INVALID_OPTIONS+=(${OPTARG})
;;
esac
done
# Exit on invalid options
if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then
echo "Invalid option(s):" >&2
for I in "${INVALID_OPTIONS[@]}"; do
echo "-"${I} >&2
done
echo >&2
echo "${HELP}" >&2
exit 1
fi
# Move "7.2" to "php72", the latter is the docker container name
DOCKER_PHP_IMAGE=`echo "php${PHP_VERSION}" | sed -e 's/\.//'`
# Set $1 to first mass argument, this is the optional test file or test directory to execute
shift $((OPTIND - 1))
TEST_FILE=${1}
if [ -n "${1}" ]; then
TEST_FILE=".Build/public/typo3conf/ext/tea/${1}"
fi
if [ ${SCRIPT_VERBOSE} -eq 1 ]; then
set -x
fi
if [ -z ${TEST_SUITE} ]; then
echo "${HELP}"
exit 0
fi
# Suite execution
case ${TEST_SUITE} in
cgl)
# Active dry-run for cgl needs not "-n" but specific options
if [[ ! -z ${CGLCHECK_DRY_RUN} ]]; then
CGLCHECK_DRY_RUN="--dry-run --diff"
fi
setUpDockerComposeDotEnv
docker-compose run cgl
SUITE_EXIT_CODE=$?
docker-compose down
;;
clean)
rm -rf ../../.cache ../../composer.lock ../../.Build/ ../../Tests/Acceptance/Support/_generated/ ../../composer.json.testing
;;
composer)
setUpDockerComposeDotEnv
docker-compose run composer
SUITE_EXIT_CODE=$?
docker-compose down
;;
composerInstall)
setUpDockerComposeDotEnv
cp ../../composer.json ../../composer.json.orig
if [ -f "../../composer.json.testing" ]; then
cp ../../composer.json ../../composer.json.orig
fi
docker-compose run composer_install
cp ../../composer.json ../../composer.json.testing
mv ../../composer.json.orig ../../composer.json
SUITE_EXIT_CODE=$?
docker-compose down
;;
composerInstallLowest)
setUpDockerComposeDotEnv
cp ../../composer.json ../../composer.json.orig
if [ -f "../../composer.json.testing" ]; then
cp ../../composer.json ../../composer.json.orig
fi
docker-compose run composer_install_lowest
cp ../../composer.json ../../composer.json.testing
mv ../../composer.json.orig ../../composer.json
SUITE_EXIT_CODE=$?
docker-compose down
;;
composerInstallHighest)
setUpDockerComposeDotEnv
cp ../../composer.json ../../composer.json.orig
if [ -f "../../composer.json.testing" ]; then
cp ../../composer.json ../../composer.json.orig
fi
docker-compose run composer_install_highest
cp ../../composer.json ../../composer.json.testing
mv ../../composer.json.orig ../../composer.json
SUITE_EXIT_CODE=$?
docker-compose down
;;
coveralls)
setUpDockerComposeDotEnv
docker-compose run coveralls
SUITE_EXIT_CODE=$?
docker-compose down
;;
functional)
handleDbmsAndDriverOptions
setUpDockerComposeDotEnv
case ${DBMS} in
mariadb)
echo "Using driver: ${DATABASE_DRIVER}"
docker-compose run functional_mariadb
SUITE_EXIT_CODE=$?
;;
mysql)
echo "Using driver: ${DATABASE_DRIVER}"
docker-compose run functional_mysql
SUITE_EXIT_CODE=$?
;;
postgres)
docker-compose run functional_postgres
SUITE_EXIT_CODE=$?
;;
sqlite)
# sqlite has a tmpfs as Web/typo3temp/var/tests/functional-sqlite-dbs/
# Since docker is executed as root (yay!), the path to this dir is owned by
# root if docker creates it. Thank you, docker. We create the path beforehand
# to avoid permission issues.
mkdir -p ${ROOT_DIR}/public/typo3temp/var/tests/functional-sqlite-dbs/
docker-compose run functional_sqlite
SUITE_EXIT_CODE=$?
;;
*)
echo "Invalid -d option argument ${DBMS}" >&2
echo >&2
echo "${HELP}" >&2
exit 1
esac
docker-compose down
;;
lint)
setUpDockerComposeDotEnv
docker-compose run lint
SUITE_EXIT_CODE=$?
docker-compose down
;;
phpstan)
setUpDockerComposeDotEnv
docker-compose run phpstan
SUITE_EXIT_CODE=$?
docker-compose down
;;
phpstanGenerateBaseline)
setUpDockerComposeDotEnv
docker-compose run phpstan_generate_baseline
SUITE_EXIT_CODE=$?
docker-compose down
;;
unit)
setUpDockerComposeDotEnv
docker-compose run unit
SUITE_EXIT_CODE=$?
docker-compose down
;;
update)
# pull typo3/core-testing-*:latest versions of those ones that exist locally
docker images typo3/core-testing-*:latest --format "{{.Repository}}:latest" | xargs -I {} docker pull {}
# remove "dangling" typo3/core-testing-* images (those tagged as <none>)
docker images typo3/core-testing-* --filter "dangling=true" --format "{{.ID}}" | xargs -I {} docker rmi {}
;;
*)
echo "Invalid -s option argument ${TEST_SUITE}" >&2
echo >&2
echo "${HELP}" >&2
exit 1
esac
exit $SUITE_EXIT_CODE