🐘Advanced PHP autograding

Discover the advanced autograding options available for PHP assignments

In this guide, we explore the advanced grading options available for PHP assignments. For more information about setting up a PHP assignment from scratch, see:

🐘pageCreate your first PHP assignment

Unit tests with PHPUnit

PHPUnit is an industry-standard unit testing framework for PHP. It is particularly useful for grading assignments that require students to write functions and classes. Using PHPUnit unit tests offers several advantages over conventional IO tests, including the ability to use assertions, parametrize test cases, and provide better feedback for students. For further documentation about PHPUnit we recommend this online resource.

Consider the example submission Fibonacci.php file below:

<?php

function PrintFibonacci($n) {
    $num1 = 0;
    $num2 = 1;

    echo "$num1\n";
    echo "$num2\n";

    for ($i = 2; $i < $n; $i++) {
        $num3 = $num1 + $num2;
        echo "$num3\n";
        $num1 = $num2;
        $num2 = $num3;
    }
}

function ComputeFibonacci($n) {
    if ($n == 0) {
        return 0;
    }
    if ($n == 1) {
        return 1;
    }
    if ($n == 2) {
        return 1;
    }
    $num1 = 0;
    $num2 = 1;

    for ($i = 2; $i <= $n; $i++) {
        $num3 = $num1 + $num2;
        $num1 = $num2;
        $num2 = $num3;
    }
    return $num3;
}

$number = (int)readline("Enter the number of terms: ");
PrintFibonacci($number);

Our goal is to unit test the ComputeFibonacci function. Our tests are defined in the following FibonacciTests.php file:

<?php

use PHPUnit\Framework\TestCase;

include('./Fibonacci.php');

class FibonacciTests extends TestCase
{
    public function testFibonacciZero()
    {
        $this->assertEquals(0, ComputeFibonacci(0));
    }

    public function testFibonacciOne()
    {
        $this->assertEquals(1, ComputeFibonacci(5));
    }

    public function testFibonacciTwo()
    {
        $this->assertEquals(1, ComputeFibonacci(2));
    }

    public function testFibonacciThree()
    {
        $this->assertEquals(2, ComputeFibonacci(3));
    }

    public function testFibonacciTen()
    {
        $this->assertEquals(55, ComputeFibonacci(10));
    }

    public function testFibonacciTwenty()
    {
        $this->assertEquals(6765, ComputeFibonacci(20));
    }
}

Setup: Install PHPUnit

After installing PHP as described in the previous guide, we can use Script Block to install Composer, a PHP dependency management framework, and then PHPUnit.

In the Install php dependecies Script block above, we run the following Bash script:

set -e

# install composer
yes | sudo apt install php-cli unzip
curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
HASH=`curl -sS https://composer.github.io/installer.sig`
php -r "if (hash_file('SHA384', '/tmp/composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer

# install php dependencies
sudo apt-get update
sudo apt-get install php-xml
sudo apt-get install php-mbstring

# install php tools
composer require --dev phpunit/phpunit:^9.5

# add the tools to the path
echo 'export PATH=$PATH:~/vendor/phpunit' >> ~/.cg_bash_env
echo 'export PATH=$PATH:~/vendor/bin' >> ~/.cg_bash_env

Test execution

Once we are done with the Setup Phase in AutoTest, we can move on to the next Tests phase. Here, we first need to upload our testing file FibonacciTests.php using an Upload Files Block.

We can then run our unit tests using a Custom Test Block as shown below:

The Custom Test Block runs the following commands:

set -e

# move the necessary files to the current directory
cp $UPLOADED_FILES/* . 
mv  ~/composer.json .

# wrap a bash script around phpunit (needed to handle the exit code returned by phpunit)
cat <<EOF > script.sh
phpunit --log-junit report.xml FibonacciTests.php 
cg junitxml report.xml
exit 0
EOF

# run the script that calls phpunit
chmod +x script.sh 
./script.sh

Notice that you can hide these commands from the students using a Hide Block.

The results of the unit tests will be shown to the student as below:

Code Quality Tests with PHP_CodeSniffer

PHP_CodeSniffer is an industry-standard linter for PHP that allows you to enforce rules from various coding standards. It is a useful tool for enforcing code styling best practices for beginner programmers. To read more about PHP_CodeSniffer, we recommend this online resource.

Setup: Install php_codesniffer

We can repeat the same steps described in the section above for installing PHPUnit, just now the installing script is slightly different:

set -e

# install composer
yes | sudo apt install php-cli unzip
curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
HASH=`curl -sS https://composer.github.io/installer.sig`
php -r "if (hash_file('SHA384', '/tmp/composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer

# install php dependencies
sudo apt-get update
sudo apt-get install php-xml
sudo apt-get install php-mbstring

# install php tools
composer require --dev squizlabs/php_codesniffer

# add the tools to the path
echo 'export PATH=$PATH:~/vendor/phpunit' >> ~/.cg_bash_env
echo 'export PATH=$PATH:~/vendor/bin' >> ~/.cg_bash_env

Test execution

We can run PHP_Codesniffer on a student file, Fibonacci.php` in the example below, through a Custom Test Block:

Within the Custom Test Block, we run the following script:

set -e

# wrap a bash script around phpcs (needed to handle the exit code returned by phpcs)
cat <<EOF > script.sh
phpcs --report=checkstyle --standard=PSR12 ./Fibonacci.php > report.xml
cg checkstyle parse report.xml
exit 0
EOF

# run the script that calls phpcs
chmod +x script.sh 
./script.sh

Running the Code Quality Test will produce inline comments within the student submission, as shown below:

Last updated