Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 13-09-2016 10:45:57

Ragnatos
Membre
Date d'inscription: 26-04-2016
Messages: 10

tests unitaires avec une BDD "virtuelle"

Bonjour à toutes et tous

Je viens vous voir pour un problème de tests unitaires (avec PHPUnit) sous Zend 2 qui est assez compliqué pour moi (je suis débutant en tests unitaires).

Je vais assez de vous expliquer le projet car il est assez complexe et je précise que je suis en alternance et que je prend la suite du précédent alternant, donc certains choix (notamment la disposition des répertoires, etc ...) me sont imposés.
J'ai actuellement 3 modules: Application (qui gère ma page d'accueil et mon controller pour l'authentification), Library (qui contient mes models, mes services et mes repositories entre autres) et un autre module qui pour l'instant n'a pas besoin d'être présenté car quasiment rien n'est fait dessus.

J'ai mis en place des tests unitaires basiques pour ma page d'accueil sans aucun problème. J'ai attaqué les tests unitaires pour mon controller d'authentification et je me heurte à une réflexion concernant la base de données.

Pour me logger, je vais voir en base de données si le login et le password sont conforment à ceux passé en paramètre (normalement rien de choquant). Sauf que la base de données sur laquelle je tape c'est la base de données courant (qui deviendra la base de données de prod) et donc elle sera amené à voir ses données évoluées (on peut imaginer que le login que j'utilise pour mes tests soit supprimé ou que le mot de passe soit changé par exemple).

Je voudrais donc savoir s'il y a un moins de créer une sorte de base de données "virtuelle" où j'aurais défini les données présentes et qui ne changera jamais. Je demande "virtuelle" pour différencier l'idée d'avoir une base de données en dur dédié aux tests unitaires (mais ce sera cette solution que je proposerai si je ne trouve pas mieux).  On peut par exemple imaginer un fichier xml où je défini mes tables et les données présentes (j'ai vu ça une fois mais je ne sais pas si c'est possible de faire pareil)


Je suis ouvert à toutes les suggestions et possibilités et j'espère que vous pourrez m'aider

Cordialement
Ragnatos
Cordialement

PS: je sais pas si cela peut aider mais pour les requêtes en BDD j'utilise doctrine

Hors ligne

 

#2 13-09-2016 10:52:46

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: tests unitaires avec une BDD "virtuelle"

Bonjour,

Pour répondre a ta question, oui c'est possible de créer une base de donnée virtuelle, mais c'est un travail fastidieux, et selon ma connaissance des tests unitaires complètement inutile, overkill etc...
SI tu fais des tests fonctionnels ok, tu teste ton code et ta data donc oui tu dois faire une base de donnée virtuelle.
Si tu fais des tests unitaires alors non ne testes pas ta donnée, test juste la logique de ton code.

En gros :

- Mock tes méthodes Doctrine et fait leur retourner tes jeux de résultats en "dur" dans ton test. Ne contrôle pas la donnée mais contrôle juste les valeur de retour et d'entrée de tes méthodes. Un des buts des Tests unitaires est l'anti-régréssion qui est achevé par ce genre de tests, ta donnée n'a rien avoir avoir les TU puisqu'elle change par nature, alors qu'un TU ne doit jamais bouger pour vraiment exister en tant que test utile.

J'espère avoir été compréhensible. hésites pas a demander plus d'info si necessaire


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#3 13-09-2016 10:58:39

Ragnatos
Membre
Date d'inscription: 26-04-2016
Messages: 10

Re: tests unitaires avec une BDD "virtuelle"

Bonjour et merci pour ta réponse,

D'après la définition que tu me donne, je suis plutôt en train de mettre en place des tests fonctionnels. Donc si je ne veux pas trop avoir de problème je crois qu'utiliser une BDD dédiée aux tests semble être la solution la plus simple et facile à mettre en oeuvre (à priori)

Après concernant la définition que tu donnes des tests unitaires j'ai un peu plus de mal: par exemple j'ai une fonction qui doit me renvoyer du JSON, si j'ai bien compris lorsque je rédige mon test unitaire je dois juste vérifier que j'obtiens bien du JSON sans prendre en compte les valeurs retournés c'est ça ?

Dernière modification par Ragnatos (13-09-2016 11:05:00)

Hors ligne

 

#4 13-09-2016 12:11:51

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: tests unitaires avec une BDD "virtuelle"

Si tu as une méthode qui doit te renvoyer du json tu teste l'entrée de ta méthode admettons que tu ai un array en paramètre (PHP donc) tu fais les assertions qu'il faut ou pas dans cette méthode et dans ton teste tu fais bien une check sur ton retour du genre

Code:

[lang=php]

$data = array('key' => $subData);

$result = $this->service->getJsonOfMydata($data);
$decoded = json_decode($result); // si sa passe tu as du json... tu peux tester aussi que c'est bien du Json je te laisse regarder ce point sur le web
$this->assertInternalType('array', $decoded);
$this->assertArrayHasKey('youSubKey', $decoded['key']);
// and so on...

Ton test unitaire ici n'as pas testé de la donnée, mais juste le comportement de ton code. Libre a toi de faire un second test avec des données fausse en entrée et de faire des


Code:

[lang=php]
$this->setExpectedException()

Pour contrôler que ton code marche bien si ton array PHP ne peux pas être sérialisé en Json par exemple.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#5 15-09-2016 08:34:26

