Page 3 of 5

Posted: Wed Aug 23, 2006 3:55 am
by Jenk
Cool :)

nice easy one :P

Code: Select all

class testOfHttpRequest extends UnitTestCase
{
    public function testCreationOfNewRequestMethod()
    {
        $_POST['dumy'] = 1;
        $request = new HttpRequest('post');
        $this->assertIdentical($_POST, $request->getRequestGlobal());
        $_POST = array(); //Clean up
    }

    public function testRetrievalOfSingleRequestVar()
    {
        $_POST['dumy'] = 1;
        $request = new HttpRequest('post');
        $this->assertIdentical($_POST['dumy'], $request->get('dumy'));
        $_POST = array(); //Clean up
    }

    public function testCheckVarExists()
    {
        $request = new HttpRequest('post');
        $this->assertFalse($request->has('dumy'));
        unset($request);
        $_POST['dumy'] = 1;
        $request = new HttpRequest('post');
        $this->assertTrue($request->has('dumy'));
        $_POST = array(); //Clean up
    }

    public function testOfGETRequestMethod()
    {
        $_GET['dummy'] = 1;
        $request = new HttpRequest('get');
        $this->assertIdentical($_GET, $request->getRequestGlobal());
        $this->assertTrue($request->has('dummy'));
        $this->assertIdentical($_GET['dummy'], $request->get('dummy'));
        $_GET = array();
    }
    
    public function testOfCOOKIERequestMethod()
    {
        $_COOKIE['dummy'] = 1;
        $request = new HttpRequest('cookie');
        $this->assertIdentical($_COOKIE, $request->getRequestGlobal());
        $this->assertTrue($request->has('dummy'));
        $this->assertIdentical($_COOKIE['dummy'], $request->get('dummy'));
        $_COOKIE = array();
    }
}
Though strictly speaking, it's not an actual request method - but's all part of the same jive within the HTTP header/request and is succumb to the same practices such as magic quotes :)

Code: Select all

class HttpRequest
{
    protected $reqVar;

    public function __construct($method)
    {
        switch (strtolower($method))
        {
            case 'get': $this->reqVar = $_GET;
            break;
            case 'post': $this->reqVar = $_POST;
            break;
            case 'cookie': $this->reqVar = $_COOKIE;
            break;
        }
    }
    
    public function getRequestGlobal()
    {
        return $this->reqVar;
    }

    public function get ($name)
    {
        return $this->reqVar[$name];
    }

    public function has ($name)
    {
        return isset($this->reqVar[$name]);
    }
}

Posted: Wed Aug 23, 2006 10:41 am
by Luke
now what? :?

Posted: Wed Aug 23, 2006 10:48 am
by Jenk
get_magic_quotes_gpc() ?

Posted: Wed Aug 23, 2006 1:08 pm
by Luke
I am not quite sure how to go about that... How would you fake magic_quotes being on? just addslashes() to the dummy text?

Posted: Wed Aug 23, 2006 1:26 pm
by Chris Corbyn
The Ninja Space Goat wrote:I am not quite sure how to go about that... How would you fake magic_quotes being on? just addslashes() to the dummy text?
Exactly... if you can use addslashes() to do it yourself then you've mimmicked it. As for the class detecting that, use ini_set() to fool it ;) It doesn't need to really be happening.... you can set things up artificially like this ;)

Posted: Wed Aug 23, 2006 1:33 pm
by Luke
I don't think ini_set works for setting the magic_quotes because it is already done by the time your php script is run... isn't it?

Posted: Wed Aug 23, 2006 1:42 pm
by Chris Corbyn
Gah, you're right I just tried it. I didn't expect it to actually be turned on, but at least allow ini_get() to think it is. Looks like we're going to need to write a method to return TRUE or FALSE if magic quotes is on or not. That way we can fake it's return value ;)

Posted: Wed Aug 23, 2006 1:49 pm
by Chris Corbyn
I can do this if you want to watch and then do the next step? :)

Posted: Wed Aug 23, 2006 1:53 pm
by Luke
I'd appreciate it... I've been ripping my hair out :x

Posted: Wed Aug 23, 2006 2:16 pm
by Chris Corbyn
The Ninja Space Goat wrote:I'd appreciate it... I've been ripping my hair out :x
;) The clue is to use a partial Mock. This finished up with me needing to make a few other modifications to keep the original tests passing. Interestingly, I needed to make sure the item was a string before stripslashing it, otherwsie the assertIdentical assertions fails with a type mismatch where we had an integer.

The test

Code: Select all

class testOfHttpRequest extends UnitTestCase
{
    public function testCreationOfNewRequestMethod()
    {
        $_POST['dumy'] = 1;
        $request = new HttpRequest('post');
        $this->assertIdentical($_POST, $request->getRequestGlobal());
        $_POST = array(); //Clean up
    }

    public function testRetrievalOfSingleRequestVar()
    {
        $_POST['dumy'] = 1;
        $request = new HttpRequest('post');
        $this->assertIdentical($_POST['dumy'], $request->get('dumy'));
        $_POST = array(); //Clean up
    }

    public function testCheckVarExists()
    {
        $request = new HttpRequest('post');
        $this->assertFalse($request->has('dumy'));
        unset($request);
        $_POST['dumy'] = 1;
        $request = new HttpRequest('post');
        $this->assertTrue($request->has('dumy'));
        $_POST = array(); //Clean up
    }

