PHPUnit
[ class tree: PHPUnit ] [ index: PHPUnit ] [ all elements ]

Source for file Gtk.php

Documentation is available at Gtk.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2004 Scott Mattocks                                    |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Scott Mattocks <scottmattocks@php.net>                       |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Gtk.php,v 1.2 2004/11/25 09:06:55 sebastian Exp $
  20. /**
  21.  * GTK GUI interface for PHPUnit.
  22.  *
  23.  * This class is a PHP port of junit.awtui.testrunner. Documentation
  24.  * for junit.awtui.testrunner can be found at
  25.  * http://junit.sourceforge.net
  26.  *
  27.  * Due to the limitations of PHP4 and PHP-Gtk, this class can not
  28.  * duplicate all of the functionality of the JUnit GUI. Some of the
  29.  * things this class cannot do include:
  30.  * - Reloading the class for each run
  31.  * - Stopping the test in progress
  32.  *
  33.  * To use simply intantiate the class and call main()
  34.  * $gtk =& new PHPUnit_GUI_Gtk;
  35.  * $gtk->main();
  36.  *
  37.  * Once the window has finished loading, you can enter the name of
  38.  * a class that has been loaded (include/require some where in your
  39.  * code, or you can pass the name of the file containing the class.
  40.  *
  41.  * You can also load classes using the SetupDecorator class.
  42.  * require_once 'PHPUnit/GUI/SetupDecorator.php';
  43.  * require_once 'PHPUnit/GUI/Gtk.php';
  44.  * $gui = new PHPUnit_GUI_SetupDecorator(new PHPUnit_GUI_Gtk());
  45.  * $gui->getSuitesFromDir('/path/to/test','.*\.php$',array('index.php','sql.php'));
  46.  * $gui->show();
  47.  *
  48.  * @todo Allow file drop. (Gtk_FileDrop)
  49.  *
  50.  * @author     Scott Mattocks
  51.  * @copyright  Copyright &copy; 2004 Scott Mattocks
  52.  * @license    PHP 3.0
  53.  * @version    @VER@
  54.  * @category   PHP
  55.  * @package    PHPUnit
  56.  * @subpackage GUI
  57.  */
  58. class PHPUnit_GUI_Gtk {
  59.  
  60.     /**
  61.      * The main gtk window
  62.      * @var object 
  63.      */
  64.     var $gui;
  65.     /**
  66.      * The text entry that contains the name of the
  67.      * file that holds the test(s)/suite(s).
  68.      * @var object 
  69.      */
  70.     var $suiteField;
  71.     /**
  72.      * The label that shows the number of tests that
  73.      * were run.
  74.      * @var object 
  75.      */
  76.     var $numberOfRuns;
  77.     /**
  78.      * The label that shows the number of errors that
  79.      * were encountered.
  80.      * @var object 
  81.      */
  82.     var $numberOfErrors;
  83.     /**
  84.      * The label that shows the number of failures
  85.      * that were encountered.
  86.      * @var object 
  87.      */
  88.     var $numberOfFailures;
  89.     /**
  90.      * The label for reporting user messages.
  91.      * @var object 
  92.      */
  93.     var $statusLine;
  94.     /**
  95.      * The text area for reporting messages from successful
  96.      * test runs. (not necessarily successful tests)
  97.      * @var object 
  98.      */
  99.     var $reportArea;
  100.     /**
  101.      * The text area for reporting errors encountered when
  102.      * running tests.
  103.      * @var object 
  104.      */
  105.     var $dumpArea;
  106.     /**
  107.      * The progress bar indicator. Shows the percentage of
  108.      * passed tests.
  109.      * @var object 
  110.      */
  111.     var $progress;
  112.     /**
  113.      * A checkbox for the user to indicate whether or not they
  114.      * would like to see results from all tests or just failures.
  115.      * @object
  116.      */
  117.     var $showPassed;
  118.  
  119.     /**
  120.      * Constructor.
  121.      *
  122.      * The constructor checks for the gtk extension and loads it
  123.      * if needed. Then it creates the GUI. The GUI is not shown
  124.      * nor is the main gtk loop started until main() is called.
  125.      *
  126.      * @access public
  127.      * @param  none 
  128.      * @return void 
  129.      */
  130.     function PHPUnit_GUI_Gtk()
  131.     {
  132.         // Check for php-gtk extension.
  133.         if (!extension_loaded('gtk')) {
  134.             dl'php_gtk.' . PHP_SHLIB_SUFFIX);
  135.         }
  136.  
  137.         // Create the interface but don't start the loop
  138.         $this->_createUI();
  139.     }
  140.     /**
  141.      * Start the main gtk loop.
  142.      *
  143.      * main() first sets the default state of the showPassed
  144.      * check box. Next all widgets that are part of the GUI
  145.      * are shown. Finally the main gtk loop is started.
  146.      *
  147.      * @access public
  148.      * @param  boolean $showPassed 
  149.      * @return void 
  150.      */
  151.     function main($showPassed = true)
  152.     {
  153.         $this->showPassed->set_active($showPassed);
  154.         $this->gui->show_all();
  155.  
  156.         gtk::main();
  157.     }
  158.     /**
  159.      * Create the user interface.
  160.      *
  161.      * The user interface is pretty simple. It consists of a
  162.      * menu, text entry, run button, some labels, a progress
  163.      * indicator, and a couple of areas for notification of
  164.      * any messages.
  165.      *
  166.      * @access private
  167.      * @param  none 
  168.      * @return void 
  169.      */
  170.     function _createUI()
  171.     {
  172.         // Create a window.
  173.         $window =new GtkWindow;
  174.         $window->set_title('PHPUnit Gtk');
  175.         $window->set_usize(400-1);
  176.  
  177.         // Create the main box.
  178.         $mainBox =new GtkVBox;
  179.         $window->add($mainBox);
  180.  
  181.         // Start with the menu.
  182.         $mainBox->pack_start($this->_createMenu());
  183.  
  184.         // Then add the suite field entry.
  185.         $mainBox->pack_start($this->_createSuiteEntry());
  186.  
  187.         // Then add the report labels.
  188.         $mainBox->pack_start($this->_createReportLabels());
  189.  
  190.         // Next add the progress bar.
  191.         $mainBox->pack_start($this->_createProgressBar());
  192.  
  193.         // Then add the report area and the dump area.
  194.         $mainBox->pack_start($this->_createReportAreas());
  195.  
  196.         // Finish off with the status line.
  197.         $mainBox->pack_start($this->_createStatusLine());
  198.  
  199.         // Connect the destroy signal.
  200.         $window->connect_object('destroy'array('gtk''main_quit'));
  201.  
  202.         // Assign the member.
  203.         $this->gui =$window;
  204.     }
  205.     /**
  206.      * Create the menu.
  207.      *
  208.      * The menu is very simple. It an exit menu item, which exits
  209.      * the application, and an about menu item, which shows some
  210.      * basic information about the application itself.
  211.      *
  212.      * @access private
  213.      * @param  none 
  214.      * @return &object The GtkMenuBar
  215.      */
  216.     function &_createMenu()
  217.     {
  218.         // Create the menu bar.
  219.         $menuBar =new GtkMenuBar;
  220.  
  221.         // Create the main (only) menu item.
  222.         $phpHeader =new GtkMenuItem('PHPUnit');
  223.  
  224.         // Add the menu item to the menu bar.
  225.         $menuBar->append($phpHeader);
  226.  
  227.         // Create the PHPUnit menu.
  228.         $phpMenu =new GtkMenu;
  229.  
  230.         // Add the menu items
  231.         $about =new GtkMenuItem('About...');
  232.         $about->connect('activate'array(&$this'about'));
  233.         $phpMenu->append($about);
  234.  
  235.         $exit =new GtkMenuItem('Exit');
  236.         $exit->connect_object('activate'array('gtk''main_quit'));
  237.         $phpMenu->append($exit);
  238.  
  239.         // Complete the menu.
  240.         $phpHeader->set_submenu($phpMenu);
  241.  
  242.         return $menuBar;
  243.     }
  244.     /**
  245.      * Create the suite entry and related widgets.
  246.      *
  247.      * The suite entry has some supporting components such as a
  248.      * label, the show passed check box and the run button. All
  249.      * of these items are packed into two nested boxes.
  250.      *
  251.      * @access private
  252.      * @param  none 
  253.      * @return &object A box that contains all of the suite entry pieces.
  254.      */
  255.     function &_createSuiteEntry()
  256.     {
  257.         // Create the outermost box.
  258.         $outerBox         =new GtkVBox;
  259.  
  260.         // Create the suite label, box, and field.
  261.         $suiteLabel       =new GtkLabel('Test class name:');
  262.         $suiteBox         =new GtkHBox;
  263.         $this->suiteField =new GtkEntry;
  264.         $this->suiteField->set_text($suiteName != NULL ? $suiteName '');
  265.  
  266.         // Create the button the user will use to start the test.
  267.         $runButton =new GtkButton('Run');
  268.         $runButton->connect_object('clicked'array(&$this'run'));
  269.  
  270.         // Create the check box that lets the user show only failures.
  271.         $this->showPassed =new GtkCheckButton('Show passed tests');
  272.  
  273.         // Add the components to their respective boxes.
  274.         $suiteLabel->set_alignment(00);
  275.         $outerBox->pack_start($suiteLabel);
  276.         $outerBox->pack_start($suiteBox);
  277.         $outerBox->pack_start($this->showPassed);
  278.  
  279.         $suiteBox->pack_start($this->suiteField);
  280.         $suiteBox->pack_start($runButton);
  281.  
  282.         return $outerBox;
  283.     }
  284.  
  285.     /**
  286.      * Create the labels that tell the user what has happened.
  287.      *
  288.      * There are three labels, one each for total runs, errors and
  289.      * failures. There is also one label for each of these that
  290.      * describes what the label is. It could be done with one label
  291.      * instead of two but that would make updates much harder.
  292.      *
  293.      * @access private
  294.      * @param  none 
  295.      * @return &object A box containing the labels.
  296.      */
  297.     function &_createReportLabels()
  298.     {
  299.         // Create a box to hold everything.
  300.         $labelBox         =new GtkHBox;
  301.  
  302.         // Create the non-updated labels.
  303.         $numberOfRuns     =new GtkLabel('Runs:');
  304.         $numberOfErrors   =new GtkLabel('Errors:');
  305.         $numberOfFailures =new GtkLabel('Failures:');
  306.  
  307.         // Create the labels that will be updated.
  308.         // These are asssigned to members to make it easier to
  309.         // set their values later.
  310.         $this->numberOfRuns     =new GtkLabel(0);
  311.         $this->numberOfErrors   =new GtkLabel(0);
  312.         $this->numberOfFailures =new GtkLabel(0);
  313.  
  314.         // Pack everything in.
  315.         $labelBox->pack_start($numberOfRuns);
  316.         $labelBox->pack_start($this->numberOfRuns);
  317.         $labelBox->pack_start($numberOfErrors);
  318.         $labelBox->pack_start($this->numberOfErrors);
  319.         $labelBox->pack_start($numberOfFailures);
  320.         $labelBox->pack_start($this->numberOfFailures);
  321.  
  322.         return $labelBox;
  323.     }
  324.  
  325.     /**
  326.      * Create the success/failure indicator.
  327.      *
  328.      * A GtkProgressBar is used to visually indicate how many
  329.      * tests were successful compared to how many were not. The
  330.      * progress bar shows the percentage of success and will
  331.      * change from green to red if there are any failures.
  332.      *
  333.      * @access private
  334.      * @param  none 
  335.      * @return &object The progress bar
  336.      */
  337.     function &_createProgressBar()
  338.     {
  339.         // Create the progress bar.
  340.         $this->progress =new GtkProgressBar(new GtkAdjustment(001.110));
  341.  
  342.         // Set the progress bar to print the percentage.
  343.         $this->progress->set_show_text(true);
  344.  
  345.         return $this->progress;
  346.     }
  347.  
  348.     /**
  349.      * Create the report text areas.
  350.      *
  351.      * The report area consists of one text area for failures, one
  352.      * text area for errors and one label for identification purposes.
  353.      * All three widgets are packed into a box.
  354.      *
  355.      * @access private
  356.      * @param  none 
  357.      * @return &object The box containing the report areas.
  358.      */
  359.     function &_createReportAreas()
  360.     {
  361.         // Create the containing box.
  362.         $reportBox =new GtkVBox;
  363.  
  364.         // Create the identification label
  365.         $reportLabel =new GtkLabel('Errors and Failures:');
  366.         $reportLabel->set_alignment(00);
  367.  
  368.         // Create the scrolled windows for the text areas.
  369.         $reportScroll =new GtkScrolledWindow;
  370.         $dumpScroll   =new GtkScrolledWindow;
  371.  
  372.         // Make the scroll areas big enough.
  373.         $reportScroll->set_usize(-1150);
  374.         $dumpScroll->set_usize(-1150);
  375.  
  376.         // Only show the vertical scroll bar when needed.
  377.         // Never show the horizontal scroll bar.
  378.         $reportScroll->set_policy(GTK_POLICY_NEVERGTK_POLICY_AUTOMATIC);
  379.         $dumpScroll->set_policy(GTK_POLICY_NEVERGTK_POLICY_AUTOMATIC);
  380.  
  381.         // Create the text areas.
  382.         $this->reportArea =new GtkText;
  383.         $this->dumpArea =new GtkText;
  384.  
  385.         // Don't let words get broken.
  386.         $this->reportArea->set_word_wrap(true);
  387.         $this->dumpArea->set_word_wrap(true);
  388.  
  389.         // Pack everything in.
  390.         $reportBox->pack_start($reportLabel);
  391.         $reportScroll->add($this->reportArea);
  392.         $reportBox->pack_start($reportScroll);
  393.         $dumpScroll->add($this->dumpArea);
  394.         $reportBox->pack_start($dumpScroll);
  395.  
  396.         return $reportBox;
  397.     }
  398.  
  399.     /**
  400.      * Create a status label.
  401.      *
  402.      * A status line at the bottom of the application is used
  403.      * to notify the user of non-test related messages such as
  404.      * failures loading a test suite.
  405.      *
  406.      * @access private
  407.      * @param  none 
  408.      * @return &object The status label.
  409.      */
  410.     function &_createStatusLine()
  411.     {
  412.         // Create the status label.
  413.         $this->statusLine =new GtkLabel('');
  414.         $this->statusLine->set_alignment(00);
  415.  
  416.         return $this->statusLine;
  417.     }
  418.  
  419.     /**
  420.      * Show a popup with information about the application.
  421.      *
  422.      * The popup should show information about the version,
  423.      * the author, the license, where to get the latest
  424.      * version and a short description.
  425.      *
  426.      * @access public
  427.      * @param  none 
  428.      * @return void 
  429.      */
  430.     function about()
  431.     {
  432.         // Create the new window.
  433.         $about =new GtkWindow;
  434.         $about->set_title('About PHPUnit GUI Gtk');
  435.         $about->set_usize(250-1);
  436.  
  437.         // Put two vboxes in the hbox.
  438.         $vBox =new GtkVBox;
  439.         $about->add($vBox);
  440.  
  441.         // Create the labels.
  442.         $version     =new GtkLabel(" Version: 1.0");
  443.         $license     =new GtkLabel(" License: PHP License v3.0");
  444.         $where       =new GtkLabel(" Download from: http://pear.php.net/PHPUnit/");
  445.         $unitAuth    =new GtkLabel(" PHPUnit Author: Sebastian Bergman");
  446.         $gtkAuth     =new GtkLabel(" Gtk GUI Author: Scott Mattocks");
  447.  
  448.         // Align everything to the left
  449.         $where->set_alignment(0.5);
  450.         $version->set_alignment(0.5);
  451.         $license->set_alignment(0.5);
  452.         $gtkAuth->set_alignment(0.5);
  453.         $unitAuth->set_alignment(0.5);
  454.  
  455.         // Pack everything into the vBox;
  456.         $vBox->pack_start($version);
  457.         $vBox->pack_start($license);
  458.         $vBox->pack_start($where);
  459.         $vBox->pack_start($unitAuth);
  460.         $vBox->pack_start($gtkAuth);
  461.  
  462.         // Connect the destroy signal.
  463.         $about->connect('destroy'array('gtk''true'));
  464.  
  465.         // Show the goods.
  466.         $about->show_all();
  467.     }
  468.  
  469.     /**
  470.      * Load the test suite.
  471.      *
  472.      * This method tries to load test suite based on the user
  473.      * info. If the user passes the name of a tests suite, it
  474.      * is instantiated and a new object is returned. If the
  475.      * user passes a file that contains a test suite, the class
  476.      * is instantiated and a new object is returned. If the user
  477.      * passes a file that contains a test case, the test case is
  478.      * passed to a new test suite and the new suite object is
  479.      * returned.
  480.      *
  481.      * @access public
  482.      * @param  string  The file that contains a test case/suite or the classname.
  483.      * @return &object The new test suite.
  484.      */
  485.     function &loadTest(&$file)
  486.     {
  487.         // Check to see if a class name was given.
  488.         if (is_a($file'PHPUnit_TestSuite')) {
  489.             return $file;
  490.         elseif (class_exists($file)) {
  491.             require_once 'PHPUnit/TestSuite.php';
  492.             return new PHPUnit_TestSuite($file);
  493.         }
  494.  
  495.         // Check that the file exists.
  496.         if (!@is_readable($file)) {
  497.             $this->_showStatus('Cannot find file: ' $file);
  498.             return false;
  499.         }
  500.  
  501.         $this->_showStatus('Loading test suite...');
  502.  
  503.         // Instantiate the class.
  504.         // If the path is /path/to/test/TestClass.php
  505.         // the class name should be test_TestClass
  506.         require_once $file;
  507.         $className str_replace(DIRECTORY_SEPARATOR'_'$file);
  508.         $className substr($className0strpos($className'.'));
  509.  
  510.         require_once 'PHPUnit/TestSuite.php';
  511.         return new PHPUnit_TestSuite($className);
  512.     }
  513.  
  514.     /**
  515.      * Run the test suite.
  516.      *
  517.      * This method runs the test suite and updates the messages
  518.      * for the user. When finished it changes the status line
  519.      * to 'Test Complete'
  520.      *
  521.      * @access public
  522.      * @param  none 
  523.      * @return void 
  524.      */
  525.     function runTest()
  526.     {
  527.         // Notify the user that the test is running.
  528.         $this->_showStatus('Running Test...');
  529.  
  530.         // Run the test.
  531.         $result PHPUnit::run($this->suite);
  532.  
  533.         // Update the labels.
  534.         $this->_setLabelValue($this->numberOfRuns,     $result->runCount());
  535.         $this->_setLabelValue($this->numberOfErrors,   $result->errorCount());
  536.         $this->_setLabelValue($this->numberOfFailures$result->failureCount());
  537.  
  538.         // Update the progress bar.
  539.         $this->_updateProgress($result->runCount(),
  540.                                $result->errorCount(),
  541.                                $result->failureCount()
  542.                                );
  543.  
  544.         // Show the errors.
  545.         $this->_showFailures($result->errors()$this->dumpArea);
  546.  
  547.         // Show the messages from the tests.
  548.         if ($this->showPassed->get_active()) {
  549.             // Show failures and success.
  550.             $this->_showAll($result$this->reportArea);
  551.         else {
  552.             // Show only failures.
  553.             $this->_showFailures($result->failures()$this->reportArea);
  554.         }
  555.  
  556.         // Update the status message.
  557.         $this->_showStatus('Test complete');
  558.     }
  559.  
  560.     /**
  561.      * Set the text of a label.
  562.      *
  563.      * Change the text of a given label.
  564.      *
  565.      * @access private
  566.      * @param  widget  &$label The label whose value is to be changed.
  567.      * @param  string  $value  The new text of the label.
  568.      * @return void 
  569.      */
  570.     function _setLabelValue(&$label$value)
  571.     {
  572.         $label->set_text($value);
  573.     }
  574.  
  575.     /**
  576.      * The main work of the application.
  577.      *
  578.      * Load the test suite and then execute the tests.
  579.      *
  580.      * @access public
  581.      * @param  none 
  582.      * @return void 
  583.      */
  584.     function run()
  585.     {
  586.         // Load the test suite.
  587.         $this->suite =$this->loadTest($this->suiteField->get_text());
  588.  
  589.         // Check to make sure the suite was loaded properly.
  590.         if (!is_object($this->suite)) {
  591.             // Raise an error.
  592.             $this->_showStatus('Could not load test suite.');
  593.             return false;
  594.         }
  595.  
  596.         // Run the tests.
  597.         $this->runTest();
  598.     }
  599.  
  600.     /**
  601.      * Update the status message.
  602.      *
  603.      * @access private
  604.      * @param  string  $status The new message.
  605.      * @return void 
  606.      */
  607.     function _showStatus($status)
  608.     {
  609.         $this->statusLine->set_text($status);
  610.     }
  611.  
  612.     /**
  613.      * Alias for main()
  614.      *
  615.      * @see main
  616.      */
  617.     function show($showPassed = true)
  618.     {
  619.         $this->main($showPassed);
  620.     }
  621.  
  622.     /**
  623.      * Add a suite to the tests.
  624.      *
  625.      * This method is require by SetupDecorator. It adds a
  626.      * suite to the the current set of suites.
  627.      *
  628.      * @access public
  629.      * @param  object $testSuite The suite to add.
  630.      * @return void 
  631.      */
  632.     function addSuites($testSuite)
  633.     {
  634.         if (!is_array($testSuite)) {
  635.             settype($testSuite'array');
  636.         }
  637.  
  638.         foreach ($testSuite as $suite{
  639.  
  640.             if (is_a($this->suite'PHPUnit_TestSuite')) {
  641.                 $this->suite->addTestSuite($suite->getName());
  642.             else {
  643.                 $this->suite =$this->loadTest($suite);
  644.             }
  645.  
  646.             // Set the suite field.
  647.             $text $this->suiteField->get_text();
  648.             if (empty($text)) {
  649.                 $this->suiteField->set_text($this->suite->getName());
  650.             }
  651.         }
  652.     }
  653.  
  654.     /**
  655.      * Show all test messages.
  656.      *
  657.      * @access private
  658.      * @param  object  The TestResult from the test suite.
  659.      * @return void 
  660.      */
  661.     function _showAll(&$result)
  662.     {
  663.         // Clear the area first.
  664.         $this->reportArea->delete_text(0-1);
  665.         $this->reportArea->insert_text($result->toString()0);
  666.     }
  667.  
  668.     /**
  669.      * Show failure/error messages in the given text area.
  670.      *
  671.      * @access private
  672.      * @param  object  &$results The results of the test.
  673.      * @param  widget  &$area    The area to show the results in.
  674.      */
  675.     function _showFailures(&$results&$area)
  676.     {
  677.         $area->delete_text(0-1);
  678.         foreach (array_reverse($resultstrueas $result{
  679.             $area->insert_text($result->toString()0);
  680.         }
  681.     }
  682.  
  683.     /**
  684.      * Update the progress indicator.
  685.      *
  686.      * @access private
  687.      * @param  integer $runs 
  688.      * @param  integer $errors 
  689.      * @param  integer $failures 
  690.      * @return void 
  691.      */
  692.     function _updateProgress($runs$errors$failures)
  693.     {
  694.         $percentage = 1 - (($errors $failures$runs);
  695.         $this->progress->set_percentage($percentage);
  696.     }
  697. }
  698. ?>

Documentation generated on Mon, 11 Mar 2019 14:22:35 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.