Expectations At Arbitrary Script-points

Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")

Moderator: General Moderators

Post Reply
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Expectations At Arbitrary Script-points

Post by Ambush Commander »

Recently, I tried to run this test code on SimpleTest:

Code: Select all

$this->mapper->expectArguments('delete', array(&$captcha1));
$this->mapper->expectArguments('delete', array(&$captcha2));
So it would always inextricably fail. I later found out that both expectArguments are checked on every method call, so one would always fail on me, rather than expectArguments represent possible arguments that could be passed.

So I ended up using expectArgumentsAt(). However, the UnitOfWork doesn't apply any particular logic on which order the captcha objects are passed to the mapper (it just so turned out that captcha1 came before captcha2). Which means a brittle testcase.

If you had to have this sort of testcase, what would you do? I have a sneaking suspicion that the solution is a custom Expectation class, but I'm not sure. What would you do?
User avatar
sweatje
Forum Contributor
Posts: 277
Joined: Wed Jun 29, 2005 10:04 pm
Location: Iowa, USA

Post by sweatje »

Code: Select all

$this->mapper->expectArgumentsAt(0, 'delete', array(&$captcha1));
$this->mapper->expectArgumentsAt(1, 'delete', array(&$captcha2));
Is really your only choice. I was bugging Marcus to have an "expectOnce" that was not alway the first one, but instead would just be happy if it was ever called, and he thought something similar might go into the rewrite of MockObjects in an upcomming version of simpletest.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

How about...

Code: Select all

class EqualsOneExpectation extends SimpleExpectation {
    
    var $validObjects = array();
    
    function test(&$obj) {
        foreach ($this->validObjects as $key => $value) { //assign by reference hack
            if ($this->validObjects[$key] === $obj) return true;
        }
        return false;
    }
    
    function add(&$obj) {
        $this->validObjects[] =& $obj;
    }
    
    function testMessage($obj) {
        return "Object [" . class_name($obj) . "] should match one of allowed objects";
    }
}

Code: Select all

$expectation =& new EqualsOneExpectation();
$expectation->add(&$captcha1);
$expectation->add(&$captcha2);
$this->mapper->expectArguments('delete',array(&$expectation));
This is what I was thinking... would it work?
User avatar
sweatje
Forum Contributor
Posts: 277
Joined: Wed Jun 29, 2005 10:04 pm
Location: Iowa, USA

Post by sweatje »

Code: Select all

foreach ($this->validObjects as $key => $value) { //assign by reference hack
is probably better written

Code: Select all

foreach (array_keys($this->validObjects) as $key) {
Also, I think I might lean towards an InListExpectation and just pass in the valid array of cadidates to the constructor.
Last edited by sweatje on Sat Oct 22, 2005 10:24 pm, edited 1 time in total.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Mmm... never thought of that...
Post Reply