Pratiquez-vous TDD sur des projets personnels ? - Sephi-Chan - 18-02-2012
Hello,
En ce moment, je fais un peu de refactoring sur Conquest on Rails en pratiquant le développement piloté par les tests (Test Driven Development) et je me posais la question : est-ce que certains d'entre-vous le pratiquent sur leurs projets de jeux ?
Et à défaut de TDD, est-ce que vous écrivez des tests automatisés pour vos différentes systèmes ?
Si oui, ça pourrait être intéressant d'en discuter plus souvent sur le forum : c'est parfois difficile de déterminer quoi tester, et également difficile d'écrire un code robuste (couplage, responsabilité, etc.).
RE: Pratiquez-vous TDD sur des projets personnels ? - niahoo - 18-02-2012
Systématiquement.
Je teste uniquement mes API en codant d'abord les tests, dans une approche top down.
Mais quand je trouve des comportements, des façons de faire récurrentes, je crée des mini sous projets pour sortir de mon projet les briques de bases qui ne lui sont pas spécifiques
RE: Pratiquez-vous TDD sur des projets personnels ? - Sephi-Chan - 18-02-2012
As-tu des paires test/implémentation à présenter (sur un Gist, par exemple) ?
C'est toujours intéressant de voir la manière de spécifier.
RE: Pratiquez-vous TDD sur des projets personnels ? - niahoo - 18-02-2012
faut que je te trouve ça oui, là je pars de chez moi, uppez le topic
RE: Pratiquez-vous TDD sur des projets personnels ? - Ter Rowan - 18-02-2012
je ne fais pas des TDD mais je développe mes tests automatisés après la première version de mon développement :
dès que je crée une méthode d'un objet, je crée autant de cas tests qu'il y a de couples (entrées , sorties) possibles (bon en théorie, dans certains cas c'est pas vraiment possible)
les tests me servent surtout à la non régression
j'en ai pour le moment 820, y a probablement de la redondance et des "trous" fonctionnels mais j'en suis assez content
cas particulier, j'ai des cas tests concernant des méthodes qui utilisent le hasard
de fait j'ai surchargé une fonction de jet de dés :
normal
function Dice($a, $b)
{
return mt_rand ($a, $b);
}
surchargé
function Dice($a, $b)
{
return chance::GetRoll();
}
class chance
{
private static $rolls = array();
private static $cursor = 0;
private static $infinite;
// si infinite = true, alors on boucle sur le tableau des tirages a l infini
public static function SetRolls( $rolls, $infinite = false )
{
if (!is_array($rolls) )
$rolls = array($rolls);
self::$rolls = $rolls;
self::$cursor = 0;
self::$infinite = $infinite;
}
public static function GetRoll()
{
if (self::$cursor >= count(self::$rolls) )
if (self::$infinite)
self::$cursor =0;
else
throw new classError( 1000, array('message' =>'jet de dé non prévu'));
return self::$rolls[self::$cursor ++];
}
}
ainsi lors des tests, je ne laisse pas la place au hasard, je définis avant les appels des méthodes qui utilisent le hasard quel(s) sera(ont) le(s) résultat(s) du dé
RE: Pratiquez-vous TDD sur des projets personnels ? - Sephi-Chan - 18-02-2012
Pour l'aléatoire (et parfois le temps) on utilise des stubs :
Random.stub(:roll).and_return(42) # Pour tout stub.
Random.stub(:roll).with(1, 100).and_return(42) # Pour ne stub qu'avec des arguments précis.
RE: Pratiquez-vous TDD sur des projets personnels ? - niahoo - 27-02-2012
Voilà un extrait d'un test d'une classe simple. C'est pas très propre mais ça fonctionne bien. La classe est triviale aussi
<?php
require_once dirname(__FILE__) . '/../src/behaviours/gen_state.php';
//require_once dirname(__FILE__).'/../behaviours/gen_state.php';
class Test_gen_state extends UnitTestCase {
function __construct() {
parent::__construct();
debug_printer::get_printer()->title(__CLASS__, '-');
}
function test_wrap() {
$this->assertTrue(gen_state::wrap(array()) instanceof gen_state);
$this->assertTrue(count(gen_state::wrap(array())->export()) == 0);
$gs = gen_state::wrap(array('a' => 'b'));
$this->assertTrue(count($gs->export()) == 1);
$this->assertTrue($gs->get('a') == 'b');
}
function test_exception() {
$this->expectException();
$gs = gen_state::wrap(array('a' => 'b'));
$gs->get('b');
}
function test_default() {
$gs = gen_state::wrap(array());
$this->assertTrue($gs->get_default('b', 'default value') == 'default value');
}
function test_set() {
$gs = gen_state::wrap(array());
$self = $gs->set('a', 42);
$this->assertFalse($gs->export() == array('a' => 43));
$this->assertTrue($gs->export() == array('a' => 42));
$this->assertTrue($self === $gs);
}
function test_set_new() {
$gs = gen_state::wrap(array());
$this->assertTrue($gs->set_new('newkey', 'newvalue'));
$this->expectException();
$this->assertTrue($gs->set_new('newkey', 'newvalue'));
}
function test_replace() {
$gs = gen_state::wrap(array('a' => 'wrong value'));
$this->assertTrue($gs->replace('a', 'correct value'));
$gs2 = gen_state::wrap(array());
$this->expectException();
$gs2->replace('a', 'correct value');
}
function test_keys() {
$state = array(
'A', 'b', 'CCC', 'dé'
);
$expected_keys = array_keys($state);
$gs = gen_state::wrap($expected_keys);
$this->assertTrue($gs->keys() == $expected_keys);
}
function test_get_callback() {
$gs = gen_state::wrap(array('a' => 'exists'));
$callback = 'max';
$callback_args = array(
array(1, 2, 7, 6, 5) // max is 7
);
$this->assertTrue($gs->get_callback('a', $callback, $callback_args) == 'exists');
$this->assertTrue($gs->get_callback('b', $callback, $callback_args) == 7);
$gs2 = gen_state::wrap(array());
$this->expectException();
$gs2->replace('a', 'correct value');
}
function test_merge_new() {
$gs = gen_state::wrap(array(
'a' => 'exists_a',
'b' => 'exists_b',
'c' => 'exists_c'
));
$gs->merge_new(array(
'a' => 'replaced_a',
'd' => 'replaced_d'
));
$this->assertTrue($gs->get('a') == 'exists_a');
$this->assertTrue($gs->get('d') == 'replaced_d');
}
function test_null_value() {
$a = gen_state::wrap(array('a' => null));
$this->assertTrue(is_null($a->get('a')));
$b = gen_state::wrap(array());
$b->set('b', null);
$this->assertTrue(is_null($b->get('b')));
}
function test_has() {
$gs = gen_state::wrap(array('a' => null, 'b' => 123));
$this->assertTrue($gs->has('a'));
$this->assertTrue($gs->has('b'));
$this->assertFalse($gs->has('c'));
}
function test_append_to() {
$gs = gen_state::wrap(array(
'a' => array(1, 2, 3),
'b' => 'some string'
));
$gs->append_to('a', 4);
$this->assertEqual($gs->get('a'), array(1, 2, 3, 4));
$gs->append_to('b', '-other string');
$this->assertEqual($gs->get('b'), 'some string-other string');
$gs->append_to('a', 'val', 'key');
$this->assertEqual($gs->get('a'), array(1, 2, 3, 4, 'key' => 'val'));
}
}
|