Skeleton for unit testing with PHPUnit

Skeleton for unit testing with PHPUnit

Created:28 Feb 2017 17:14:22 , in  Host development,  Web development

Recently, I have written an article on installing PHPUnit with a BASH script. In this post I take a step forward with the subject and build a skeleton for testing PHP class(es) with the framework. Like in the first article on PHPUnit, and in fact in pretty much every post on sWWW, I put greater emphasis on computer code rather than descriptions or step-by-step guides. Hence, the job will be done with a BASH script again.

Building a skeleton for PHPUnit

At first glance building a skeleton for PHPUnit looks a not-too- demanding tasks. You need a directory with sub-directories for your source code ( src/ ) and tests ( tests/ ).

In the former you put your PHP class(es) in, in the latter go all your testing PHP classes - that is ,stuff PHPUnit will work with. Also, if more than one PHP class is to be tested, some autoloading script will be handy. Finally, one has to remember, PHPUnit follows some conventions with respect to how tests classes, source PHP classes and files they reside in are expected to be named. If PHPUnit is to work smoothly, these conventions have to be followed and dealt with correctly too.

Taking all the above into account, building a skeleton for PHPUnit by hand, except for the initial attempt perhaps, makes little sense. It becomes a rather tedious task quick. It can be fairly error prone as well. Also, the last srtaw, it is a true time waster. In other words, this task is a perfect candidate for a script.

Automated skeleton building with BASH

Below is my BASH script, PHPUnit_skeleton.sh, for building a skeleton for testing PHP code with PHPUnit. It creates a basic testing environment for one or more PHP classes. It provides a minimal autoload script and a file for running tests called run.sh


#!/usr/bin/env bash

# PHPUnit_skeleton.sh 1.0
# Description: create skeleton for testing PHP classes with PHPunit
# Author: Sylwester Wojnowski
# WWW: wojnowski.net.pl

help(){
  script_name=$( basename $0 )
  echo "${script_name} creates basic test environment for testing PHP class(es) with PHPUnit framework."
  echo "Usage: ${script_name} PHPClassName [directory|-] [PHP version]" 
  echo "Parameters:"
  echo " - PHPClassName - name of the class (no .php extension) to build skeleton for. First character of the phpClassName will be capitalized."
  echo " - directory - existing system directory or - (dash) "
  echo " - PHPVersion - version of PHP. ${script_name} supports PHP versions 5.6 and 7.x"
} 

build_skeleton(){
  
  echo "Beginning building skeleton for testing class ${skel_class} ..." 1>&2
  
  mkdir $skeleton_dir
  mkdir $skeleton_src_dir
  mkdir $skeleton_tests_dir
  touch $skeleton_readme_file
  touch $skeleton_run_file
  touch $skeleton_phpclass_file
  touch $skeleton_classtest_file
  touch $skeleton_autoload_file

  chmod 755 $skeleton_run_file

  echo "$skeleton_run_file_content" > $skeleton_run_file
  echo "$phpclass_file_content" > $skeleton_phpclass_file
  echo "$classtest_file_content" > $skeleton_classtest_file
  echo "$skeleton_autoload_file_content" > $skeleton_autoload_file

  echo "Skeleton building complete!" 1>&2
  echo "Execute ${skeleton_run_file} to check, everything is working fine." 1>&2
} 


prepare_test_and_build(){

  local skeletons_dir=$(pwd)
  
  # set skeletons_dir
  [[ ! -z "$2" ]] && {
    # if $2 == - move on 
    [[ "$2" != '-' ]] && {
      [[ -d "$2"  ]] && {
        skeletons_dir="$2"
        re='/$'
        [[ $skeletons_dir =~ $re ]] && {
          skeletons_dir=${skeletons_dir%/}
        } 
      }
    }  
  }
  
  local skel_class="$1"

  local phpclass_file_content=
  local classtest_file_content=
  local skeleton_run_file_content=
  local skeleton_autoload_file=
  
  skel_class=${skel_class^}
  skel_class=${skel_class/'.php'/}
  local skeleton_dir="${skeletons_dir}/${skel_class}/"
  local skeleton_src_dir="${skeletons_dir}/${skel_class}/src/"
  local skeleton_readme_file="${skeletons_dir}/${skel_class}/readme.txt"
  local skeleton_run_file="${skeletons_dir}/${skel_class}/run.sh"
  local skeleton_tests_dir="${skeletons_dir}/${skel_class}/tests/"
  local skeleton_phpclass_file="${skeletons_dir}/${skel_class}/src/${skel_class}.php"
  local skeleton_classtest_file="${skeletons_dir}/${skel_class}/tests/${skel_class}Test.php"
  local skeleton_autoload_file="${skeletons_dir}/${skel_class}/src/autoload.php" 
  
  # default PHP version 
  local PHPVersion='5.6'
  local PHPStrictTypes=''

  # add strict types for PHP version 7.x
  [[ ! -z "$3" ]] && { 
    PHPVersion="$3"
    local pvre='^7\.'
    [[ $PHPVersion =~ $pvre ]] && {
      PHPStrictTypes='declare(strict_types=1);'      
    } 
  } 
  
  [[ -z "$skel_class" ]] && {
    echo "Error! PHP class Name not specified. Exiting ..."
    help
    exit 1
  }

  [[ -d $skeleton_dir ]] && {
    echo "$skeleton_dir exists already. Use different PHP class name. Exiting ...";
    help
    exit 1
  }

# src # src/class.php contents
read -r -d '' phpclass_file_content <<- EOC
<?php

class ${skel_class}{
  private function __construct($conf){
  
  }
}
EOC

# tests/classTest contents
read -r -d '' classtest_file_content <<- EOC
<?php
${PHPStrictTypes}
use PHPUnit\Framework\TestCase;

/**
 * @covers ${skel_class}
 */
final class ${skel_class}Test extends TestCase {
  # sample test ...
  public function testSomething(){
    \$this->assertEquals(
       1,1
    );
  }
}
EOC

# src/autoload.php contents
read -r -d '' skeleton_run_file_content <<- EOC
#!/usr/bin/env bash
# uncomment for single PHP class testing
# phpunit --bootstrap src/${skel_class}.php tests/${skel_class}Test
# all classes in tests/ testing 
phpunit --include-path \$(pwd) --bootstrap src/autoload.php tests
EOC

# src/autoload.php contents
read -r -d '' skeleton_autoload_file_content <<- 'EOC'
<?php
spl_autoload_register(function($class){
  include 'src/'.$class.'.php';
});
EOC

build_skeleton
}

prepare_test_and_build "$1" "$2" "$3"

Script arguments

PHPUnit_skeleton.sh takes maksimum three arguments.

Here is a basic synopsis:


Usage: PHPUnit_skeleton.sh PHPClassName [directory|-] [PHP version]

First argument is a name of PHP class to be tested. It is the only required argument. On its basis the whole testing environment is built ( by default in the directory where the script is kept).

The second argument - existing directory path - allows to save the skeleton in that directory instead of in the directory the script is in. If dash symbol (-) is given instead of a path, this argument will be skipped.

Finally, the third argument allows to choose PHP version the skeleton will be built for. Testing code written for PHP 7.x differs slightly from that for PHP 5.6. By default, the script builds for PHP in version 5.6. So if you need PHP 7.x, make sure you provide this argument.

Examples of use

Firstly, make sure you have PHPUnit installed correctly.

Secondly, before invoking PHPUnit_skeleton.sh, make it executable ( chmod +x PHPUnit_skeleton.sh ).

Command:


./PHPUnitSkeleton.sh SampleClass

or equivalently (if PHPUnitSkeleton.sh is put in one of directories specified in PATH environmental variable)


PHPUnitSkeleton.sh SampleClass 

will create a following directory tree:


- SampleClass/
     |_ run.sh
     |
     |_ src/
     |   |_ SampleClass.php
     |   | 
     |   |_ autoload.php 
     |
     |_ tests/
         |
	 |_ SampleClassTest.php
       

in the current working directory.


./PHPUnitSkeleton.sh sampleClass 

will create the same tree in the current working directory.


./PHPUnitSkeleton.sh sampleClass - 7.0 

will output tests code for PHP 7.x in tests/SampleClassTest.php .


./PHPUnitSkeleton.sh sampleClass /tmp/ 7.0
 

equivalently


./PHPUnitSkeleton.sh sampleClass /tmp 7.0 

will create the tree above in /tmp directory.

Finally


./PHPUnitSkeleton.sh sampleClass /tmp

will output the tree in /tmp and write tests code for PHP 5.6 .

Once a skeleton has been built, you can write PHP code in src/SampleClass.php , tests for it in SampleClassTest.php and run tests with run.sh from the main skeleton directory (the one where src/ and tests/ directories reside).

Better autoloader

As a library / project grows it frequently becomes more and more dependent on other libaries. The basic autoloader provided with this script will include for tests only files placed directly in src/ directory. If you need code from sub-directories of src/, you'll have to either find an autoloader on the internet or write one by yourself.

A parting thought

I hope, the script will prove a time saver and a useful addition to your PHP toolbox. These are exactly the things it was written for. Feel free to contact me with questions on usage or the code above. Improvements are also welcome.

This post was updated on 27 Apr 2017 16:12:21

Tags:  BASH ,  php ,  PHPUnit 


Author, Copyright and citation

Author

Sylwester Wojnowski

Author of the above article, Sylwester Wojnowski, is sWWW admin and owner.He enjoys doing Maths and studying algorithms, writing code in scripting and command languages, Thrash Metal music and playing electric guitar.

Copyrights

©Copyright, 2017 Sylwester Wojnowski. This article may not be reproduced or published as a whole or in parts without permission from the author. If you share it, please give author credit and do not remove embedded links.

Computer code, if present in the article, is excluded from the above and licensed under GPLv3.

Citation

Cite this article as:

Wojnowski, Sylwester. "Skeleton for unit testing with PHPUnit." From sWWW - Code For The Web . https://wojnowski.net.pl//main/index/skeleton-for-unit-testing-with-phpunit