[Solar-svn] Revision 2684

pmjones at solarphp.com pmjones at solarphp.com
Thu Aug 9 16:36:04 CDT 2007


Branch: Solar_Cli_MakeTests: [NEW] New CLI command to make Solar_Test stub files


Added: branches/orm/Solar/Cli/MakeTests/Data/classAbstract.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests/Data/classAbstract.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests/Data/classAbstract.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,86 @@
+<?php
+/**
+ * 
+ * Abstract class test.
+ * 
+ */
+class Test_:class extends :extends {
+    
+    /**
+     * 
+     * Configuration values.
+     * 
+     * @var array
+     * 
+     */
+    protected $_Test_:class = array(
+    );
+    
+    // -----------------------------------------------------------------
+    // 
+    // Support methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Constructor.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __construct($config)
+    {
+        $this->skip('abstract class');
+        parent::__construct($config);
+    }
+    
+    /**
+     * 
+     * Destructor; runs after all methods are complete.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __destruct()
+    {
+        parent::__destruct();
+    }
+    
+    /**
+     * 
+     * Setup; runs before each test method.
+     * 
+     */
+    public function setup()
+    {
+        parent::setup();
+    }
+    
+    /**
+     * 
+     * Setup; runs after each test method.
+     * 
+     */
+    public function teardown()
+    {
+        parent::teardown();
+    }
+    
+    // -----------------------------------------------------------------
+    // 
+    // Test methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Test -- Constructor.
+     * 
+     */
+    public function test__construct()
+    {
+        $obj = Solar::factory(':class');
+        $this->assertInstance($obj, ':class');
+    }
+}
\ No newline at end of file

Added: branches/orm/Solar/Cli/MakeTests/Data/classAdapter.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests/Data/classAdapter.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests/Data/classAdapter.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Parent test.
+ */
+require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Adapter.php';
+
+/**
+ * 
+ * Adapter class test.
+ * 
+ */
+class Test_:class extends :extends {
+    
+    /**
+     * 
+     * Configuration values.
+     * 
+     * @var array
+     * 
+     */
+    protected $_Test_:class = array(
+    );
+    
+    // -----------------------------------------------------------------
+    // 
+    // Support methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Constructor.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __construct($config)
+    {
+        $this->todo('need adapter-specific config');
+    }
+    
+    /**
+     * 
+     * Destructor; runs after all methods are complete.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __destruct()
+    {
+        parent::__destruct();
+    }
+    
+    /**
+     * 
+     * Setup; runs before each test method.
+     * 
+     */
+    public function setup()
+    {
+        parent::setup();
+    }
+    
+    /**
+     * 
+     * Setup; runs after each test method.
+     * 
+     */
+    public function teardown()
+    {
+        parent::teardown();
+    }
+    
+    // -----------------------------------------------------------------
+    // 
+    // Test methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Test -- Constructor.
+     * 
+     */
+    public function test__construct()
+    {
+        $obj = Solar::factory(':class');
+        $this->assertInstance($obj, ':class');
+    }
+}
\ No newline at end of file

Added: branches/orm/Solar/Cli/MakeTests/Data/classConcrete.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests/Data/classConcrete.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests/Data/classConcrete.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,85 @@
+<?php
+/**
+ * 
+ * Concrete class test.
+ * 
+ */
+class Test_:class extends :extends {
+    
+    /**
+     * 
+     * Configuration values.
+     * 
+     * @var array
+     * 
+     */
+    protected $_Test_:class = array(
+    );
+    
+    // -----------------------------------------------------------------
+    // 
+    // Support methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Constructor.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __construct($config)
+    {
+        parent::__construct($config);
+    }
+    
+    /**
+     * 
+     * Destructor; runs after all methods are complete.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __destruct()
+    {
+        parent::__destruct();
+    }
+    
+    /**
+     * 
+     * Setup; runs before each test method.
+     * 
+     */
+    public function setup()
+    {
+        parent::setup();
+    }
+    
+    /**
+     * 
+     * Setup; runs after each test method.
+     * 
+     */
+    public function teardown()
+    {
+        parent::teardown();
+    }
+    
+    // -----------------------------------------------------------------
+    // 
+    // Test methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Test -- Constructor.
+     * 
+     */
+    public function test__construct()
+    {
+        $obj = Solar::factory(':class');
+        $this->assertInstance($obj, ':class');
+    }
+}
\ No newline at end of file

