web-dev-qa-db-fra.com

unitest vs pytest

Dans unittest, je peux configurer des variables dans une classe, puis les méthodes de cette classe peuvent choisir la variable à utiliser ...

class test_class(unittest.TestCase):
    def setUp(self):        
        self.varA = 1
        self.varB = 2
        self.varC = 3
        self.modified_varA = 2

    def test_1(self):
        do_something_with_self.varA, self.varB

    def test_2(self):
        do_something_with_self_modified_varA, self.varC

En résumé, il était facile de mettre en place une série de tests pouvant être classés dans une classe, puis d’utiliser différentes variables (varA et varB) pour différentes méthodes. Dans pytest, j'ai créé un appareil dans conftest.py au lieu d'une classe dans unittest, comme ceci ...

@pytest.fixture(scope="module")
def input1():
    varA = 1
    varB = 2
    return varA, varB

@pytest.fixture(scope="module")
def input2():
    varA = 2
    varC = 3
    return varA, varC

Je nourris cette entrée1 et entrée2 à mes fonctions dans un fichier différent (disons test_this.py) pour deux fonctions différentes. Voici les questions basées sur les informations ci-dessus ...

  1. Étant donné que je ne peux pas simplement déclarer des variables locales dans conftest.py, je ne peux pas simplement importer ce fichier. Existe-t-il un meilleur moyen de déclarer différentes variables pouvant être utilisées dans différentes fonctions de test_this.py? J'ai cinq configurations différentes dans mes tests réels pour ces variables, ce qui définit beaucoup de fixtures différentes dans conftest.py et je les utilise comme argument de fonction dans cinq fonctions différentes de test_this.py, cela semble douloureux. mes variables et choisir ce que je veux

  2. Devrais-je déclarer des variables globales dans test_this.py et les utiliser dans les fonctions comme je le souhaite? Semble un peu pas Pythonic. Ces variables ne sont utilisées que par les fonctions de ce fichier.

  3. Disons que j'ai aussi test_that.py et test_them.py. Si j'ai des variables partagées entre ces différents fichiers, comment pourrais-je les déclarer? créez simplement un fichier calle variables.py dans le répertoire où se trouvent tous ces fichiers de test et effectuez une importation à tout moment? De cette façon, je peux garder toutes les données dans un fichier séparé.

  4. Est-ce que j'ai l'impression que pytest décourage d'utiliser une classe pour organiser vos fonctions? Chaque exemple que j'ai lu en ligne, tout semble utiliser de nombreuses fonctions avec des appareils uniquement. Qu'est-ce qu'une configuration de définition de classe et de méthodes et d'organisation de tests dans pytest?

  5. J'ai un scénario de test où je dois utiliser le résultat d'une fonction dans une autre. Avec pytest, j’ai une assertion qui se trouve à la fin d’une fonction et non d’un retour, de sorte que je ne pourrai pas utiliser cette fonction en tant que fixture. Comment puis-je accomplir cela? Je sais que ce n'est pas une bonne pratique que mon test repose sur un autre, mais y a-t-il un moyen de contourner le problème?

Merci d'avance pour vos réponses.

24
LuckyStarr

1) Tout d’abord, vous pouvez déclarer ces fixtures non seulement dans conftest.py, mais dans tous les modules python de votre choix. Et vous pouvez importer ce module. Vous pouvez également utiliser les fixtures de la même manière que vous avez utilisé la méthode setUp:

@pytest.fixture(scope='class')
def input(request):
    request.cls.varA = 1
    request.cls.varB = 2
    request.cls.varC = 3
    request.cls.modified_varA = 2

@pytest.usefixtures('input')
class TestClass:
    def test_1(self):
        do_something_with_self.varA, self.varB

    def test_2(self):
        do_something_with_self_modified_varA, self.varC

ou vous pouvez définir des variables séparées dans des fixtures séparées:

def fixture_a():
    return varA

def fixture_b():
    return varB

def fixture_c():
    return varC

def fixture_mod_A():
    return modified_varA

ou faire un appareil qui retourne toutes les variables (pourquoi pas?) ou même faire un appareil paramétré indirect qui retourne les variables de votre choix (moyen assez déroutant):

@pytest.fixture()
def parametrized_iput(request):
   vars = {'varA': 1, 'varB': 2, 'varC': 3}
   var_names = request.param
   return (vars[var_name] for var_name in var_names)

@pytest.mark.parametrize('parametrized_iput', [('varA', 'varC')], indirect=True)
def test_1(parametrized_iput)
   varA, varC = parametrized_iput
   ...

Ou même, vous pouvez créer une fabrique d’appareils qui vous permettra de réaliser vos appareils à la volée. Cela semble curieux lorsque vous n’avez que 5 tests et 5 configurations de variables, mais lorsque vous obtenez des centaines des deux, cela peut être utile.

3) Bien sûr, vous pouvez. Mais je vous recommande de ne pas importer ce fichier directement, mais d'utiliser l'option de ligne de commande indiquant quel fichier importer. Dans ce cas, vous pouvez choisir un autre fichier avec des variables sans changer votre code.

4) J'utilise des classes dans mes tests car j'ai migré de nosetest. Je n'ai mentionné aucun problème d'utilisation des cours dans pytest.

5) Dans ce cas, je vous propose de faire ce qui suit: Fist faire la fonction avec les actions souhaitées:

def some_actions(a, b):
    # some actions here
    ...
    return c

puis utilisez-le à la fois dans test et fixture:

def test():
    assert some_actions(1,2) == 10

@pytest.fixture()
def some_fixture():
     return some_actions(1,2)
19
Ilya Karpeev

Je pense que unittest est plus facile à lire. Pour les nouveaux testeurs, unittest est vraiment facile. Cela fonctionne hors de la boîte. Vous dépendez de l'implémentation Python, mais ils ne changeront pas l'interface dans les années à venir. 

J'aime organiser mes tests de manière à avoir au maximum 1 test par fichier. Dans ce cas, je ne dépend pas des classes ... mais j'importe des classes de chaque test pour effectuer des tâches.

Certains sites Web se plaignent que les couleurs unittest ne sont pas possibles. Je pense que c’est une blague, car mes subordonnés créent des rapports de sortie JUNIT pour Jenkins et d’autres. Il existe d'excellents outils (même 1 fichier) pour convertir JUNIT en site Web, ce n'est pas la responsabilité d'un outil de test.

En outre, certaines personnes se plaignent du fait que vous avez besoin de beaucoup de code pour commencer un peu moins sévère. Je ne suis pas d'accord, il faut 4 lignes de code pour créer un peu plus fort! Mais Pytest a besoin de connaître toutes les annotations difficiles, qui ne sont pas normales pour un simple développeur Python.

Une des raisons importantes est également que les plus modestes resteront libres. Toutefois, si vous souhaitez utiliser pytest pour une raison quelconque (bitbucket, etc.), il existe des outils pour convertir vos tests et rendre le code moins lisible.

S'amuser!

0
Bart Mensfort