2017-09-04 1 views
2

house.py:Comment tester une classe Héritée méthodes pytest

class House: 
    def is_habitable(self): 
     return True 

    def is_on_the_ground(self): 
     return True 

conftest.py:

import pytest 
from house import House 


@pytest.fixture(scope='class') 
def house(): 
    return House() 

test_house.py:

class TestHouse: 
    def test_habitability(self, house): 
     assert house.is_habitable() 

    def test_groundedness(self, house): 
     assert house.is_on_the_ground() 

Jusqu'à ce moment-là, tout est testé.

maintenant ajouter une sous-classe et passer outre une méthode house.py:

class House: 
    def is_habitable(self): 
     return True 

    def is_on_the_ground(self): 
     return True 


class TreeHouse(House): 
    def is_on_the_ground(self): 
     return False 

-je ajouter un nouvel appareil pour cette classe dans conftest.py:

import pytest 
from house import House 
from house import TreeHouse 


@pytest.fixture(scope='class') 
def house(): 
    return House() 


@pytest.fixture(scope='class') 
def tree_house(): 
    return TreeHouse() 

ajouter une nouvelle classe de test pour arbre maison test_house.py:

class TestHouse: 
    def test_habitability(self, house): 
     assert house.is_habitable() 

    def test_groundedness(self, house): 
     assert house.is_on_the_ground() 


class TestTreeHouse: 
    def test_groundedness(self, tree_house): 
     assert not tree_house.is_on_the_ground() 

A ce poi NT, le code fonctionne, mais il y a des cas qui ne sont pas testés. Par exemple, pour être complet, je devrais tester à nouveau les méthodes héritées de House dans TreeHouse.

La réécriture des mêmes tests à partir du TestHouse ne serait pas DRY.

Comment est-ce que je teste la méthode héritée de TreeHouse (dans ce cas is_habitable) sans dupliquer le code?

Je voudrais quelque chose comme re-tester le TreeHouse avec les mêmes tests que sa super classe, mais pas pour les méthodes/propriétés qui sont nouvelles ou remplacées. Après quelques recherches, je suis tombé sur des sources contradictoires. Et après avoir creusé dans la documentation pyest, je ne comprends pas ce qui s'applique à ce scénario.

Je suis intéressé par le pytest pour ce faire. Veuillez consulter les documents et expliquer comment cela s'applique ici.

+0

votre dernière ligne devrait être 'affirmer pas tree_house.is_on_the_ground()' –

+0

merci pour l'édition @PaulH – Bastian

+0

@PaulH Je suppose que je pourrais aussi me débarrasser de la '== True' dans les autres affirmations. – Bastian

Répondre

3

Une façon de le faire serait d'utiliser le nom de fixation house pour toutes les méthodes d'essai (même si elle teste un TreeHouse) et override its value in each test context:

class TestTreeHouse(TestHouse): 
    @pytest.fixture 
    def house(self, tree_house): 
     return tree_house 

    def test_groundedness(self, house): 
     assert not house.is_on_the_ground() 

Notez également TestTreeHouse Hérite de TestHouse. Puisque pytest merely enumerates methods of classes (c'est-à-dire qu'il n'y a pas d '"enregistrement" effectué avec, disons, un décorateur @pytest.test()), tous les tests définis dans TestHouse seront découverts dans les sous-classes de celui-ci, sans autre intervention.

+1

J'aime la réponse. Sur cette réponse: https://stackoverflow.com/a/44431292/1075374 cependant, il est dit que pytest interdit les hiérarchies de classes, bien que le lien ne l'explique pas. Avez-vous une opinion à ce sujet? – Bastian

+0

J'ai essayé cela et pour une raison quelconque 'self' se perd dans le chemin. 'TestTreeHouse.test_habitability' ->' TypeError: is_habitable() missing 1 argument positionnel requis: 'self''. La même chose arrive avec le deuxième test. Une idée? – Bastian

+0

Peut-être que vous renvoyez l'objet * class 'TreeHouse' depuis le fixture 'tree_house', au lieu d'une instance de la classe:' TreeHouse() ' – theY4Kman

0

Vous pouvez utiliser pytest parameterization pour passer plusieurs arguments au même test, dans ce cas, l'argument serait très probablement la classe en cours de test.

+0

Merci pour le lien. J'utilise des paramètres pour répéter des tests avec différents paramètres/arguments. Mais je ne vois pas comment cela fonctionnerait dans ce contexte. Souhaitez-vous élargir votre réponse plus loin qu'un simple lien vers les documents en clarifiant et en montrant un code de travail? – Bastian