SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 42
  1. #1
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Red face Simple Test::Huh?

    Hello,

    Been doing some refactoring, and using Simple Test, there seams to be problem. Is it a problem with Simple Test, since I got the scripts working as they should without using Simple Test after scratching my head for an hour

    Ironic? I don't know, since I kind of depend on Simple Test now, as do a lot of other people, so what is wrong folks?

    PHP Code:
    error_reportingE_ALL ); // php5.0.3 
    PHP Code:
    define'SIMPLE_TEST''../tools/simpletest/' );
        require_once( 
    SIMPLE_TEST.'reporter.php' );
        require_once( 
    SIMPLE_TEST.'unit_tester.php' );
        
        class 
    TestActionHandlers extends UnitTestCase {
            public function 
    __construct() {
                
    parent::__construct'Test: Action Handler' );
            }
            
            public function 
    testIsActionHandler() {
                
    $handler = new PageActionHandler'admin/' );
                
    $this -> assertTrue$handler'IActionHandler' );
            }
            
            public function 
    testHasChildren() {
                
    $handler = new PageActionHandler'admin/' );
                
    $this -> assertFalse( !$handler -> hasChildren() );
            }
            
            public function 
    testGetIdentity() {
                
    $handler = new PageActionHandler'admin/' );
                
    $this -> assertTrue$handler -> getId(), 'page' );
            }
        }
        
        
    $test = new TestActionHandlers();
        
    $test -> run( new HtmlReporter() ); 
    PHP Code:
    abstract class BaseActionHandler implements IActionHandler {
            protected 
    $children = array();
            
            public function 
    __construct$pathname ) { 
                if( 
    file_exists$filename Handle::resolve$pathname ).'/config.php' ) ) {
                    require_once( 
    $filename );
                    foreach( 
    $children as $child => $params ) {
                        
    $tagname $child;
                        
    $classid array_shift$params );
                        
    $globals array_shift$params );
                        
                        if( empty( 
    $globals ) ) {
                            
    // action handler resides in current path
                            
    $filename Handle::resolve$pathname.$tagname );
                            
    $t_name $pathname.$tagname;
                        } else {
                            
    // action handler resides outside current path
                            
    $filename Handle::resolve$globals.$tagname );
                            
    $t_name $globals.$tagname;
                        }
                        
    // fetch action handler, ignore errors if file not found
                        
    @require_once( $filename.'/handler.class.php' );
                        if( 
    class_existsstrtolower$classid ) ) ) {
                            
    // file was fetched
                            
    $handler = new $classid$t_name.'/' );
                            
    $this -> attach$handler );
                        }
                    }
                } 
            }
            
            public function 
    getId() {
                return 
    $this -> id;
            }
            
            public function 
    hasChildren() {
                return 
    count$this -> children );
            }
            
            public function 
    getChildren() {
                return 
    $this -> children;
            }
            
            public function 
    attachIComposite $composite ) {
                
    $this -> children[$composite -> getId()] = $composite;
            }
            abstract public function 
    executeIResponse $response );
        }

    class 
    Handle {} 
    PHP Code:
    class PageActionHandler extends BaseActionHandler {
            protected 
    $id 'page';
            
            public function 
    __construct$pathname ) {
                
    parent::__construct$pathname );
            }
            
            public function 
    executeIResponse $response ) {
            }
        }

    // ./modules/admin/body/handler.class.php
    class BodyActionHandler {}

    // ./modules/common/menu/handler.class.php
    class MenuActionHandler {} 
    Code:
    // ./modules/admin/config.php
    
    $children = array(
    		'body'		=> 	array(
    			
    			'classid'	=>	'BodyActionHandler',
    			'globals'	=>	'' ),
    			
    		'menu'		=>	array(
    			'classid'	=>	'MenuActionHandler',
    			'globals'	=>	'common/' )
     
    		);
    Basically, the problem is that with Simple Test, I get these errors,

    Code:
    Fail: testHasChildren -> False assertion got True at line [103]
    Exception: testHasChildren -> Unexpected PHP error [Invalid argument supplied for foreach()] severity [E_WARNING] in [C:\Apache2\htdocs\public_html\index.php] line [29]
    Exception: testGetIdentity -> Unexpected PHP error [Invalid argument supplied for foreach()] severity [E_WARNING] in [C:\Apache2\htdocs\public_html\index.php] line [29]
    Any help would be much sought after, thanks.
    Last edited by Dr Livingston; Sep 20, 2005 at 10:09.

  2. #2
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looks to me like SimpleTest is just telling you that you have errors in your code:

    PHP Code:
            public function __construct$pathname ) {
                if( 
    file_exists$filename Handle::resolve$pathname ).'/config.php' ) ) {
                    require_once( 
    $filename );
                    foreach( 
    $children as $child => $params ) { 
    $children is not defined, therefor throwing Invalid argument errors, and getChildren() is counting an empty array, returning 0 which you are negating to true in your false assertion.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  3. #3
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ah... Damn

    I never seen that one, god damn it

    So, you think the tests will pass if I change it to the following?

    PHP Code:
    // ...
    foreach( $this -> children as $child ) { ... 
    EDIT:

    Whilst the script worked outside the tests, it took Unit Testing to find the bug. Had I not bothered with Unit Testing, well, need I say more?

    Just goes to show just how important Unit Testing is, and what it can do for you

    My face is still read btw, but not near as red as it was before
    Last edited by Dr Livingston; Sep 20, 2005 at 10:49.

  4. #4
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Whilst the script worked outside the tests, it took Unit Testing to find the bug. Had I not bothered with Unit Testing, well, need I say more?

    Just goes to show just how important Unit Testing is, and what it can do for you
    I'm not here to diminish the quality of Unit Testing, but it is no substitute for just generally good coding practices.

    For example, always pre-define your variables. Even though PHP doesn't require this [though it does throw a warning if you don't]. Anytime I code a foreach() now, I'm always thinking "where did this array come from?". If there's not a clear path, I've done something wrong.

    And always develop with E_ALL to catch all warnings, with or without Unit Testing [which would have immediately caught the error before even implementing the test].

    Things like this can go a long way to avoiding these kinds of mistakes in general. You certainly don't need Unit Testing to catch stuff like this.

  5. #5
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The variable in question was already defined, but the problem is that I am a touch typist, and type something like 70 odd words a minute. The abstract class is not new to me, and so typed it from memory.

    But I neglected to reference to the class property in this case, so it's just a case of a typing mistake on my part, and not something more lethal such as a programmatic mistake.

    And so, I didn't pickup on the typing mistake, since I knew the class from memory and so I wasn't looking for it. Unit Testing or not, a typo can bring down your scripts, in this case Unit Testing caught the error in question.

    Better to be safe than not I think

  6. #6
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Unit Testing or not, a typo can bring down your scripts, in this case Unit Testing caught the error in question.
    That is exactly my point. Unit Testing did not catch this error. PHP caught the error itself and sent you notice in the form of a warning. Developing with a high error reporting level will catch these kinds errors, regardless of how you test. You just didn't see it, because I am guessing prior to implementing the Unit Test, you did not have error reporting set to a high level.

    You said you thought the script was working as it should without running the unit test, and I am saying that always developing with a high level of error reporting, you would have immediately caught the error when just running the script, and avoided the headache that ensued

  7. #7
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you did not have error reporting set to a high level.
    Well, I always use this at the top of the file,

    PHP Code:
    error_reportingE_ALL E_STRICT ); 
    But with Simple Test, using PHP5.x you need to remove the E_STRICT for obvious reasons. What do you use if there is something that is more robust than that?

    Unit Testing did not catch this error.
    True, but in my case, PHP didn't catch it either

  8. #8
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    True, but in my case, PHP didn't catch it either
    If you ran the class, it did. I don't doubt that you didn't see the warning, but PHP did catch it. Maybe you have display errors turned off or something, but PHP did in fact catch the error. otherwise, you would have not gotten a "php warning" from simple test.

    I use a custom error handler to catch stuff like this, that stops script execution dead in its tracks and spits out to the browser the error or warning, plus a traceback with a source code snippet for each part of the traceback with a 10 line buffer around each part, to quickly see the problem.

    But just a normal php warning will do as well, which should show up with or without the unit test when running your script (unless you have it set to not output warnings or errors).

    Again, I'm not trying to dismiss unit testing, but PHP is more than capable of catching alot of those silly programmatic goofs we all do.

  9. #9
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, I don't really know, but this part...

    PHP Code:
    // ...
    foreach( $children as $child ) { ... 
    The variable $children resides in the REQUIREd file, and in this case, there is an array, with indexes. This is what puzzled me, since the script works w/out Unit Testing, and going by what Jason had to say.

    Looking again, Simple Test throws up an error with this script. I don't really know why it does this, since the variable is set. To stop the error, I'm using

    PHP Code:
    // ...
    if( isset( $children ) ) {
    foreach( 
    $children as $child ) { ... 
    This stops Simple Test throwing an error, but despite the variable being set, and that there are child elements, that isn't the case with the tests.

    Which brings to me ask why is Simple Testing throwing an error? I now belive after all this that there is something wrong with Simple Test.

    Spooky.

  10. #10
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    The variable $children resides in the REQUIREd file, and in this case, there is an array, with indexes. This is what puzzled me, since the script works w/out Unit Testing, and going by what Jason had to say.
    Now I am equally as puzzled... if $children is in the required file and is an array, then there should be no reason for the PHP warning simpletest gives back that I can see.

    Is that "foreach( $children as $child => $params ) {" line 29 of your index.php script that the warning references?

  11. #11
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape
    I'm not here to diminish the quality of Unit Testing, but it is no substitute for just generally good coding practices.
    ...
    You certainly don't need Unit Testing to catch stuff like this.
    There really is no substitute for testing. I would lay a fairly large bet that you'll find bugs in an untested app which you didn't realise were there. The discipline of testing leads you to think about the behaviour of a class in much greater detail thus leading to better quality code.

    As a ball park figure, say you make ten thousand individual assertions on average per day while coding (and running tests constantly). Over the lifetime of an app, that could add up to millions. There's no way you can get near this level of assurance without an automated testing tool which can run all tests in a few minutes at the click of a button.

  12. #12
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    if $children is in the required file and is an array, then there should be no reason for the PHP warning simpletest gives back that I can see.
    Exactly The point that Simple Test is throwing an error is what is leading me to think that there is something wrong with Simple Test it's self.

    I thought that there was something for a brief moment, wrong with my script but that isn't the case. The error thrown by Simple Test indeed does reside on line 29, where the foreach() is. I don't get the error anymore due to the isset() but in saying that, any tests don't recognise any child elements.

    Which is complete nonsense. If I could go as far as saying that this is a bug, I don't know if it's due to me using PHP5.x or not, but could someone using what I've posted, try to duplicate it using PHP4.x?

    If this is a bug, it needs to be documented so other developers are made aware of it. Anyways, at the moment I'm unable to use Simple Test, so if anyone can offer a solution, I'd most welcome it.

    Thanks

  13. #13
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by McGruff
    There really is no substitute for testing. I would lay a fairly large bet that you'll find bugs in an untested app which you didn't realise were there. The discipline of testing leads you to think about the behaviour of a class in much greater detail thus leading to better quality code.
    When the hell did I say don't test?

  14. #14
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, you didn't, not directly, but I think that it could be seen as being implied?

    Again, I'm not trying to dismiss unit testing, but PHP is more than capable of catching alot of those silly programmatic goofs we all do.
    Unit Testing and the art of testing prevents those silly programmatic goofs from ever happening. Ie With Unit Testing, you can catch the errors before PHP catches them, as you can do that, knowing that any tests will return a red bar without fail.

    Remember that went we are talking errors, we are not only talking about syntax errors, we are talking logic errors as well... Which PHP does not pick up on

  15. #15
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    >> but I think that it could be seen as being implied?

    That's quite a jump to make.

    >> Ie With Unit Testing, you can catch the errors before PHP catches them

    And how exactly is that? Is a Unit Test able to catch them before executing the code? I don't think so. PHP catches it and passes it onto the Unit Test or whatever handler you are using at that moment.

    >> we are talking logic errors as well.. Which PHP does not pick up on

    Which is where unit testing, etc comes in. And also that thing of yours called a brain.

  16. #16
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's quite a jump to make.
    Not really, not so much of a jump, maybe a step.

    Ie With Unit Testing, you can catch the errors before PHP catches them
    Was thinking of something else, but your right.

    And also that thing of yours called a brain.
    What brain? Who said that I have a brain huh?

  17. #17
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    I thought that there was something for a brief moment, wrong with my script but that isn't the case. The error thrown by Simple Test indeed does reside on line 29, where the foreach() is. I don't get the error anymore due to the isset() but in saying that, any tests don't recognise any child elements.

    Which is complete nonsense. If I could go as far as saying that this is a bug, I don't know if it's due to me using PHP5.x or not, but could someone using what I've posted, try to duplicate it using PHP4.x?
    I think what you are finding is that you are not excersizing the code in an identical manner to what you are in a normal run. Perhaps it is something like a path issue where you are in a tests/ sub directory and therefore the include file is not found in it normal relative path location, or something similar.

    Quote Originally Posted by Dr Livingston
    If this is a bug, it needs to be documented so other developers are made aware of it. Anyways, at the moment I'm unable to use Simple Test, so if anyone can offer a solution, I'd most welcome it.
    Pretty amazing how SimpleTest was able to inject that bug into a line of your code!!!!
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  18. #18
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think what you are finding is that you are not excersizing the code in an identical manner to what you are in a normal run.
    Sorry Jason, but that isn't the case. The scripts being tested are as is, as in a real example of use. I have attached the files in question, so unzip the file and folder, to your server, ie root folder,

    Code:
    http://localhost/index.php
    Where you have this for example,

    Code:
    + htdocs
    + --- modules
    + index.php
    If you add the following to the bottom of the file (index.php) you'll see the composite structure. This is what I've been testing with

    PHP Code:
     echo( '<pre>' ); print_r$page ); echo( '</pre>' ); 
    I have complete faith in Marcus and Simple Test and still believe in Unit Testing with Simple Test but this has me stumped (not that, that isn't difficult).

    If you find anything untoward, I'd be grateful to know more...

  19. #19
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    + htdocs
    + --- modules
    + index.php
    When I remember, it should be

    Code:
    + htdocs
    + --- public_html
    + ------ modules
    + --- index.php
    Code:
    http://localhost/public_html/index.php
    Either that, or adjust the base pathname in the Handle class

  20. #20
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, I downloaded your file, unzipped it, browsed to index.php and it dumped:

    Code:
    PageActionHandler Object
    (
        [id:protected] => page
        [children:protected] => Array
            (
            )
    
    )
    for which children is the same empty array that would return a count of 0 and be negated to true and therefor fail your assertion as requested.

    Other than that, isn't it awfully confusing to have a ton of files with the exact same names in different directories? Doesn't seem like the easiest way to keep things straight.

  21. #21
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm...

    I get something different, not using any tests. Using tests, Simple Test ignores any child elements, from the array that is from the file REQUIRE, so I don't understand why your only seeing the root element, and nothing more?

    Code:
    PageActionHandler Object
    (
        [id:protected] => page
        [children:protected] => Array
            (
                [body] => BodyActionHandler Object
                    (
                        [id:protected] => body
                        [children:protected] => Array
                            (
                                [breadcrumb] => BreadcrumbActionHandler Object
                                    (
                                        [id:protected] => breadcrumb
                                        [children:protected] => Array
                                            (
                                            )
    
                                    )
    
                            )
    
                    )
    
                [menu] => MenuActionHandler Object
                    (
                        [id:protected] => menu
                        [children:protected] => Array
                            (
                            )
    
                    )
    
            )
    
    )
    As to your other point, there is no confusion at all for me. As to this being a good approach to take or not I've not had much problems with it so far, ideally I would like to remove the dependency of the configuration files, so that each controller would know of it's own child controllers, but on the fly

  22. #22
    SitePoint Addict been's Avatar
    Join Date
    May 2002
    Location
    Gent, Belgium
    Posts
    284
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Still think, like Jason suggested, that it is a path problem, here's why:
    Primo, from class Handle:
    PHP Code:
    static public function resolve$pathname ) {
           return 
    $_SERVER['DOCUMENT_ROOT'].'/public_html/modules/'.$pathname;
                 } 
    Secundo, from class BaseActionHandler:
    PHP Code:
             if( file_exists$filename Handle::resolve$pathname ).'/config.php' ) ) {
                         @require_once( 
    $filename );
         
    // ... 
    Tertio, from the usage:
    PHP Code:
        $page = new PageActionHandler'admin/' ); 
    So, if I played PHP parser well enough, new PageActionHandler('admin/') will eventually resolve to the document root with '/public_html/modules/admin//config.php' appended to it (note the double slash)
    I'm guessing that only the test has the slash after 'admin', but your runtime code has not?
    Per
    Everything
    works on a PowerPoint slide

  23. #23
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm guessing that only the test has the slash after 'admin', but your runtime code has not?
    Nope, that is not it either. If only it were as simple as that, then I could get some sleep, but that isn't the case either. In both regards, they're the same.

    Anyways, earlier testing before the refactoring would have picked up on that surely?

  24. #24
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape
    When the hell did I say don't test?
    Charming.

  25. #25
    SitePoint Addict been's Avatar
    Join Date
    May 2002
    Location
    Gent, Belgium
    Posts
    284
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by been
    So, if I played PHP parser well enough, ...
    Apparently not...

    I've never even considered something like
    PHP Code:
    require_once 'modules///admin///config.php'
    would actually work...
    Per
    Everything
    works on a PowerPoint slide


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •