5

Supposons que vous écrivez une fonction pour vérifier si une page a été atteinte par l'URL appropriée. La page a un bout "canonique" - par exemple, alors qu'une page pourrait être atteinte à stackoverflow.com/questions/123, nous préférerions (pour des raisons de SEO) la rediriger vers stackoverflow.com/questions/123/how-do -i-move-the-tortue-in-logo - et la redirection réelle est contenue en toute sécurité dans sa propre méthode (par exemple, redirectPage ($ url)), mais comment tester correctement la fonction qui l'appelle?Tests unitaires avec effets secondaires?

Par exemple, prendre la fonction suivante:

function checkStub($questionId, $baseUrl, $stub) { 
    canonicalStub = model->getStub($questionId); 
    if ($stub != $canonicalStub) { 
    redirectPage($baseUrl . $canonicalStub); 
    } 
} 

Si vous deviez test unitaire la fonction checkStub(), ne serait pas la redirection obtenir de la manière?

Cela fait partie d'un problème plus vaste où certaines fonctions semblent devenir trop grandes et laisser le domaine des tests unitaires et dans le monde des tests d'intégration. Mon esprit pense immédiatement aux routeurs et aux contrôleurs comme ayant ce genre de problèmes, car les tester conduit nécessairement à la génération de pages plutôt que de se limiter à leur propre fonction.

Est-ce que j'échoue juste aux essais unitaires?

+0

Ralentissez ... et repenser à ce que vous essayez vraiment tester ici ... Si vous supprimez le Redirect, le checkStub la méthode ne fait pas grand-chose donc je ne suis pas sûr du vrai test ici. Habituellement, vous testez les effets secondaires qu'une telle fonction provoque. – Gishu

+0

@gishu: oui, c'est un exemple incroyablement imparfait issu d'un problème que j'ai résolu depuis ... le problème a été résolu, mais l'exemple (rediriger) est resté coincé dans ma tête.Focus sur la fin de la question - routeurs, contrôleurs - comme la vraie viande de la question. Comment puis-je tester des fonctions dont le but est en grande partie de «créer des choses» mais qui doivent encore être testées en raison de leur propre ordre interne et logique. Je vais m'évanouir maintenant et je vais probablement changer d'avis sur cette question dans la matinée. J'espère que vous pouvez voir mon intention maintenant (cela pourrait aider à savoir que je suis tout nouveau dans les tests unitaires). – AgentConundrum

+0

Vous venez juste de dire que vous mélangez la logique avec la création d'objets, ce qui rend les tests unitaires difficiles. Pouvez-vous partager ces deux préoccupations? Si c'est le cas, écrire vos tests unitaires sera plutôt trivial. – strager

Répondre

0

Il semble que vous ayez juste un autre cas de test. Vous devez vérifier que le talon est identifié correctement comme un talon avec des tests positifs et négatifs, et vous devez vérifier que la page vers laquelle vous êtes redirigé est correcte.

Ou est-ce que je comprends mal la question?

+2

pouvez-vous poser votre question et corriger vos typos kthx? – strager

1

Vous dites ...

Cela fait partie d'un problème plus vaste où certaines fonctions semblent être trop grand et quitter le domaine des tests unitaires et dans le monde des tests d'intégration

Je pense que c'est pourquoi les tests unitaires sont (1) durs et (2) mènent à un code qui ne s'effrite pas sous son propre poids. Vous devez être méticuleux pour briser toutes vos dépendances ou vous vous retrouvez avec des tests unitaires == tests d'intégration. Dans votre exemple, vous devez injecter un redirecteur en tant que dépendance. Vous utilisez un simulacre, double ou espion. Ensuite, vous faites les tests comme @atk expose. Parfois ça ne vaut pas le coup. Plus souvent cela vous oblige à écrire un meilleur code. Et c'est difficile à faire sans un conteneur IOC.

1

C'est une vieille question, mais je pense que cette réponse est pertinente. @Rob indique que vous devez injecter un redirecteur en tant que dépendance - et bien sûr, cela fonctionne. Cependant, votre problème est que vous n'avez pas une bonne séparation des préoccupations.

Vous devez rendre vos fonctions aussi atomiques que possible, puis composer des fonctionnalités plus importantes en utilisant les fonctions granulaires que vous avez créées. Vous avez écrit ceci:

function checkStub($questionId, $baseUrl, $stub) { 
    canonicalStub = model->getStub($questionId); 
    if ($stub != $canonicalStub) { 
    redirectPage($baseUrl . $canonicalStub); 
    } 
} 

J'écrirait ceci:

function checkStubEquality($stub1, $stub2) { 
    return $stub1 == $stub2; 
    } 

    canonicalStub = model->getStub($questionId); 
    if (!checkStubEquality(canonicalStub, $stub)) redirectPage($baseUrl . $canonicalStub);