oct
25
2011

par Paul

Je n’étais pas content de la syntaxe des tests unitaires avec Symfony:

$t->comment('::foo()');
$t->is(foo('dawa'), 'dawa', 'foo() dummy function.');

foo() est dupliqué lors de l’écriture des tests.

Qui produisait un affichage :

# foo()
ok 1 - foo() dummy function

J’ai donc écrit un proxy à lime_test ce qui donne comme écriture :

$tester = new Tester();
$result = $tester->test('foo()', function() use(&$tester){
    $tester->is(foo('dawa'), 'dawa', 'dummy function');
    return foo('dawa');
});

ce qui produit comme affichage :

# - Testing foo()
ok 1 -  [@13] dummy function

@13 étant la ligne du test dans le fichier de tests.
Ca peut parait verbeux pour ce petit test mais dans mon utilisation ca donne:

$company = $tester->test('msCompany', function() use(&$tester)
        {
            $company = $tester->test('create', function() use(&$tester)
                            {
                                $obj = new msCompany();
                                $obj->setName('Foo');
                                $obj->setAddress('no address.');
                                $obj->setCity('no city.');
                                $obj->setCountry('no country.');
                                $obj->setContactEmail('no_email@contact.com');
                                $obj->setContactPhone('no phone.');

                                try
                                {
                                    $obj->save();
                                    $tester->fail('Duplicate name.');
                                } catch (Exception $e)
                                {
                                    $tester->pass('Duplicate name detected.');
                                }

                                $obj->setName('foo');

                                try
                                {
                                    $obj->save();
                                    $tester->ok(!is_null($obj->getId()), get_class($obj) . ' "' . $obj->getName() . '" cree.');
                                } catch (Exception $e)
                                {
                                    $tester->fail($e->getMessage());
                                }

                                return $obj;
                            });
            return $tester->test('delete', function() use(&$tester, &$user, &$company)
                    {
                        $company->delete();
                        $res = Doctrine::getTable('msCompany')->findById($company->getId());
                        $tester->is(count($res), 0, 'Suppression effectuee');
                        return $company;
                    });
        });

Et le proxy est :

class Tester
{

    protected $stack = array();
    protected $level = 0;
    protected $lime;

    public function __construct()
    {
        $this->lime = new lime_test();
    }

    public function test($comment, $callback)
    {
        $this->level++;
        $comment = str_repeat('-', $this->level) . ($this->level ? ' ' : '') . 'Testing ' . $comment;
        $this->lime->comment($comment);

        $elt = array(
            'function' => $comment,
            'comment' => $comment,
        );

        array_unshift($this->stack, $elt);

        $ret = $callback();

        $elt = array_shift($this->stack);
        $this->level--;
        return $ret;
    }

    public function prefix($stackTrace = null)
    {
        $stackTrace = is_null($stackTrace) ? debug_backtrace() : $stackTrace;
        $file = basename($stackTrace[1]['file']);
        $function = isset($stackTrace[2]) ? $stackTrace[2]['function'] : null;
        $line = $stackTrace[1]['line'];

        $pad = str_repeat(' ', $this->level);

        $elt = $this->stack[0];
        if (in_array($function, array('__call', '{closure}', '', null)))
        {
            $function = '';
        } else
        {
            $function .= '() ';
        }

        if ($this->level == 0)
        {
            return $pad . $function . '[@' . $line . '] ';
        }
        return $pad . $function . '[@' . $line . '] ';
    }

    public function __call($name, $arguments)
    {
        $comment = array_pop($arguments);
        $comment = $this->prefix(debug_backtrace()) . $comment;
        array_push($arguments, $comment);
        return call_user_func_array(array($this->lime, $name), $arguments);
    }

}