Skip to content

Commit dd47da4

Browse files
authored
code coverage (#299)
* install xdebug in web container, specify source directory for phpunit * setup code coverage requirement in github actions * change name of action * document testing * move minimum coverage to a file, fix dockerfile, more docs
1 parent 7fe817d commit dd47da4

File tree

7 files changed

+91
-39
lines changed

7 files changed

+91
-39
lines changed

.github/workflows/functional.yml

Lines changed: 0 additions & 27 deletions
This file was deleted.

.github/workflows/phpunit.yml

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
name: phpunit
1+
name: docker-compose-phpunit
22

3-
on: [push]
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
47

58
jobs:
6-
phpunit:
9+
docker-compose-phpunit:
710
runs-on: ubuntu-latest
811
steps:
912
- uses: actions/checkout@v3
@@ -13,10 +16,12 @@ jobs:
1316
uses: shivammathur/setup-php@v2
1417
with:
1518
php-version: "8.3"
16-
# php extensions also listed in tools/docker-dev/web/Dockerfile and README.md
17-
extensions: curl,mysql,ldap,pdo,redis,intl
18-
tools: composer:v2
19-
- name: Install dependencies
20-
run: composer install --prefer-dist --no-progress
21-
- name: Run PHPUnit tests
22-
run: vendor/bin/phpunit --colors=always --testsuite unit
19+
tools: composer
20+
- name: install composer dependencies
21+
run: composer update
22+
- name: Run docker compose
23+
uses: hoverkraft-tech/compose-action@v2.0.1
24+
with:
25+
compose-file: "./tools/docker-dev/docker-compose.yml"
26+
- name: Execute tests in the running services
27+
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'

CONTRIBUTING.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* The maximum line length for any PHP file is 100 characters, instead of PSR-12's 120 characters.
88
* Comments should be used sparingly.
99
* Empty lines should be used sparingly.
10+
* No code should call `die()` or `exit()`, instead `UnitySite::die()`.
1011

1112
This repository will automatically check PRs for linting compliance.
1213

@@ -56,3 +57,52 @@ Notable users:
5657
### Changes to Dev Environment
5758

5859
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.
60+
61+
## Testing
62+
63+
Github Actions are used to execute all following tests for all pull requests.
64+
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.
65+
66+
### `pre-commit`
67+
68+
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.
69+
`pre-commit` runs automatically every time you commit, assuming you set it up correctly.
70+
To save time, `pre-commit` only runs on the files with staged changes.
71+
To run on all files, use `pre-commit run --all-files`.
72+
73+
### `phpunit`
74+
75+
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.
76+
Our functional tests pretend to make HTTP requests by modifying global variables in the same way that a production webserver would.
77+
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.
78+
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.
79+
Once a user action has been taken, internal interfaces are used to verify the results.
80+
81+
To run `phpunit`, spawn 2 shells in differnt tabs:
82+
83+
tab 1:
84+
```shell
85+
cd ./tools/docker-dev
86+
./build.sh
87+
./run.sh
88+
```
89+
90+
tab 2:
91+
```
92+
$ container="$(docker container ls | grep web | awk '{print $1}')"
93+
$ docker exec "$container" -it bash
94+
> cd /var/www/unity-web
95+
> ./vendor/bin/phpunit /path/to/tests
96+
```
97+
98+
For `/path/to/tests/`, you usually want `./test/functional/` but you can select a specific file to save time when troubleshooting specific tests.
99+
100+
### code coverage
101+
102+
`phpunit` has code coverage built in.
103+
It recommends the use of "strict code coverage", where every single test explicitly lists what functions it covers.
104+
That's a lot of work, so instead we accept what phpunit refers to as "risky unintentionally covered code".
105+
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.
106+
This percentage should be increased over time to just below whatever the current coverage is.
107+
108+
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`

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"phpmailer/phpmailer": "6.6.4"
66
},
77
"require-dev": {
8-
"phpunit/phpunit": "<12.1"
8+
"phpunit/phpunit": "<12.1",
9+
"robiningelbrecht/phpunit-coverage-tools": "<2"
910
}
1011
}

coverage.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRule;
4+
5+
return [
6+
new MinCoverageRule(
7+
pattern: '*',
8+
minCoverage: 65,
9+
exitOnLowCoverage: true
10+
),
11+
];

phpunit.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,14 @@
1313
<directory>test/functional</directory>
1414
</testsuite>
1515
</testsuites>
16+
<source>
17+
<include>
18+
<directory suffix=".php">resources/lib</directory>
19+
</include>
20+
</source>
21+
<extensions>
22+
<bootstrap class="RobinIngelbrecht\PHPUnitCoverageTools\PhpUnitExtension">
23+
<parameter name="cleanUpCloverXml" value="1"/>
24+
</bootstrap>
25+
</extensions>
1626
</phpunit>

tools/docker-dev/web/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y \
1515
php-cli \
1616
php-mbstring \
1717
php-xml \
18-
php-intl
18+
php-intl \
19+
php-xdebug
1920
COPY htpasswd /etc/apache2/.htpasswd
2021
RUN chown www-data /etc/apache2/.htpasswd
2122
COPY unity-apache.conf /etc/apache2/sites-available/unity.conf
@@ -27,6 +28,7 @@ RUN sed -i '/display_errors/c\display_errors = on' /etc/php/8.3/apache2/php.ini
2728
RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/apache2/php.ini
2829
RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/cli/php.ini
2930
RUN sed -i '/memory_limit/c\memory_limit = -1' /etc/php/8.3/apache2/php.ini
31+
RUN echo 'xdebug.mode=coverage' >> /etc/php/8.3/cli/php.ini
3032

3133
# Start apache2 server
3234
EXPOSE 80

0 commit comments

Comments
 (0)