Added: branches/orm/Solar/Cli/MakeTests/Data/classFactory.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests/Data/classFactory.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests/Data/classFactory.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,85 @@
+<?php
+/**
+ * 
+ * Factory class test.
+ * 
+ */
+class Test_:class extends :extends {
+    
+    /**
+     * 
+     * Configuration values.
+     * 
+     * @var array
+     * 
+     */
+    protected $_Test_:class = array(
+    );
+    
+    // -----------------------------------------------------------------
+    // 
+    // Support methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Constructor.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __construct($config)
+    {
+        parent::__construct($config);
+    }
+    
+    /**
+     * 
+     * Destructor; runs after all methods are complete.
+     * 
+     * @param array $config User-defined configuration parameters.
+     * 
+     */
+    public function __destruct()
+    {
+        parent::__destruct();
+    }
+    
+    /**
+     * 
+     * Setup; runs before each test method.
+     * 
+     */
+    public function setup()
+    {
+        parent::setup();
+    }
+    
+    /**
+     * 
+     * Setup; runs after each test method.
+     * 
+     */
+    public function teardown()
+    {
+        parent::teardown();
+    }
+    
+    // -----------------------------------------------------------------
+    // 
+    // Test methods.
+    // 
+    // -----------------------------------------------------------------
+    
+    /**
+     * 
+     * Test -- Constructor.
+     * 
+     */
+    public function test__construct()
+    {
+        $obj = Solar::factory(':class');
+        $this->assertInstance($obj, ':class_Adapter');
+    }
+}
\ No newline at end of file

Added: branches/orm/Solar/Cli/MakeTests/Data/methodAbstract.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests/Data/methodAbstract.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests/Data/methodAbstract.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,10 @@
+    
+    /**
+     * 
+     * Test -- :summ
+     * 
+     */
+    public function :name()
+    {
+        $this->skip('abstract method');
+    }

Added: branches/orm/Solar/Cli/MakeTests/Data/methodConcrete.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests/Data/methodConcrete.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests/Data/methodConcrete.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,10 @@
+    
+    /**
+     * 
+     * Test -- :summ
+     * 
+     */
+    public function :name()
+    {
+        $this->todo('stub');
+    }

Added: branches/orm/Solar/Cli/MakeTests/Info/options.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests/Info/options.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests/Info/options.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,13 @@
+<?php
+return array(
+    'target' => array(
+        'long' => 'target',
+        'descr' => 'Where the tests will be written to.',
+    ),
+    'only' => array(
+        'long' => 'only',
+        'param' => null,
+        'value' => false,
+        'descr' => 'Make tests only for the named class; do not descend into subdirectories.',
+    ),
+);
\ No newline at end of file

Added: branches/orm/Solar/Cli/MakeTests.php
===================================================================
--- branches/orm/Solar/Cli/MakeTests.php	                        (rev 0)
+++ branches/orm/Solar/Cli/MakeTests.php	2007-08-09 21:36:04 UTC (rev 2684)
@@ -0,0 +1,282 @@
+<?php
+/**
+ * 
+ * Command to make a test class (or set of classes) from a named class.
+ * 
+ * @category Solar
+ * 
+ * @package Solar_Cli
+ * 
+ * @author Paul M. Jones <pmjones at solarphp.com>
+ * 
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ * 
+ * @version $Id: Base.php 2498 2007-06-01 19:36:45Z pmjones $
+ * 
+ */
+
+/**
+ * 
+ * Command to make a test class (or set of classes) from a given class.
+ * 
+ * The class should be in the include_path.
+ * 
+ * Synopsis
+ * ========
+ * 
+ * `**solar make-tests** [options] CLASS`
+ * 
+ * Options
+ * =======
+ * 
+ * `--config FILE`
+ * : Path to the Solar.config.php file.  Default false.
+ * 
+ * `--target _arg_`
+ * : Directory where the test classes should be written to.  Default is the
+ *   current working directory.
+ * 
+ * `--only`
+ * : Make only the test for the given class, do not recurse into subdirectories.
+ * 
+ * Examples
+ * ========
+ * 
+ * Make test files for a class and its subdirectories.
+ * 
+ *     $ cd /path/to/tests/
+ *     $ solar make-tests Vendor_Example
+ * 
+ * Make "remotely":
+ * 
+ *     $ solar make-tests --dir /path/to/tests Vendor_Example
+ * 
+ * Make only the Vendor_Example test (no subdirectories):
+ * 
+ *     $ solar make-tests --only Vendor_Example
+ * 
+ * @category Solar
+ * 
+ * @package Solar_Cli
+ * 
+ */
+class Solar_Cli_MakeTests extends Solar_Cli_Base {
+    
+    protected $_tpl; // templates for classes and methods
+    
+    protected $_class; // the source class to work with
+    
+    protected $_target; // the target directory for writing tests
+    
+    protected $_file; // name of the test file to work with
+    
+    protected $_code; // the code in the test file
+    
+    protected function _exec($class = null)
+    {
+        $this->_println("Making tests.");
+        
+        // make sure we have a class to work with
+        if (! $class) {
+            throw $this->_exception('ERR_NO_CLASS_SPECIFIED');
+        }
+        
+        // make sure we have a target directory
+        $this->_setTarget();
+        
+        // get all the class and method templates
+        $this->_loadTemplates();
+        
+        // build a class-to-file map object for later use
+        $map = Solar::factory('Solar_Class_Map');
+        
+        // tell the user where the source and targets are
+        $this->_println("Source: " . $map->getBase());
+        $this->_println("Target: $this->_target");
+        
+        // get the class and file locations
+        $class_file = $map->fetch($class);
+        foreach ($class_file as $class => $file) {
+            
+            // tell the user what class we're on
+            $this->_print("$class: "); 
+            
+            // if this is an exception class, skip it
+            if (strpos($class, '_Exception')) {
+                $this->_println("skip (exception class)");
+                continue;
+            }
+            
+            // load the class and get its API reference
+            Solar::loadClass($class);
+            $apiref = Solar::factory('Solar_Docs_Apiref');
+            $apiref->addClass($class);
+            $api = $apiref->api[$class];
+            
+            // set the file name, creating if needed
+            $this->_setFile($class, $api);
+            
+            // get the code currently in the file
+            $this->_code = file_get_contents($this->_file);
+            
+            // add new test methods
+            $this->_addTestMethods($api);
+            
+            // write the file back out again
+            file_put_contents($this->_file, $this->_code);
+            
+            // done with this class
+            $this->_println(' ;');
+        }
+        
+        // done with all classes.
+        $this->_println('Done.');
+    }
+    
+    protected function _loadTemplates()
+    {
+        $this->_tpl = array();
+        $dir = Solar::fixdir(dirname(__FILE__) . '/MakeTests/Data');
+        $list = glob($dir . '*.php');
+        foreach ($list as $file) {
+            $key = substr(basename($file), 0, -4);
+            $this->_tpl[$key] = file_get_contents($file);
+        }
+    }
+    
+    protected function _setTarget()
+    {
+        // look for a test directory, otherwise assume that the tests are
+        // in the same dir
+        $this->_target = $this->_options['target'];
+        if (! $this->_target) {
+            $this->_target = getcwd();
+        }
+        
+        // make sure it matches the OS.
+        $this->_target = Solar::fixdir($this->_target);
+        
+        // make sure it exists
+        if (! is_dir($this->_target)) {
+            throw $this->_exception('ERR_TARGET_NOT_EXIST');
+        }
+    }
+    
+    protected function _setFile($class, $api)
+    {
+        $this->_file = $this->_target 
+                     . str_replace('_', DIRECTORY_SEPARATOR, "Test_$class")
+                     . '.php';
+        
+        // create the file if needed
+        if (file_exists($this->_file)) {
+            return;
+        }
+        
+        // create the directory if needed
+        $dir = dirname($this->_file);
+        if (! is_dir($dir)) {
+            mkdir($dir, 0777, true);
+        }
+        
+        // use the right code template
+        if ($api['abstract']) {
+            $code = $this->_tpl['classAbstract'];
+        } elseif (! empty($api['methods']['solarFactory'])) {
+            $code = $this->_tpl['classFactory'];
+        } else {
+            $code = $this->_tpl['classConcrete'];
+        }
+        
+        // use the right "extends" for adapter classes.
+        // extends this to helpers and abstracts?
+        // note that this still writes the new methods, when they should
+        // be inherited from the parent test instead.
+        $pos = strrpos($class, '_Adapter_');
+        if ($pos) {
+            $code = $this->_tpl['classAdapter'];
+            $extends = 'Test_' . substr($class, 0, $pos + 8);
+        } else {
+            $extends = 'Solar_Test';
+        }
+        
+        // do replacements
+        $code = str_replace(
+            array(':class', ':extends'),
+            array($class, $extends),
+            $code
+        );
+        
+        // write the file
+        file_put_contents($this->_file, $code);
+    }
+    
+    protected function _addTestMethods($api)
+    {
+        // prepare the testing code for appending new methods.
+        $this->_code = trim($this->_code);
+        
+        // the last char should be a brace.
+        $last = substr($this->_code, -1);
+        if ($last != '}') {
+            throw $this->_exception('ERR_LAST_BRACE', array(
+                'file' => $this->_file
+            ));
+        }
+        
+        // strip the last brace
+        $this->_code = substr($this->_code, 0, -1);
+        
+        // ignore these methods
+        $ignore = array('__construct', '__destruct', 'apiVersion', 'dump',
+            'locale');
+        
+        // look for methods and add them if needed
+        foreach ($api['methods'] as $name => $info) {
+            
+            // is this an ignored method?
+            if (in_array($name, $ignore)) {
+                $this->_print('.');
+                continue;
+            }
+            
+            // is this a public method?
+            if ($info['access'] != 'public') {
+                $this->_print('.');
+                continue;
+            };
+            
+            // the test-method name
+            $test_name = 'test' . ucfirst($name);
+            
+            // does the test-method definition already exist?
+            $def = "public function {$test_name}()";
+            $pos = strpos($this->_code, $def);
+            if ($pos) {
+                $this->_print('.');
+                continue;
+            }
+            
+            // use the right code template
+            if ($info['abstract']) {
+                $test_code = $this->_tpl['methodAbstract'];
+            } else {
+                $test_code = $this->_tpl['methodConcrete'];
+            }
+            
+            // do replacements
+            $test_code = str_replace(
+                array(':name', ':summ'),
+                array($test_name, $info['summ']),
+                $test_code
+            );
+            
+            // append to the test code
+            $this->_code .= $test_code;
+            $this->_print('+');
+        }
+        
+        // append the last brace
+        $this->_code .= "\n}\n";
+    }
+}




More information about the Solar-svn mailing list