unittest versus pytest

In unittest kan ik variabelen in een klasse instellen en dan kunnen de methoden van deze klasse kiezen welke variabele het wil gebruiken…

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

Dus in unittest was het gemakkelijk om een aantal tests samen te stellen die onder één klasse konden vallen en vervolgens veel verschillende variabelen (varA en varB) voor verschillende methoden te gebruiken. In pytest heb ik een armatuur gemaakt in conftest.py in plaats van een klasse in unittest, zoals deze…

@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

Ik geef deze input1 en input2 aan mijn functies in een ander bestand (laten we zeggen test_this.py) voor twee verschillende functies. Dit zijn de vragen op basis van bovenstaande informatie…

  1. Omdat ik niet zomaar lokale variabelen in conftest.py kan declareren, aangezien ik dit bestand niet zomaar kan importeren. Is er een betere manier om hier verschillende variabelen te declareren die in verschillende functies in test_this.py kunnen worden gebruikt? Ik heb vijf verschillende configuraties in mijn eigenlijke testen voor deze variabelen, die veel verschillende armaturen in conftest.py definiëren en ze gebruiken als functieargument in vijf verschillende functies in test_this.py klinkt pijnlijk, ik ga liever terug naar unittest-klassenstructuur, definieer mijn variabelen en kies en kies wat ik wil

  2. Moet ik gewoon globale variabelen declareren in test_this.py en ze gebruiken in de functies zoals ik wil? Lijkt een beetje niet pythonisch. Deze variabelen worden alleen gebruikt door de functies in dit bestand.

  3. Stel dat ik test_that.py en test_them.py ook heb. Als ik een aantal gedeelde variabelen tussen deze verschillende bestanden heb, hoe zou ik ze dan declareren? maak gewoon een bestand aan met de naam variabelen.py in de map waar al deze testbestanden staan en voer een import uit wanneer ik dat nodig heb? Zo kan ik alle gegevens apart bewaren.

  4. Heb ik de indruk dat pytest het gebruik van een klasse ontmoedigt om je functies te organiseren? Elk voorbeeld dat ik online lees, het lijkt allemaal een heleboel functies te gebruiken met alleen armaturen. Wat is een configuratie voor het definiëren van klasse en methoden en het organiseren van tests in pytest ?

  5. Ik heb een testscenario waarin ik het resultaat van de ene functie in de andere moet gebruiken. Met pytest heb ik een bewering dat aan het einde van een functie geen return is, dus ik zal deze functie niet als een armatuur kunnen gebruiken. Hoe bereik ik dit? Ik weet dat dit geen goede gewoonte is dat mijn ene test afhankelijk is van een andere, maar is er een oplossing voor?

Bij voorbaat dank voor uw antwoorden.


Antwoord 1, autoriteit 100%

1) Allereerst kun je die fixtures niet alleen declareren in conftest.py, maar in elke gewenste Python-module. En u kunt die module importeren.
U kunt fixtures ook op dezelfde manier gebruiken als de setUp-methode:

@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

of u kunt afzonderlijke variabelen in afzonderlijke fixtures definiëren:

def fixture_a():
    return varA
def fixture_b():
    return varB
def fixture_c():
    return varC
def fixture_mod_A():
    return modified_varA

of maak één armatuur die alle variabelen retourneert (waarom niet?)
of maak zelfs indirecte geparametriseerde fixture die variabelen naar uw keuze retourneert (vrij verwarrende manier):

@pytest.fixture()
def parametrized_input(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_input', [('varA', 'varC')], indirect=True)
def test_1(parametrized_input)
   varA, varC = parametrized_input
   ...

Of je kunt zelfs een armaturenfabriek maken die armaturen voor je maakt. Klinkt vreemd als je maar 5 tests en 5 configuraties van variabelen hebt, maar als je honderden van beide krijgt, kan het handig zijn.

3) Natuurlijk kan dat. Maar ik raad u aan dit bestand niet rechtstreeks te importeren, maar de opdrachtregeloptie te gebruiken die aangeeft welk bestand u wilt importeren. In dit geval kunt u een ander bestand met variabelen kiezen zonder uw code te wijzigen.

4) Ik gebruik klassen in mijn tests omdat ik ben gemigreerd van nosetest. Ik heb geen enkel probleem genoemd met het gebruik van klassen in pytest.

5) In dat geval stel ik je voor om het volgende te doen:
maak eerst de functie met de gewenste acties:

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

gebruik het dan zowel in de test als in de fixture:

def test():
    assert some_actions(1,2) == 10
@pytest.fixture()
def some_fixture():
     return some_actions(1,2)

Antwoord 2, Autoriteit 48%

Ik denk dat Unittest gemakkelijker te lezen is. Voor nieuwe testers is Unittest heel eenvoudig. Het werkt uit de doos. Je bent afhankelijk van de implementatie van Python, maar ze zullen de interface komende jaren niet veranderen.

Ik vind het leuk om mijn tests op een zodanige manier te organiseren dat ik maximaal 1 test per bestand heb. In dat geval is ik niet afhankelijk van klassen … maar ik importeer de lessen van elke test om dingen te doen.

Sommige websites klagen over kleuren in Unittest is niet mogelijk. Ik denk dat dat een grap is, omdat mijn Unittests Junit-uitvoerrapporten voor Jenkins en anderen creëren. Er zijn geweldige tools (zelfs 1 bestand) om Junit naar een website te converteren, dat is niet de verantwoordelijkheid van een testtool.

Ook klagen sommige mensen dat je veel code nodig hebt om een ​​ongetrouwde te beginnen. Ik ben het niet eens, het duurt 4 regels code om een ​​Unittest te maken! Maar Pytest moet alle moeilijke annotaties kennen, die niet normaal zijn voor een eenvoudige Python-ontwikkelaar.

Een belangrijke redenen is ook dat Unittest vrij blijft. Als u echter om een ​​of andere reden Pytest wilt gebruiken (bitbucket enz.), Zijn er hulpmiddelen om uw tests om te zetten en de code minder leesbaar te maken.

Veel plezier!

Other episodes