    public function testOfGETRequestMethod()
    {
        $_GET['dummy'] = 1;
        $request = new HttpRequest('get');
        $this->assertIdentical($_GET, $request->getRequestGlobal());
        $this->assertTrue($request->has('dummy'));
        $this->assertIdentical($_GET['dummy'], $request->get('dummy'));
        $_GET = array();
    }

    public function testOfCOOKIERequestMethod()
    {
        $_COOKIE['dummy'] = 1;
        $request = new HttpRequest('cookie');
        $this->assertIdentical($_COOKIE, $request->getRequestGlobal());
        $this->assertTrue($request->has('dummy'));
        $this->assertIdentical($_COOKIE['dummy'], $request->get('dummy'));
        $_COOKIE = array();
    }

    public function testOutputIsClean()
    {
        Mock::GeneratePartial('HttpRequest', 'MockHttpRequest', array('magicQuotesIsOn', 'getRequestGlobal'));

        $input = "What's happenin' boys?";
        $_GET['dummy'] = addslashes($input);
        $request = new MockHttpRequest($this);
        $request->setReturnValue('getRequestGlobal', $_GET);
        $request->setReturnValue('magicQuotesIsOn', false);
        $this->assertEqual("What\\'s happenin\\' boys?", $request->get('dummy'));
        unset($request);

        $request = new MockHttpRequest($this);
        $request->setReturnValue('getRequestGlobal', $_GET);
        $request->setReturnValue('magicQuotesIsOn', true);
        $this->assertEqual("What's happenin' boys?", $request->get('dummy'));
        $_GET = array();
    }
}
And the code:

Code: Select all

class HttpRequest
{
    protected $reqVar;

    public function __construct($method)
    {
        switch (strtolower($method))
        {
            case 'get': $this->reqVar = $_GET;
            break;
            case 'post': $this->reqVar = $_POST;
            break;
            case 'cookie': $this->reqVar = $_COOKIE;
            break;
        }
    }

    public function getRequestGlobal()
    {
        return $this->reqVar;
    }

    public function get ($name)
    {
        $req = $this->getRequestGlobal();
        return $this->cleanRequestVar($req[$name]);
    }

    public function has ($name)
    {
        $req = $this->getRequestGlobal();
        return isset($req[$name]);
    }

    public function cleanRequestVar($req)
    {
        if (!$this->magicQuotesIsOn()) return $req;
        else
        {
            $return = array();
            if (is_array($req))
            {
                foreach ($req as $key => $value) $ret[$key] = $this->cleanRequestVar($value);
            }
            else
            {
                if (is_string($req)) return stripslashes($req);
                else return $req;
            }
        }
    }

    public function magicQuotesIsOn()
    {
        if (get_magic_quotes_gpc()) return true;
        else return false;
    }
}
By generating a partial mock we could mimmick the behaviour as if magic quotes was on. My big greivance with these (unless I'm missing something) is that you can set constructor params in the usual way so I ended up slightly changing the code for get() and has().

Posted: Wed Aug 23, 2006 2:19 pm
by Chris Corbyn
Someone wanna test that still works with COOKIE? I totally never covered that one. Not sure magic_quotes screws with cookie data does it?

Posted: Wed Aug 23, 2006 3:16 pm
by Ollie Saunders
Sorry to rain on your parade but if you are doing true TDD you should have written the tests before the code. But keep going anyway this looks good. I'm following closely because i'm writing a lot of unit tests at the moment.
feyd wrote:static properties are almost as bad as singletons
I do prefer static classes to singletons. What is bad about static properties? Not the principle surely.
Also I'm interested what is the definition of a plugin in the sense you have been using it? I still think of them as those things for Winamp.

Posted: Wed Aug 23, 2006 3:31 pm
by Chris Corbyn
ole wrote:Sorry to rain on your parade but if you are doing true TDD you should have written the tests before the code. But keep going anyway this looks good. I'm following closely because i'm writing a lot of unit tests at the moment.
feyd wrote:static properties are almost as bad as singletons
I do prefer static classes to singletons. What is bad about static properties? Not the principle surely.
Also I'm interested what is the definition of a plugin in the sense you have been using it? I still think of them as those things for Winamp.
Excuse me. We have been writing tests, and then writing code. My understanding was that you write a small test, then write some code to pass it. Then write another test, followed by the code to pass it etc etc.

How on earth could you possibly drive the direction of development if you wrote an entire lengthy set of tests before ever writing the code? Yes test first, code second, but not *all tests* then *all code*. Maybe I misunderstood you?

Posted: Wed Aug 23, 2006 3:39 pm
by Chris Corbyn
ole wrote:Also I'm interested what is the definition of a plugin in the sense you have been using it? I still think of them as those things for Winamp.
Ah ha ;) And what do winamp plugins do? They change the behaviour of the application. We can do just the same with PHP code. Plugins adhere to an API which gives them access to components in the pluggable system, and also allows the pluggable system to trigger calls in the plugins. :)

Posted: Wed Aug 23, 2006 4:08 pm
by Ollie Saunders
Excuse me. We have been writing tests, and then writing code. My understanding was that you write a small test, then write some code to pass it. Then write another test, followed by the code to pass it etc etc.
My mistake, there was too much to read.
How on earth could you possibly drive the direction of development if you wrote an entire lengthy set of tests before ever writing the code? Yes test first, code second, but not *all tests* then *all code*. Maybe I misunderstood you?
This is an interesting point, exactly how many test should you write before swaping to code? I'm only new to TDD myself; all us newbies together can't be great?! I've been reading that Beck's book on TDD and this isn't specified so far.