Skip to content

Instantly share code, notes, and snippets.

@headzoo
Last active August 29, 2015 14:01
Show Gist options
  • Save headzoo/f3fdd1d13c0af6fff2c4 to your computer and use it in GitHub Desktop.
Save headzoo/f3fdd1d13c0af6fff2c4 to your computer and use it in GitHub Desktop.
PhpStorm wrapper script for PHPUnit Skeleton Generator
#!/usr/bin/env php
<?php
/**
* PhpStorm wrapper script for PHPUnit Skeleton Generator
* ------------------------------------------------------
* This script is designed for use with projects which have the following directory structure:
* /project-dir
* /src
* /tests
* /vendor
*
* The test cases it generates will be placed in the 'tests' directory.
*
* Installation
* ------------
* 1. Globally install PHPUnit with composer using the following command:
* composer global require "phpunit/phpunit=3.7.*"
*
* Note: PhpStorm is not compatible with versions of PHPUnit greater than 3.7.*.
*
* 2. Globally install PHPUnit Skeleton Generator with Composer using the following command:
* composer global require "phpunit/phpunit-skeleton-generator=2.0.*@dev"
*
* 3. Install this script to your bin directory using the following commands:
* cd /home/<user>/bin
* git clone https://gist.github.com/f3fdd1d13c0af6fff2c4.git
* cp f3fdd1d13c0af6fff2c4/gistfile1.php ./phpunit-skelgen
* rm -rf f3fdd1d13c0af6fff2c4
* chmod +x phpunit-skelgen
*
* Note: Change <user> to your user name. Create the /bin directory if it does not already exist, and ensure
* it's in your PATH.
*
* 4. Setup the skeleton generator as an external tool from your PhpStorm settings:
* Go to the PhpStorm settings and click on the "External Tools" setting.
* From the setting window click the green + icon to create a new tool.
* Name the tool "PHPUnit Skeleton Generator" and leave the group and description blank.
* Fill in the tool settings using the example below.
*
*
* Example
* -------
* Program : /home/<user>/bin/phpunit-skelgen.php
* Parameters : $ProjectFileDir$/vendor/autoload.php $FilePath$ $ProjectFileDir$/tests
* Working directory : $ProjectFileDir$
*
* Note: Change <user> to your user name. The $value$ strings in the examples above are PhpStorm macros, and
* should not be changed.
*/
define("PHPUNIT_SKELGEN", "phpunit-skelgen");
if ($argc < 4) {
println("Usage: {$argv[0]} <bootstrap-file> <class-source> <test-directory>");
}
if (!file_exists($argv[1])) {
println("Bootstrap file '{$argv[1]}' does not exist.", true);
}
if (!file_exists($argv[2])) {
println("Class source file '{$argv[2]}' does not exist.", true);
}
$namespace = null;
$class_name = getFileClass($argv[2], $namespace);
if (!$class_name) {
println("No class definition found in file '{$argv[2]}'.", true);
}
$test_dir = path("{$argv[3]}/{$namespace}");
$test_class = "{$class_name}Test";
$test_src = path("{$argv[3]}/{$test_class}.php");
if (!file_exists($test_dir)) {
if (!mkdir($test_dir, 0777, true)) {
println("Unable to create test directory '{$test_dir}'.", true);
die();
}
}
$args = array_map("escapeshellarg", [
"bootstrap" => $argv[1],
"class" => $class_name,
"class-source" => $argv[2],
"test-class" => $test_class,
"test-source" => $test_src
]);
array_unshift($args, PHPUNIT_SKELGEN);
$cmd = vsprintf(
"%s --bootstrap=%s generate-test %s %s %s %s",
$args
);
exec($cmd);
/**
* Returns the fully-qualified name for the class defined in the given file
*
* Returns the name of the first class defined in the file. Returns null if the file does
* not have a class definition.
*
* @param string $file A PHP file containing at least one class definition
* @param string $namespace Receives the class namespace
*
* @return string|null
*/
function getFileClass($file, &$namespace = null)
{
$fqn = null;
$contents = file_get_contents($file);
preg_match("/class ([\\w]+)/", $contents, $matches);
if ($matches) {
$fqn = $matches[1];
preg_match("/namespace (.+);/", $contents, $matches);
if ($matches) {
$namespace = $matches[1];
$fqn = "{$namespace}\\{$fqn}";
}
}
return $fqn;
}
/**
* Convenience function for printing strings on the command line
*
* Kills script execution after printing the message when $is_error is true.
*
* @param string $msg The string to print
* @param bool $err Send the message to stderr?
*
* @throws Exception
*/
function println($msg, $err = false)
{
$output = (!$err) ? "php://stdout" : "php://stderr";
$output = fopen($output, "w+");
if ($output) {
fwrite($output, "{$msg}\r\n");
fclose($output);
}
if ($err) {
die(1);
}
}
/**
* Sanitizes a file path
*
* @param string $path The path to sanitize
*
* @return string
*/
function path($path)
{
return str_replace(["\\", "/"], DIRECTORY_SEPARATOR, $path);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment