Install PHPUnit with VisualPHPUnit on a Shared Hosting Server

Update: The 4.x branch of PHPUnit has some changes, such as no longer using Autoload.php, that make this tutorial outdated. I’ll try to see if the new versions can be run on shared hosting as well, but in the meantime, the following instructions only apply for PHPUnit 3.x.

Here’s how to install and run PHPUnit with the VisualPHPUnit graphical interface, on any shared hosting server, without need for PEAR, composer, phar, or SSH command line; in fact all you need is your web browser, FTP access, and a code editor such as Notepad++.

PHPUnit: Dependency Madness

PHPUnit is the best case against the DRY philosophy I’ve ever came across, since it’s chock-full of random dependencies you won’t even be using for anything else. As such, be prepared to download and extract a helluva lot of packages.

First of all create a folder on your computer for housing all necessary files and directories, I’ve named mine Utilities for reference. Now go to https://github.com/sebastianbergmann/phpunit/branches and check the requirements of every numbered version until you find the newest one that will run on the php version you’ve got on your server. If you don’t know which version of php you’re using, run phpinfo() to find out. Download the zip for your version, and extract just the PHPUnit folder inside into Utilities.

Go to https://github.com/sebastianbergmann/php-file-iterator, download the zip and extract just the File folder into Utilities.

Go to https://github.com/sebastianbergmann/php-text-template, download the zip and extract just the Text folder into Utilities.

For the next 3 packages, download the zip files and extract just the PHP folder in each zip into Utilities (merge the folders): https://github.com/sebastianbergmann/php-code-coverage
https://github.com/sebastianbergmann/php-timer
https://github.com/sebastianbergmann/php-token-stream

Now create a folder inside Utilities called SebastianBergmann . Now create 3 folders inside SebastianBergmann, called: Diff , Exporter , and Version . For the next 3 packages, download the zip files and extract just the contents of the src folder (not the folder itself, only its contents) in each one into the corresponding folder inside SebastianBergmann: https://github.com/sebastianbergmann/diff
https://github.com/sebastianbergmann/exporter
https://github.com/sebastianbergmann/version

Finally, go to https://github.com/sebastianbergmann/phpunit-mock-objects, download the zip and extract just the PHPUnit folder into Utilities (merge it with the existing folder).

Great, now that you’ve got PHPUnit and all its dependencies, upload the “Utilities” folder to your server, preferably into a non web-accesible location. For reference, your folder tree should look like this:

folder tree

VisualPHPUnit: Let there be GUI

Now that PHPUnit is on your server, let’s make it usable with a web browser based GUI. Download the zip from https://github.com/NSinopoli/VisualPHPUnit, extract it, and rename the main folder if you want (I creatively renamed mine to VisualPHPUnit for reference).

Go into app/config/bootstrap.php and make the following changes:

  • Comment or delete the following line: 'pear_path' => '/usr/share/pear',
  • The default directory for tests is VisualPHPUnit/app/test , if you wish to change it or add other directories, modify the ‘test_directories’ array. By the way, $root points to the VisualPHPUnit folder.
  • Comment or delete the following lines: set_include_path( get_include_path() . PATH_SEPARATOR . $root . PATH_SEPARATOR . $config['pear_path'] );
  • Below the lines you just commented, add the following two, changing the relative paths so that they point to your Utilities folder from the web-accessible folder where you’ll upload the VisualPHPUnit package: set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/../Utilities'); set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/../Utilities' . '/PHPUnit');

Now upload your VisualPHPUnit folder to a web-accessible location on your server. Fire up your browser, open your VisualPHPUnit location, and see if you feel lucky.

Well do you, punk?

If your stars have aligned now you should have a working install of PHPUnit with VisualPHPUnit. If not, it’s troubleshooting time!

“Fatal error: require_once() [function.require]: Failed opening required ‘PHPUnit/Autoload.php'”

Your include paths in VisualPHPUnit/app/config/bootstrap.php are wrong, sort them out

“Fatal error: require_once() [function.require]: Failed opening required {any other file related to phpunit}

You missed a PHPUnit dependency, you can find all the packages you need (and then some more) at https://github.com/sebastianbergmann?tab=repositories

“404: Not Found” error / You just get the Index of your /VisualPHPUnit folder

You’ve got the curse of the .htaccess, brought on by lazy open-source web development practices. There are 2 .htaccess files in VisualPHPUnit that are used to redirect requests, and we need to fix them.

First open the .htaccess file in the “VisualPHPUnit” folder.

  • Find the following line:
    RewriteRule ^$ app/public/ [L] add an [R] flag so that you can see the redirected address in your browser, so the line becomes:
    RewriteRule ^$ app/public/ [L,R]
  • Go to your web browser, reload your VisualPHPUnit tab, and check the address to which you’re being redirected. It should be {your VisualPHPUnit location}/app/public/ . Since it’s not, find the following line in your .htaccess file:
    RewriteEngine on and insert the following line after it: RewriteBase /
  • Reload again your browser tab, and check where you’re being redirected now. Part of the path will probably be missing in the middle, so you’ll need to edit the line you just added so that your browser ends up redirecting you correctly to {your VisualPHPUnit location}/app/public/ . In my case I had to change it to this:
    RewriteBase /VisualPHPUnit/
  • Once you get redirected to the correct address, you need to remove the [R] flag you set at the beginning, so that the line you modified to
    RewriteRule ^$ app/public/ [L,R] becomes once again
    RewriteRule ^$ app/public/ [L]
Your browser should load VisualPHPUnit now, but tests will not work since we need to fix the remaining redirection. Go into VisualPHPUnit/app/public and open the .htaccess file there.
  • Find the following line:
    RewriteRule ^(.*)$ index.php [QSA,L] and insert the [R] redirection flag as before, so the line becomes:
    RewriteRule ^(.*)$ index.php [QSA,L,R]
  • Go to your browser and open the link on the top of your VisualPHPUnit tab that says “Archives”. Check the address bar to see where you are being redirected. You should be redirected to {your VisualPHPUnit location}/app/public/index.php . Since you’re not, you know the drill, find the following line in your .htaccess file:
    RewriteEngine on and insert the following line after it: RewriteBase /
  • Reload your browser tab, check where you’re being redirected and what’s missing in the path, and modify the line you just added until the redirection takes you to the correct address. In my case, I had to change it to this:
    RewriteBase /VisualPHPUnit/app/public/
  • Once you get redirected to the correct address, you need to remove the [R] flag you set, so that the line you modified to
    RewriteRule ^(.*)$ index.php [QSA,L,R] becomes once again
    RewriteRule ^(.*)$ index.php [QSA,L]
Now you should be able to see the files in your test directory and run tests.

Tests don’t run and return empty results

You’re using a PHPUnit version that requires a newer PHP version to run. Get an older version of PHPUnit.

“Fatal error: Uncaught exception ‘PHPUnit_Framework_Error_Notice’ with message ‘Non-static method PHP_Timer::start() should not be called statically, assuming $this from incompatible context'” when you try running tests

You’ve got the curse of the shitty non-backwards-compatible dependency refactoring, go into your Utilities folder and open PHPUnit/Framework/TestResult.php and make the following changes:

  • Find the following line:
    PHP_Timer::start(); comment it out or delete it, and insert the following 2 lines after it: $timer = new PHP_Timer; $timer->start();
  • Find the following line:
    $time = PHP_Timer::stop(); comment it out or delete it, and insert the following line after it: $time = $timer->stop();
Your tests should run fine now.