web-dev-qa-db-fra.com

Test des méthodes de classe avec pytest

Dans la documentation de pytest, divers exemples de cas de test sont répertoriés. La plupart d'entre eux montrent le test des fonctions. Mais il me manque un exemple de test de classes et de méthodes de classe. Supposons que nous ayons la classe suivante dans le module cool.py Que nous aimons tester:

class SuperCool(object):

    def action(self, x):
        return x * x

À quoi doit ressembler la classe de test correspondante dans tests/test_cool.py?

class TestSuperCool():

    def test_action(self, x):
        pass

Comment test_action() peut-il être utilisé pour tester action()?

24
laserbrain

Tout ce que vous devez faire pour tester une méthode de classe est d'instancier cette classe et d'appeler la méthode sur cette instance:

def test_action(self):
    sc = SuperCool()
    assert sc.action(1) == 1
22
elethan

Eh bien, une façon consiste simplement à créer votre objet dans la méthode de test et à interagir avec lui à partir de là:

def test_action(self, x):
    o = SuperCool()
    assert o.action(2) == 4

Vous pouvez apparemment utiliser quelque chose comme le style classique setup et teardown unittest en utilisant les méthodes ici: http://doc.pytest.org/en/latest/xunit_setup.html

Je ne suis pas sûr à 100% de leur utilisation car la documentation de pytest est terrible.

Edit: oui donc apparemment si vous faites quelque chose comme

class TestSuperCool():
    def setup(self):
        self.sc = SuperCool()

    ... 

    # test using self.sc down here
9
Tyler Sebastian

J'utiliserais n'importe quel appareil uniquement pour créer un environnement de test (comme une connexion à une base de données) ou un paramétrage des données.

Si vos données sont relativement triviales, vous pouvez les définir dans le testcase:

def test_action_without_fixtures():
    sc = SuperCool()
    sc.element = 'snow'
    sc.melt()
    assert sc.element == 'water'

Exemple avec paramétrage:

@pytest.mark.parametrize("element, expected", [('snow', 'water'), ('tin', 'solder')])
def test_action_with_parametrization(element, expected):
    sc = SuperCool()
    sc.element = element
    sc.melt()
    assert sc.element == expected
4
Kirill

Si l'initialisation de la classe est coûteuse mais que vous devez exécuter de nombreux tests paramétrés sur une méthode de classe, vous pouvez modifier la définition de la méthode pour autoriser les entrées externes. Ensuite, vous pouvez initialiser une fois en dehors de la boucle de test et exécuter autant de tests que vous le souhaitez sur la méthode. Par exemple:

Au lieu de cela:

class SuperCool():
    def action(self):
        return self.attribute ** 2

Réécrire pour autoriser l'entrée externe:

class SuperCool():
    def action(self, x=None):
        if x is None:
            x = self.attribute
        return x ** 2

Maintenant, votre script de test peut ressembler à:

sc = SuperCool()
@pytest.mark.parametrize("x, y", [(1, 1), (2, 4)])
def test_action_with_parametrization(x, y):
    assert sc.action(x) == y

Mais je ne suis pas un programmeur expérimenté donc j'espère que ce n'est pas une sorte de XD anti-pattern

0
Trenton