From 6784e27f48ef6664dbec114f48151bba58df8f34 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Wed, 10 Sep 2025 14:57:45 -0400 Subject: [PATCH 1/5] install xdebug in web container, specify source directory for phpunit --- phpunit.xml | 5 +++++ tools/docker-dev/web/Dockerfile | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/phpunit.xml b/phpunit.xml index 746f6a79..f2e00769 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -13,4 +13,9 @@ test/functional + + + resources/lib + + diff --git a/tools/docker-dev/web/Dockerfile b/tools/docker-dev/web/Dockerfile index 40198b24..d599c276 100644 --- a/tools/docker-dev/web/Dockerfile +++ b/tools/docker-dev/web/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y \ php-cli \ php-mbstring \ php-xml \ - php-intl + php-intl \ + php-xdebug COPY htpasswd /etc/apache2/.htpasswd RUN chown www-data /etc/apache2/.htpasswd COPY unity-apache.conf /etc/apache2/sites-available/unity.conf From 87018083ec434ab919da082510f29da2f83f4a58 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Wed, 10 Sep 2025 15:28:31 -0400 Subject: [PATCH 2/5] setup code coverage requirement in github actions --- .github/workflows/functional.yml | 27 --------------------------- .github/workflows/phpunit.yml | 25 +++++++++++++++---------- composer.json | 3 ++- phpunit.xml | 6 ++++++ tools/docker-dev/web/Dockerfile | 1 + 5 files changed, 24 insertions(+), 38 deletions(-) delete mode 100644 .github/workflows/functional.yml diff --git a/.github/workflows/functional.yml b/.github/workflows/functional.yml deleted file mode 100644 index 783539c7..00000000 --- a/.github/workflows/functional.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: docker-compose-phpunit-functional - -on: - pull_request: - push: - branches: [main] - -jobs: - docker-compose-phpunit-functional: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - name: setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: "8.3" - tools: composer - - name: install composer dependencies - run: composer update - - name: Run docker compose - uses: hoverkraft-tech/compose-action@v2.0.1 - with: - compose-file: "./tools/docker-dev/docker-compose.yml" - - name: Execute tests in the running services - run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web ./vendor/bin/phpunit --testsuite=functional diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index b05c2abf..69047505 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -1,9 +1,12 @@ -name: phpunit +name: docker-compose-phpunit -on: [push] +on: + pull_request: + push: + branches: [main] jobs: - phpunit: + docker-compose-phpunit-functional: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -13,10 +16,12 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: "8.3" - # php extensions also listed in tools/docker-dev/web/Dockerfile and README.md - extensions: curl,mysql,ldap,pdo,redis,intl - tools: composer:v2 - - name: Install dependencies - run: composer install --prefer-dist --no-progress - - name: Run PHPUnit tests - run: vendor/bin/phpunit --colors=always --testsuite unit + tools: composer + - name: install composer dependencies + run: composer update + - name: Run docker compose + uses: hoverkraft-tech/compose-action@v2.0.1 + with: + compose-file: "./tools/docker-dev/docker-compose.yml" + - name: Execute tests in the running services + run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web bash -c 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-clover=path/to/clover.xml -d --min-coverage=65' diff --git a/composer.json b/composer.json index 45e6d7ec..2232137c 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,7 @@ "phpmailer/phpmailer": "6.6.4" }, "require-dev": { - "phpunit/phpunit": "<12.1" + "phpunit/phpunit": "<12.1", + "robiningelbrecht/phpunit-coverage-tools": "<2" } } diff --git a/phpunit.xml b/phpunit.xml index f2e00769..9f800960 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -18,4 +18,10 @@ resources/lib + + + + + + diff --git a/tools/docker-dev/web/Dockerfile b/tools/docker-dev/web/Dockerfile index d599c276..4e04a310 100644 --- a/tools/docker-dev/web/Dockerfile +++ b/tools/docker-dev/web/Dockerfile @@ -28,6 +28,7 @@ RUN sed -i '/display_errors/c\display_errors = on' /etc/php/8.3/apache2/php.ini RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/apache2/php.ini RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/cli/php.ini RUN sed -i '/memory_limit/c\memory_limit = -1' /etc/php/8.3/apache2/php.ini +RUN echo 'xdebug.mode=coverage' >> /etc/php/8.3/apache2/php.ini # Start apache2 server EXPOSE 80 From 1404ac10891ef379f9efdab6b5b7cfe752f70033 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Wed, 10 Sep 2025 15:29:38 -0400 Subject: [PATCH 3/5] change name of action --- .github/workflows/phpunit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 69047505..3116589f 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -6,7 +6,7 @@ on: branches: [main] jobs: - docker-compose-phpunit-functional: + docker-compose-phpunit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From 02db4714a92e55bc97a9ac01043fb2908d8fdf70 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Wed, 10 Sep 2025 16:01:04 -0400 Subject: [PATCH 4/5] document testing --- CONTRIBUTING.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a05dc7f..eece9421 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,6 +7,7 @@ * The maximum line length for any PHP file is 100 characters, instead of PSR-12's 120 characters. * Comments should be used sparingly. * Empty lines should be used sparingly. +* No code should call `die()` or `exit()`, instead `UnitySite::die()`. This repository will automatically check PRs for linting compliance. @@ -56,3 +57,50 @@ Notable users: ### Changes to Dev Environment Should the default schema of the web portal change, the `ldap/bootstrap.ldif` and `sql/bootstrap.sql` must be updated for the LDAP server and the MySQL server, respectively. + +## Testing + +Github Actions are used to execute all following tests for all pull requests. +This means that if you're feeling lazy, you don't have to go out of your way to run tests, you just have to wait a bit longer for Github to do it for you. + +### `pre-commit` + +We use `pre-commit` for enforcing (and sometimes automatically fixing) the PSR-12 code standard, whitespace discrepancies, syntax validity, secret leak detection, and whatever else can be done quickly. +`pre-commit` runs automatically every time you commit, assuming you set it up correctly. +To save time, `pre-commit` only runs on the files with staged changes. +To run on all files, use `pre-commit run --all-files`. + +### `phpunit` + +Since this codebase was not written with testing in mind, and this codebase makes extensive use of external resources such as SQL and LDAP, most of our testing does not focus on isolated "units", but high level functionality. +Our functional tests pretend to make HTTP requests by modifying global variables in the same way that a production webserver would. +This is preferred over directly calling library code because it helps to test the PHP logic in the webpages themselves, rather than just the internals. +For example, one functional test would be to set `$_SERVER["REMOTE_USER"]` to authenticate as a user, `require "resources/init.php"` to setup the `$USER` global variable, set `$_POST["key"] = "ssh-rsa ..."` and `require "webroot/panel/account.php"` to make that user enter a new SSH key in the HTML form in the `account.php` page. +Once a user action has been taken, internal interfaces are used to verify the results. + +To run `phpunit`, spawn 2 shells in differnt tabs: + +tab 1: +```shell +cd ./tools/docker-dev +./build.sh +./run.sh +``` + +tab 2: +``` +$ container="$(docker container ls | grep web | awk '{print $1}')" +$ docker exec "$container" -it bash +> cd /var/www/unity-web +> ./vendor/bin/phpunit /path/to/tests +``` + +For `/path/to/tests/`, you usually want `./test/functional/` but you can select a specific file to save time when troubleshooting specific tests. + +### code coverage + +`phpunit` has code coverage built in. +It recommends the use of "strict code coverage", where every single test explicitly lists what functions it covers. +That's a lot of work, so instead we accept what phpunit refers to as "risky unintentionally covered code". +Using [robiningelbrecht/phpunit-coverage-tools](https://github.com/robiningelbrecht/phpunit-coverage-tools), our Github Actions testing will fail if the coverage falls below a certain percentage of lines of code. +This percentage should be increased over time to just below whatever the current coverage is. From 5bcdb173292c3510c5cb59266ced82529f41b04a Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Wed, 10 Sep 2025 16:12:19 -0400 Subject: [PATCH 5/5] move minimum coverage to a file, fix dockerfile, more docs --- .github/workflows/phpunit.yml | 2 +- CONTRIBUTING.md | 2 ++ coverage.php | 11 +++++++++++ phpunit.xml | 1 - tools/docker-dev/web/Dockerfile | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 coverage.php diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 3116589f..84702a15 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -24,4 +24,4 @@ jobs: with: compose-file: "./tools/docker-dev/docker-compose.yml" - name: Execute tests in the running services - run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web bash -c 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-clover=path/to/clover.xml -d --min-coverage=65' + run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web bash -c 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-clover="$(mktemp --suffix=.xml)" -d --min-coverage=./coverage.php' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eece9421..fefa07f0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -104,3 +104,5 @@ It recommends the use of "strict code coverage", where every single test explici That's a lot of work, so instead we accept what phpunit refers to as "risky unintentionally covered code". Using [robiningelbrecht/phpunit-coverage-tools](https://github.com/robiningelbrecht/phpunit-coverage-tools), our Github Actions testing will fail if the coverage falls below a certain percentage of lines of code. This percentage should be increased over time to just below whatever the current coverage is. + +To run a code coverage test, use the same procedure for phpunit but add these arguments: `--coverage-clover="$(mktemp --suffix=.xml)" -d --min-coverage=./coverage.php` diff --git a/coverage.php b/coverage.php new file mode 100644 index 00000000..d55489ae --- /dev/null +++ b/coverage.php @@ -0,0 +1,11 @@ + - diff --git a/tools/docker-dev/web/Dockerfile b/tools/docker-dev/web/Dockerfile index 4e04a310..a65eee49 100644 --- a/tools/docker-dev/web/Dockerfile +++ b/tools/docker-dev/web/Dockerfile @@ -28,7 +28,7 @@ RUN sed -i '/display_errors/c\display_errors = on' /etc/php/8.3/apache2/php.ini RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/apache2/php.ini RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/cli/php.ini RUN sed -i '/memory_limit/c\memory_limit = -1' /etc/php/8.3/apache2/php.ini -RUN echo 'xdebug.mode=coverage' >> /etc/php/8.3/apache2/php.ini +RUN echo 'xdebug.mode=coverage' >> /etc/php/8.3/cli/php.ini # Start apache2 server EXPOSE 80