Ragnatos
Membre
Date d'inscription: 26-04-2016
Messages: 10

Re: tests unitaires avec une BDD "virtuelle"

Je me permets de dévié un peu du sujet mais qui reste dans les tests unitaires.
J'ai réussi a faire mes premiers mocks simples (qui fonctionne) et la j'essaie de faire le mock d'un repository

En parcourant internet j'ai lu que, pour pouvoir mocker mon repository, il faut aussi mocker l'entity manager.
Ce que j'ai fais avec ce code:

Code:

$emMock = $this->getMockBuilder('Doctrine\ORM\EntityManager')
        ->disableOriginalConstructor()
        ->getMock();
        $emMock->expects($this->any())
        ->method('getRepository')
        ->with('Library\Repositories\Application')
        ->will($this->returnValue($repositoryMock));

Problème: dans la fonction de mon controller que je teste, j'appelle d'autres repositories (deux autres) et du coup avec ce code, je bloque sur les appels des deux autres repositories. Du coup je voulais savoir, parce que j'ai rien trouvé, s'il existe un moyen de mettre une condition du style "si j'appelle se repository alors j'utilise les mocks sinon on fonctionne normalement"

Hors ligne

 

#6 15-09-2016 09:19:28

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: tests unitaires avec une BDD "virtuelle"

Bonjour,

Tu peux me montrer l'action de ton controller qui fait ces appels ?

Pour les mock j'utilise personnellement Mockery. Bien mieux intuitif et mieux foutu selon moi pour lequel tu n'aurais pas ce problème.


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

#7 15-09-2016 09:26:32

Ragnatos
Membre
Date d'inscription: 26-04-2016
Messages: 10

Re: tests unitaires avec une BDD "virtuelle"

Voici par exemple l'action qui gère la page index du controller que je veux tester

Code:

$managedAppCode = $this->getEvent()
            ->getRouteMatch()
            ->getParam('appliGeree');
        // ===== Autorisation =====
        $ac = $this->getServiceLocator()->get('AccessController');
        $em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
        
        // Ressource permettant de lister
        $repoResource = $em->getRepository('Library\Model\Resource');
        $repoResource->setServiceLocator($this->getServiceLocator());
        $resourceTraceShow = $repoResource->getResourceForAutorisation($managedAppCode, self::TRACE_SHOW);
        
        if (! $ac->isAllowedAndRedirect($resourceTraceShow))
            echo 'accès refusé';
            
            // Ressource permettant de supprimer
        $resourceTraceDelete = $repoResource->getResourceForAutorisation($managedAppCode, self::TRACE_DELETE);
        
        $repoAppli = $em->getRepository('Library\Model\Application');
        $repoAppli->setServiceLocator($this->getServiceLocator());
        $distinctApplicationArray = $repoAppli->getListApplicationNameLabel($managedAppCode === 'gestion' ? null : $managedAppCode);
        
        $repoTrace = $em->getRepository('Library\Model\Trace');
        $repoTrace->setServiceLocator($this->getServiceLocator());
        // --- Liste des utilisateur ---
        $userList = $repoTrace->getUserList($managedAppCode);
        // --- Liste des types ---
        $typeList = $repoTrace->getTypeList($managedAppCode);
        // --- Liste des objets ---
        $objectList = $repoTrace->getObjectList($managedAppCode);
        
        $vm = new ViewModel();
        $vm->setVariables(
            ['application' => $managedAppCode,
            'distinctApplicationArray' => $distinctApplicationArray,
            'userList' => $userList,
            'typeList' => $typeList,
            'objectList' => $objectList,
            'resourceDelete' => $ac->isAllowedAndRedirect($resourceTraceDelete)]
        );
        
        return $vm;

Hors ligne

 

#8 15-09-2016 10:24:44

tdutrion
Administrateur
Lieu: Dijon, Paris, Edinburgh
Date d'inscription: 23-12-2009
Messages: 614
Site web

Re: tests unitaires avec une BDD "virtuelle"

Bonjour,

A priori c'est l'action de ton contrôleur si dessus, du coup pourquoi ne pas passer le repository comme paramètre du constructeur de ton contrôleur ? En zf3 le contrôleur n'est plus ServiceLocatorAware, pour éviter justement ce genre de code, et tu es invité à faire une factory pour ton constructeur (c'est elle qui utilisera le serviceLocator, ou plutôt un Container de ContainerInterop, passé en param du callable).

Hors ligne

 

#9 15-09-2016 10:34:34

JGreco
Administrateur
Date d'inscription: 22-12-2012
Messages: 432

Re: tests unitaires avec une BDD "virtuelle"

Voilà comme dit Théocrite, quand tu m'a dit que tu utilisait l'EM dans ton controleur je suspectais un appel au serviceLocator dans le contrôleur, attention ce n'est pas du bon code pour le futur, si ton projet n'est pas un projet jetable je te recommande de faire une refacto en ce sens.

http://www.z-f.fr/forum/viewtopic.php?id=9032
Ce sujet (que j'affectionne particulièrement en raison de la qualité des réponses d'Orkin) me semble être intérressant dans ce contexte pour expliquer quel est une bonne architecture du code dans un projet ZF2 (c'est pas la seule mais c'est deja une bonne piste pour un code maintenable)


ZF2 et doctrine addict
profil stack overflow : http://stackoverflow.com/users/3333246/ … ab=profile

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages