Unités de test des accesseurs (getters et setters)

étant Donné les méthodes suivantes:

public function setFoo($foo) {
    $this->_foo = $foo;
    return $this;
}

public function getFoo() {
    return $this->_foo;
}

en supposant, ils peuvent être changés pour être plus complexes à l'avenir:

  • comment écririez-vous les tests unitaires pour ces méthodes?
  • juste une méthode d'essai?
  • devrais-je sauter ces tests?
  • Qu'en est-il de la couverture des codes?
  • Que Diriez-vous de @covers annotation?
  • peut-être une méthode d'essai universelle à mettre en oeuvre dans le cas d'un essai abstrait?
<!-- 2 - Netbeans 7)

cela semble une perte de temps, mais cela ne me dérangerait pas si IDE générerait ces méthodes de test automatiquement.

extrait du Commentaire du blog de Sebastian Bergman:

(c'est comme tester getters et setters -- fail!). En tout cas, s'ils devaient échouer, les méthodes qui dépendent d'eux ne seraient-elles pas un échec?

alors, qu'en est-il de la couverture du code?

26
demandé sur markus 2011-02-14 03:25:47

3 réponses

Bonne Question,

j'essaie habituellement de ne pas tester getters & setters directement car je vois un plus grand avantage à tester seulement les méthodes qui en fait quelque chose.

surtout si vous n'utilisez pas le TDD, cela a l'avantage supplémentaire de me montrer les setters que je n'utilise pas dans Mes unitts, ce qui me montre que l'éther mes tests sont incomplets ou que le setter n'est pas utilisé/nécessaire. "Si je peux exécuter tout le" vrai " code sans utiliser ce setter pourquoi est-ce y."

lors de l'utilisation de setter fluent j'écris parfois un test en vérifiant la partie 'fluent' des setter mais habituellement qui est couvert dans d'autres tests.

pour répondre À ta liste:

  • juste une méthode d'essai?

C'est mon option préférée. Tout ou rien. Tester un seul test n'est pas facile à comprendre pour les autres et semble "aléatoire" ou doit être documenté d'une manière.

Modifier après commentaire:

Oui, pour le "trivial" get/set test que je n'avais utiliser une méthode par la propriété peut-être selon le cas, même une seule méthode pour toute la classe (pour les objets de valeur avec beaucoup de getters et de setters Je ne veux pas écrire/maintenir beaucoup de tests)

  • comment écririez-vous les tests unitaires pour ces méthodes?
  • devrais-je sauter ces tests?

Je ne les sauterais pas. Peut-être les getters selon comment beaucoup de vous avez (j'ai tendance à écrire seulement getters dont j'ai réellement besoin) mais la tâche d'avoir une classe complètement couverte ne devrait pas échouer à cause de getters.

  • Qu'en est-il de la couverture des codes?
  • pourquoi pas @covers annotation?

@covers mon point de vue est toujours "utilisez-le partout ou ne l'utilisez pas du tout". Mélanger les deux "styles" de test enlève certains des avantages de l'annotation et me semble "inachevé".

  • Peut-être une méthode d'essai universelle à mettre en œuvre dans le cas d'un essai abstrait?

Pour quelque chose comme des objets de valeur qui pourrait fonctionner correctement. Il peut se casser (ou devenir plus compliqué) une fois que vous passez dans les objets / tableau avec l'indication de type, mais je le préférerais presonally plutôt que d'écrire des tests manuels pour 500 getters et setters.

6
répondu edorian 2011-02-14 11:16:41

si vous faites du TDD, vous devriez faire un test pour getter et setter. trop. Ne pas ecrire une seule ligne de code sans le tester - même si votre code est très simple.

C'est une sorte de guerre religieuse d'utiliser un tandem de getter et setter pour votre test ou pour isoler chacun en accédant aux membres protégés de la classe en utilisant testez les capacités du cadre de votre unité. Comme un testeur de boîte noire je préfère cravate mon code de test unitaire pour l'api publique au lieu de le lier à l' détails concrets de la mise en œuvre. Je espérer un changement. Je veux encourager les développeurs de reformuler le code existant. Et les internes de la classe ne devraient pas effet "code externe" (tests unitaires dans ce cas). Je ne veux briser les tests unitaires quand les internes changent, je veux qu'ils cassent quand le public api change ou quand le comportement change. Ok, ok, en cas de défaillance d'une unité test ne pointez pas vers la source unique du problème. J'ai regarder dans le getter ET le setter pour comprendre ce qui a causé la problème. La plupart du temps de lecture est très simple (moins de 5 lignes du code: par exemple un retour et un null-check optionnel avec une exception). Si vérifier cela d'abord n'est pas une grosse affaire et ne prend pas beaucoup de temps. Et la vérification de le chemin heureux du setter est la plupart du temps seulement un peu plus complexe (même si vous avez quelques vérifications de validation).

essayez d'isoler vos cas de test-écrivez un test pour un SUT (sujet test) qui valide son exactitude sans reley sur d'autres méthodes (à l'exception de mon exemple ci-dessus). Le plus vous isoler le test, le plus votre les tests repèrent le problème.

selon votre stratégie de test, vous pouvez vouloir couvrir happy path seulement (programmeur pragmatique). Ou tristes chemins, trop. Je préfère pour couvrir tous les l'exécution des chemins. Quand je pense que j'ai découvert tous les chemins d'exécution-je vérifier couverture du code pour identifier le code mort (pas pour identifier s'il y a les chemins d'exécution non couverts - une couverture de code de 100% est un indicateur d'erreur de lecture).

il est préférable pour les testeurs de boîtes noires d'utiliser phpunit en mode strict et utiliser @couvre pour masquer couverture garantie.

quand vous écrivez test unitaire, votre test sur la classe A doit être exécuté indépendamment de la classe B. ainsi, vos tests unitaires pour la classe A ne doivent pas appeler / couvrir la méthode de la classe B.

si vous voulez identifier des getter/setter obsolètes et d'autres méthodes "mortes" (qui ne sont pas utilisées par le code de production) utilisez l'analyse de code statique pour cela. La métrique qui vous intéresse est appelée " couplage afférent au niveau de la méthode (MethodCa)". Malheureusement, cette métrique (ca) n'est pas disponible au niveau de la méthode dans Depend de PHP (voir:http://pdepend.org/documentation/software-metrics/index.html et http://pdepend.org/documentation/software-metrics/afferent-coupling.html). Si vous en avez vraiment besoin, n'hésitez pas à contribuer à PHP Depend. Une option d'exclusion des appels de la même catégorie serait utile pour obtenir un résultat sans appels "collatéraux". Si vous identifiez une "mort" méthode d'essayer de comprendre si il est destiné à être utilisé dans un proche avenir (la contrepartie pour une autre méthode qui a une annotation @depricated) sinon l'enlever. Dans le cas où il est utilisé dans la même classe uniquement, faire privat / protégé. N'appliquez pas cette règle au code de la bibliothèque.

Plan B: Si vous avez des tests d'acceptation (test d'intégration, test de régression, etc.) vous pouvez exécuter ce test sans exécuter les tests unitaires en même temps et sans mode strict de phpunits. Cela peut donner un résultat de couverture de code très similaire comme si vous avait analysé votre code de production. Mais dans la plupart des cas, vos tests non unitaires ne sont pas aussi solides que votre code de production. Cela dépend de votre discipline si ce plan B est "égal enought" au code de production pour obtenir un résultat significatif.

lecture: - Livre: Programmeur Pragmatique - Livre: Code Propre

7
répondu DanielaWaranie 2013-06-30 10:00:38

C'est une question courante mais étrangement ne peut pas trouver un dupe sur ainsi.

Vous pouvez écrire des tests unitaires pour les accesseurs mais la majorité des praticiens ne le font pas. par exemple, si les accesseurs n'ont pas de logique personnalisée, Je n'écrirais pas de tests unitaires pour vérifier si l'accès sur le terrain fonctionne. Au lieu de cela, je compterais sur les consommateurs de ces accesseurs pour s'assurer que les accesseurs fonctionnent. par exemple, si getfoo et setFoo ne fonctionnent pas, les appelants de cette méthode devrait rompre. Écrire des tests unitaires pour l'appelant méthodes, les accesseurs sont vérifiés.

cela signifie aussi que la couverture du code ne devrait pas être un problème. Si vous trouvez des accesseurs qui ne sont pas couverts après l'exécution de toutes les suites de test, peut-être qu'ils sont redondants / inutilisés. Les supprimer.

Essayez d'écrire un test qui illustre un scénario où un client utilisera que accesseur. par exemple, L'extrait ci-dessous montre comment le Tooltip (propriété) pour le bouton Pause bascule en fonction de son mode courant.

[Test]
public void UpdatesTogglePauseTooltipBasedOnState()
{
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons));

    _mainViewModel.TogglePauseCommand.Execute(null);
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_ResumeAllBeacons));

    _mainViewModel.TogglePauseCommand.Execute(null);
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons));
}
3
répondu Gishu 2011-02-15 05:29:08