Fix local test execution tools (#20627)

This commit is contained in:
Maksim Spirkov
2025-10-19 18:49:34 +03:00
committed by GitHub
parent ca108e2386
commit f9c1c1d6fd
17 changed files with 183 additions and 339 deletions

View File

@@ -1,9 +1,6 @@
# docker-compose test environment COMPOSE_FILE=docker-compose.yml
# Configuration files DOCKER_YII2_PHP_IMAGE=yiisoftware/yii2-php:8.4-apache
COMPOSE_FILE=docker-compose.yml:docker-compose.mysql.yml:docker-compose.pgsql.yml:docker-compose.caching.yml DOCKER_MYSQL_IMAGE=mysql
# Image versions
DOCKER_YII2_PHP_IMAGE=yiisoftware/yii2-php:7.2-apache
DOCKER_MYSQL_IMAGE=percona:5.7
DOCKER_POSTGRES_IMAGE=postgres DOCKER_POSTGRES_IMAGE=postgres
DOCKER_MEMCACHED_IMAGE=memcached

9
tests/Dockerfile.caching Normal file
View File

@@ -0,0 +1,9 @@
FROM yiisoftware/yii2-php:8.4-apache
RUN apt-get update && apt-get install -y --no-install-recommends libmemcached-dev zlib1g-dev libzip-dev
RUN pecl install memcached
RUN docker-php-ext-enable memcached
WORKDIR /project
COPY ./ /project
RUN composer install --prefer-dist

14
tests/Dockerfile.mssql Normal file
View File

@@ -0,0 +1,14 @@
FROM yiisoftware/yii2-php:8.4-apache
RUN apt-get update && apt-get install -y --no-install-recommends curl gnupg unixodbc-dev
RUN pecl install sqlsrv pdo_sqlsrv
RUN docker-php-ext-enable sqlsrv pdo_sqlsrv
# Note: Using Debian 12 (bookworm) repo since Trixie (13) is not yet officially supported by Microsoft
RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
RUN echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get update && ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18
WORKDIR /project
COPY ./ /project
RUN composer install --prefer-dist

View File

@@ -1,17 +1,13 @@
Yii 2.0 Unit tests # Yii 2.0 Unit tests
==================
DIRECTORY STRUCTURE ## DIRECTORY STRUCTURE
-------------------
data/ models, config and other test data data/ models, config and other test data
config.php this file contains configuration for database and caching backends config.php this file contains configuration for database and caching backends
framework/ the framework unit tests framework/ the framework unit tests
runtime/ the application runtime dir for the yii test app runtime/ the application runtime dir for the yii test app
## HOW TO RUN THE TESTS
HOW TO RUN THE TESTS
--------------------
Make sure you have PHPUnit installed and that you installed all composer dependencies (run `composer update` in the repo base directory). Make sure you have PHPUnit installed and that you installed all composer dependencies (run `composer update` in the repo base directory).
@@ -35,8 +31,7 @@ A single test class could be run like the following:
phpunit tests/framework/base/ObjectTest.php phpunit tests/framework/base/ObjectTest.php
``` ```
TEST CONFIGURATION ## TEST CONFIGURATION
------------------
PHPUnit configuration is in `phpunit.xml.dist` in repository root folder. PHPUnit configuration is in `phpunit.xml.dist` in repository root folder.
You can create your own phpunit.xml to override dist config. You can create your own phpunit.xml to override dist config.
@@ -54,118 +49,39 @@ $config['databases']['mysql']['username'] = 'yiitest';
$config['databases']['mysql']['password'] = 'changeme'; $config['databases']['mysql']['password'] = 'changeme';
``` ```
## DOCKERIZED TESTING
DOCKERIZED TESTING
------------------
Get started by going to the `tests` directory and copy the environment configuration. Get started by going to the `tests` directory and copy the environment configuration.
cd tests ```bash
cp .env-dist .env cd tests
cp .env-dist .env
```
The newly created `.env` file defines the configuration files used by `docker-compose`. By default MySQL, Postgres and Caching services are enabled. The newly created `.env` file defines the configuration files used by `docker-compose`. By default MySQL, Postgres etc. services are disabled.
> You can choose services available for testing by merging `docker-compose.[...].yml` files in `.env`. For example, if you only want to test with MySQL, you can modify the `COMPOSE_FILE` variable as follows > You can choose services available for testing by merging `docker-compose.[...].yml` files in `.env`. For example, if you only want to test with MySQL, you can modify the `COMPOSE_FILE` variable as follows:
> COMPOSE_FILE=docker-compose.yml:docker-compose.mysql.yml ```env
COMPOSE_FILE=docker-compose.yml:docker-compose.mysql.yml
```
When starting the stack now, you get containers for databases and caching servers to test with. > Note: The files `docker-compose.caching.yml` and `docker-compose.mssql.yml` cannot be merged with `docker-compose.yml`.
docker-compose up -d ### Running tests via shell script
After all services have been initialized and the stack is fully up and running enter the PHP container You need to go to the `tests` directory and run the `test-local.sh` script. The first argument can be: `default`, `caching`, `mssql`, `pgsql`, `mysql`. You can pass additional arguments to this script to control the behavior of PHPUnit. For example:
docker-compose exec php bash ```bash
cd tests
sh test-local.sh default --exclude caching,db
```
Run a group of unit tests ### Manually running the tests
$ vendor/bin/phpunit -v --group base --debug
#### Examples for running phpunit in a separate container
docker-compose run php vendor/bin/phpunit -v --group caching,db
docker-compose run php vendor/bin/phpunit -v --exclude base,caching,db,i18n,log,mutex,rbac,validators,web
docker-compose run php vendor/bin/phpunit -v --exclude mssql,oci,wincache,cubrid
> Note: Documentation about [installing additional extensions](https://github.com/yiisoft/yii2-docker/blob/master/docs/install-extensions.md) can be found at `yiisoft/yii2-docker`.
### Cubrid
> Note: Images for testing Cubrid are based on PHP 5, due to incompatibilities with PHP 7
cd tests/cubrid
docker-compose up -d
docker-compose run php vendor/bin/phpunit -v --group cubrid
### MSSQL
> Note: Images for testing MSSQL are based on `bylexus/apache-php7` (Ubuntu) since drivers are not available for Debian or Alpine.
**experimental**
- needs 3.5 GB RAM, Docker-host with >4.5 GB is recommended for testing
- database CLI `tsgkadot/mssql-tools`
Example commands
cd tests/mssql
Using a shell
docker-compose run --rm sqlcmd sqlcmd -S mssql -U sa -P Microsoft-12345
Create database with sqlcmd
$ sqlcmd -S mssql -U sa -P Microsoft-12345 -Q "CREATE DATABASE yii2test"
Create database (one-liner)
docker-compose run --rm sqlcmd sqlcmd -S mssql -U sa -P Microsoft-12345 -Q "CREATE DATABASE yii2test"
Run MSSQL tests
docker-compose run php
$ vendor/bin/phpunit --group mssql
### Build triggers
curl -X POST \
-F token=${TOKEN} \
-F ref=travis \
-F "variables[DOCKER_MYSQL_IMAGE]=mysql:5.6" \
-F "variables[DOCKER_POSTGRES_IMAGE]=postgres:9.5" \
${TRIGGER_URL}
### Run tests locally
#### Via shell script
cd tests
sh test-local.sh default
#### Via runner
*experimental*
docker-compose configuration
runner:
image: schmunk42/gitlab-runner
entrypoint: bash
working_dir: /project
volumes:
- ../:/project
- /var/run/docker.sock:/var/run/docker.sock
environment:
- RUNNER_BUILDS_DIR=${PWD}/..
Start runner bash
docker-compose -f docker-compose.runner.yml run runner
Execute jobs via shell runner (with docker-compose support)
$ gitlab-runner exec shell build
$ gitlab-runner exec shell test
You can also run tests manually. To do this, you need to start the container and run the tests. For example:
```bash
docker compose up -d
docker compose exec php vendor/bin/phpunit -v
```

View File

@@ -23,9 +23,9 @@ require_once __DIR__ . '/../framework/Yii.php';
Yii::setAlias('@yiiunit', __DIR__); Yii::setAlias('@yiiunit', __DIR__);
if (getenv('TEST_RUNTIME_PATH')) { if (getenv('IS_LOCAL_TESTS')) {
Yii::setAlias('@yiiunit/runtime', getenv('TEST_RUNTIME_PATH')); Yii::setAlias('@yiiunit/runtime', '/tmp/runtime');
Yii::setAlias('@runtime', getenv('TEST_RUNTIME_PATH')); Yii::setAlias('@runtime', '/tmp/runtime');
} }
require_once __DIR__ . '/TestCase.php'; require_once __DIR__ . '/TestCase.php';

View File

@@ -1,31 +0,0 @@
FROM php:5-fpm
# /usr/local/lib/php/extensions/no-debug-non-zts-20131226/cubrid.so
RUN pecl install pdo_cubrid-9.3.0.0001
RUN echo "extension=pdo_cubrid.so" > /usr/local/etc/php/conf.d/cubrid.ini
# Install system packages for composer (git)
RUN apt-get update && \
apt-get -y install \
git \
--no-install-recommends && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Register the COMPOSER_HOME environment variable
ENV COMPOSER_HOME /composer
# Add global binary directory to PATH and make sure to re-export it
ENV PATH /usr/local/bin:$PATH
# Allow Composer to be run as root
ENV COMPOSER_ALLOW_SUPERUSER 1
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- \
--filename=composer.phar \
--install-dir=/usr/local/bin
# Project source-code
WORKDIR /project
ADD composer.* /project/
RUN /usr/local/bin/composer.phar install --prefer-dist
ADD ./ /project

View File

@@ -1,17 +0,0 @@
version: '2'
services:
php:
build:
context: ../..
dockerfile: tests/cubrid/Dockerfile
ports:
- 80
#volumes:
# - ../..:/project
depends_on:
- cubrid
cubrid:
image: lighthopper/cubrid:9.3.6.0002
command: ./create-start-demodb.sh

View File

@@ -30,7 +30,7 @@ $config = [
'mysql' => [ 'mysql' => [
'dsn' => 'mysql:host=mysql;dbname=yiitest', 'dsn' => 'mysql:host=mysql;dbname=yiitest',
'username' => 'root', 'username' => 'root',
'password' => 'secret', 'password' => 'root',
'fixture' => __DIR__ . '/mysql.sql', 'fixture' => __DIR__ . '/mysql.sql',
], ],
'sqlite' => [ 'sqlite' => [
@@ -38,9 +38,9 @@ $config = [
'fixture' => __DIR__ . '/sqlite.sql', 'fixture' => __DIR__ . '/sqlite.sql',
], ],
'sqlsrv' => [ 'sqlsrv' => [
'dsn' => 'sqlsrv:Server=mssql;Database=yii2test', 'dsn' => 'sqlsrv:Server=mssql;Database=yiitest;TrustServerCertificate=true;',
'username' => 'sa', 'username' => 'SA',
'password' => 'Microsoft-12345', 'password' => 'YourStrong!Passw0rd',
'fixture' => __DIR__ . '/mssql.sql', 'fixture' => __DIR__ . '/mssql.sql',
], ],
'pgsql' => [ 'pgsql' => [

View File

@@ -1,13 +1,22 @@
version: '2'
services: services:
php: php:
build:
context: ..
dockerfile: tests/Dockerfile.caching
ports:
- 80
volumes:
- ../tests/data/config-docker.php:/project/tests/data/config.php
environment:
IS_LOCAL_TESTS: 1
depends_on: depends_on:
- redis memcached:
- memcached condition: service_healthy
redis:
image: redis
memcached: memcached:
image: memcached image: ${DOCKER_MEMCACHED_IMAGE}
healthcheck:
test: ["CMD", "timeout", "5", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/11211"]
interval: 10s
timeout: 5s
retries: 5

View File

@@ -0,0 +1,39 @@
services:
php:
build:
context: ..
dockerfile: tests/Dockerfile.mssql
ports:
- 80
volumes:
- ../tests/data/config-docker.php:/project/tests/data/config.php
environment:
IS_LOCAL_TESTS: 1
depends_on:
mssql:
condition: service_healthy
mssql:
image: mcr.microsoft.com/mssql/server:2022-latest
environment:
SA_PASSWORD: YourStrong!Passw0rd
ACCEPT_EULA: Y
MSSQL_PID: Developer
healthcheck:
test:
[
"CMD",
"/opt/mssql-tools18/bin/sqlcmd",
"-C",
"-S",
"localhost",
"-U",
"SA",
"-P",
"YourStrong!Passw0rd",
"-Q",
"'SELECT 1'",
]
interval: 10s
timeout: 3s
retries: 5

View File

@@ -1,15 +1,16 @@
version: '2'
services: services:
php: php:
depends_on: depends_on:
- mysql mysql:
condition: service_healthy
mysql: mysql:
image: ${DOCKER_MYSQL_IMAGE} image: ${DOCKER_MYSQL_IMAGE}
environment: environment:
- MYSQL_ROOT_PASSWORD=secret MYSQL_ROOT_PASSWORD: root
- MYSQL_DATABASE=yiitest MYSQL_DATABASE: yiitest
- MYSQL_USER=travis healthcheck:
- MYSQL_PASSWORD=travis test: ["CMD", "mysql", "-uroot", "-proot", "-e", "SELECT 1"]
interval: 10s
timeout: 3s
retries: 5

View File

@@ -1,14 +1,17 @@
version: '2'
services: services:
php: php:
depends_on: depends_on:
- postgres postgres:
condition: service_healthy
postgres: postgres:
image: ${DOCKER_POSTGRES_IMAGE} image: ${DOCKER_POSTGRES_IMAGE}
environment: environment:
- POSTGRES_DB=yiitest POSTGRES_DB: yiitest
- POSTGRES_USER=postgres POSTGRES_USER: postgres
- POSTGRES_PASSWORD=postgres POSTGRES_PASSWORD: postgres
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 3s
retries: 5

View File

@@ -1,6 +1,4 @@
version: '2'
services: services:
php: php:
build: build:
context: .. context: ..
@@ -9,11 +7,5 @@ services:
working_dir: /project working_dir: /project
volumes: volumes:
- ../tests/data/config-docker.php:/project/tests/data/config.php - ../tests/data/config-docker.php:/project/tests/data/config.php
# Enable for debugging, enabling tests might be slow for file access (data) on host-volume
- ../tests:/project/tests
- ../framework:/project/framework
# Tmpfs volume (experimental, asset tests may fail)
#tmpfs:
# - /project/tests/runtime
environment: environment:
- TEST_RUNTIME_PATH=/tmp/runtime IS_LOCAL_TESTS: 1

View File

@@ -36,13 +36,23 @@ class MemCachedTest extends CacheTestCase
$this->markTestSkipped("memcached version $memcached_version is not ready for PHP $php_version. Skipping."); $this->markTestSkipped("memcached version $memcached_version is not ready for PHP $php_version. Skipping.");
} }
$memcachedHost = getenv('IS_LOCAL_TESTS') ? 'memcached' : '127.0.0.1';
// check whether memcached is running and skip tests if not. // check whether memcached is running and skip tests if not.
if (!@stream_socket_client('127.0.0.1:11211', $errorNumber, $errorDescription, 0.5)) { if (!@stream_socket_client("$memcachedHost:11211", $errorNumber, $errorDescription, 0.5)) {
$this->markTestSkipped('No memcached server running at ' . '127.0.0.1:11211' . ' : ' . $errorNumber . ' - ' . $errorDescription); $this->markTestSkipped('No memcached server running at ' . "$memcachedHost:11211" . ' : ' . $errorNumber . ' - ' . $errorDescription);
} }
if ($this->_cacheInstance === null) { if ($this->_cacheInstance === null) {
$this->_cacheInstance = new MemCache(['useMemcached' => true]); $this->_cacheInstance = new MemCache([
'useMemcached' => true,
'servers' => [
[
'host' => $memcachedHost,
'port' => 11211,
],
],
]);
} }
return $this->_cacheInstance; return $this->_cacheInstance;

View File

@@ -1,56 +0,0 @@
FROM bylexus/apache-php7
# https://www.microsoft.com/en-us/sql-server/developer-get-started/php-ubuntu
RUN apt-get update
RUN apt-get install -y curl apt-transport-https
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get update \
&& apt-get install -y unixodbc-dev-utf16 php-dev \
&& pecl install sqlsrv pdo_sqlsrv
RUN echo ";priority=20\nextension=sqlsrv.so" > /etc/php/7.0/cli/conf.d/20-sqlsrv.ini
RUN echo ";priority=20\nextension=sqlsrv.so" > /etc/php/7.0/apache2/conf.d/20-sqlsrv.ini
RUN echo ";priority=30\nextension=pdo_sqlsrv.so" > /etc/php/7.0/cli/conf.d/30-pdo_sqlsrv.ini
RUN echo ";priority=30\nextension=pdo_sqlsrv.so" > /etc/php/7.0/apache2/conf.d/30-pdo_sqlsrv.ini
# IMPORTANT NOTICE! Install `msodbcsql` after `unixodbc-dev-utf16` and `pdo_sqlsrv`, due to dependency & build issues
RUN ACCEPT_EULA=Y apt-get install -y msodbcsql
# Install system packages for composer (git)
RUN apt-get update && \
apt-get -y install \
git \
php-curl \
--no-install-recommends && \
rm -rf /tmp/* /var/tmp/*
# Register the COMPOSER_HOME environment variable
ENV COMPOSER_HOME /composer
# Add global binary directory to PATH and make sure to re-export it
ENV PATH /usr/local/bin:$PATH
# Allow Composer to be run as root
ENV COMPOSER_ALLOW_SUPERUSER 1
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- \
--filename=composer.phar \
--install-dir=/usr/local/bin
RUN composer.phar global require --optimize-autoloader \
"hirak/prestissimo"
# Project source-code
WORKDIR /project
ADD composer.* /project/
RUN /usr/local/bin/composer.phar install --prefer-dist
ADD ./ /project
# https://github.com/Microsoft/msphpsql/issues/161
RUN apt-get install -y locales \
&& echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
&& locale-gen
# Debug installation
RUN dpkg -L msodbcsql

View File

@@ -1,36 +0,0 @@
version: '2'
services:
php:
build:
context: ../..
dockerfile: tests/mssql/Dockerfile
# Alternative pre-built image (TODO: evaluate)
#image: ppoffice/apache-php-mssql-odbc
ports:
- 80
# Enable for debugging, Note: File-cache tests may be VERY slow or fail
#volumes:
# - ../../..:/project
volumes:
- ../../tests/data/config-docker.php:/project/tests/data/config.php
depends_on:
- mssql
# Enable for debugging
#entrypoint: ['bash']
mssql:
image: microsoft/mssql-server-linux
# Alternative pre-built image (TODO: evaluate)
#image: microsoft/mssql-server-windows
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=Microsoft-12345
sqlcmd:
image: tsgkadot/mssql-tools
# Mount project for accessing SQL dump (TODO)
volumes:
- ../..:/project
# Enable for debugging
#entrypoint: ['bash']

View File

@@ -1,51 +1,45 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Generate a "hash" from 0-99 for subnet tuple (10, 11, ..., 199) - it's a hack # TODO: add mariadb, sqlite and oracle
echo "Creating CI_BUILD_ID and CI_PIPELINE_ID from first argument..."
export CI_BUILD_ID=$(expr $((32#${1})) % 99)
export CI_PIPELINE_ID=${1}
# Copy snippets from https://git.hrzg.de/ci/lint
case $1 in case $1 in
'default') 'default')
export ISOLATION=buildpipeline${CI_PIPELINE_ID} shift
export COMPOSE_PROJECT_NAME=${ISOLATION}default docker compose up -d
docker-compose up -d docker compose run --rm php vendor/bin/phpunit -v $@
docker-compose run --rm php vendor/bin/phpunit -v --exclude caching,db docker compose down -v
docker-compose down -v
;; ;;
'caching') 'caching')
export ISOLATION=buildpipeline${CI_PIPELINE_ID} export COMPOSE_FILE=docker-compose.caching.yml
export COMPOSE_PROJECT_NAME=${ISOLATION}caching export COMPOSE_PROJECT_NAME=yii2tests-default
docker-compose up -d shift
docker-compose run --rm php bash -c "while ! curl mysql:3306; do ((c++)) && ((c==30)) && break; sleep 2; done" docker compose up --build -d
docker-compose run --rm php vendor/bin/phpunit -v --group caching docker compose run --rm php vendor/bin/phpunit -v --group caching --exclude-group db $@
docker-compose down -v docker compose down -v --remove-orphans
;; ;;
'mssql') 'mssql')
export ISOLATION=buildpipeline${CI_PIPELINE_ID} export COMPOSE_FILE=docker-compose.mssql.yml
export COMPOSE_PROJECT_NAME=${ISOLATION}mssql export COMPOSE_PROJECT_NAME=yii2tests-mssql
cd mssql shift
docker-compose up --build -d docker compose up --build -d
docker-compose run --rm php bash -c 'while [ true ]; do curl mssql:1433; if [ $? == 52 ]; then break; fi; ((c++)) && ((c==15)) && break; sleep 5; done' docker compose run --rm mssql /opt/mssql-tools18/bin/sqlcmd -C -S mssql -U SA -P YourStrong!Passw0rd -Q "CREATE DATABASE yiitest"
sleep 10 docker compose run --rm php vendor/bin/phpunit -v --group mssql $@
docker-compose run --rm sqlcmd sh -c 'sqlcmd -S mssql -U sa -Q "CREATE DATABASE yii2test" -P Microsoft-12345' docker compose down -v --remove-orphans
sleep 10
docker-compose logs mssql
docker-compose config
pwd
docker-compose ps
docker-compose run --rm php php -i
docker-compose run --rm php vendor/bin/phpunit -v --group mssql
docker-compose down -v --remove-orphans
;; ;;
'pgsql') 'pgsql')
export ISOLATION=buildpipeline${CI_PIPELINE_ID} export COMPOSE_FILE=docker-compose.yml:docker-compose.pgsql.yml
export COMPOSE_PROJECT_NAME=${ISOLATION}pgsql export COMPOSE_PROJECT_NAME=yii2tests-pgsql
docker-compose up -d shift
docker-compose run --rm php bash -c 'while [ true ]; do curl postgres:5432; if [ $? == 52 ]; then break; fi; ((c++)) && ((c==25)) && break; sleep 2; done' docker compose up -d
docker-compose run --rm php vendor/bin/phpunit -v --group pgsql docker compose run --rm php vendor/bin/phpunit -v --group pgsql $@
docker-compose down -v docker compose down -v
;;
'mysql')
export COMPOSE_FILE=docker-compose.yml:docker-compose.mysql.yml
export COMPOSE_PROJECT_NAME=yii2tests-mysql
shift
docker compose up -d
docker compose run --rm php vendor/bin/phpunit -v --group mysql $@
docker compose down -v
;; ;;
*) *)
echo "Warning: No job argument specified" echo "Warning: No job argument specified"