Wie kann ich meine Pytest-Klasse mit Tests richtig einrichten und herunterfahren?

Lesezeit: 9 Minuten

Benutzeravatar von Avasin
Avasin

Ich verwende Selen für End-to-End-Tests und kann nicht verstehen, wie man es verwendet setup_class und teardown_class Methoden.

Ich muss den Browser in einrichten setup_class -Methode, führen Sie dann eine Reihe von Tests durch, die als Klassenmethoden definiert sind, und beenden Sie schließlich den Browser teardown_class Methode.

Aber logischerweise scheint es eine schlechte Lösung zu sein, denn tatsächlich funktionieren meine Tests nicht mit Klassen, sondern mit Objekten. Ich passe self param in jeder Testmethode, damit ich auf die Variablen von Objekten zugreifen kann:

class TestClass:
  
    def setup_class(cls):
        pass
        
    def test_buttons(self, data):
        # self.$attribute can be used, but not cls.$attribute?  
        pass
        
    def test_buttons2(self, data):
        # self.$attribute can be used, but not cls.$attribute?
        pass
        
    def teardown_class(cls):
        pass
    

Und es scheint sogar nicht richtig zu sein, eine Browserinstanz für eine Klasse zu erstellen. Sie sollte für jedes Objekt separat erstellt werden, oder?

Also muss ich verwenden __init__ und __del__ Methoden statt setup_class und teardown_class?

Benutzeravatar von Everett Toews
Everett Toews

Entsprechend Finalisierung des Fixtures / Ausführen des Teardown-Codesist die aktuelle bewährte Methode für die Einrichtung und den Abbau yield Anstatt von return:

import pytest

@pytest.fixture()
def resource():
    print("setup")
    yield "resource"
    print("teardown")

class TestResource:
    def test_that_depends_on_resource(self, resource):
        print("testing {}".format(resource))

Das Ausführen führt zu

$ py.test --capture=no pytest_yield.py
=== test session starts ===
platform darwin -- Python 2.7.10, pytest-3.0.2, py-1.4.31, pluggy-0.3.1
collected 1 items

pytest_yield.py setup
testing resource
.teardown


=== 1 passed in 0.01 seconds ===

Eine andere Möglichkeit, Teardown-Code zu schreiben, besteht darin, a zu akzeptieren request-Kontextobjekt in Ihre Fixture-Funktion ein und ruft sie auf request.addfinalizer Methode mit einer Funktion, die den Teardown einmal oder mehrmals durchführt:

import pytest

@pytest.fixture()
def resource(request):
    print("setup")

    def teardown():
        print("teardown")
    request.addfinalizer(teardown)
    
    return "resource"

class TestResource:
    def test_that_depends_on_resource(self, resource):
        print("testing {}".format(resource))

  • Kopieren Sie das also in jede Testdatei, in der Sie die Ressource benötigen?

    – Andy Hayden

    11. November 2017 um 2:00 Uhr

  • Dies ist jedoch kein Klassenaufbau, oder? Es würde vor jeder Testmethode in der Klasse ausgeführt werden.

    – malhar

    15. November 2017 um 17:00 Uhr

  • In diesem speziellen Fall wird es nur ausgeführt, wenn es als Parameter in einer Testmethode verwendet wird. zB die resource Parameter ein test_that_depends_on_resource(self, resource)

    – Everett Toews

    16. November 2017 um 17:34 Uhr

  • Beachten Sie, dass Sie den Fixture-Scope auf ‘class’ und autouse auf true setzen können, um sicherzustellen, dass der Code einmal für jede Klasse aufgerufen wird, ohne ihn als Parameter in einen Testaufruf einfügen zu müssen: “` pytest.fixture(scope=” class”, autouse=True) def resource(): print(“setup”) yield “resource” print(“teardown”) “`

    – Chris

    1. Oktober 2020 um 12:14 Uhr

  • Aktualisierung des Links: docs.pytest.org/en/stable/…

    – Sylvain

    19. April 2021 um 11:00 Uhr

Benutzeravatar von Bruno Oliveira
Bruno Oliveira

Wenn du schreibst “als Klassenmethoden definierte Tests”meinst du wirklich Klassenmethoden (Methoden, die ihre erhalten Klasse als erster Parameter) oder einfach nur reguläre Methoden (Methoden, die eine Beispiel als erster Parameter)?

Da dein Beispiel verwendet self Bei den Testmethoden gehe ich von letzterem aus, also musst du nur verwenden setup_method stattdessen:

class Test:

    def setup_method(self, test_method):
        # configure self.attribute

    def teardown_method(self, test_method):
        # tear down self.attribute

    def test_buttons(self):
        # use self.attribute for test

Die Testmethodeninstanz wird übergeben setup_method und teardown_method, kann aber ignoriert werden, wenn Ihr Setup-/Teardown-Code den Testkontext nicht kennen muss. Weitere Informationen finden Sie hier.

Ich empfehle Ihnen auch, sich mit py.test vertraut zu machen Vorrichtungenda sie ein leistungsfähigeres Konzept sind.

  • Fixtures sind schwächer als Klassenmethoden: Sie erlauben keine Zerstörung von Objekten, die nicht von ihnen erstellt wurden (was oft wirklich notwendig ist). Ansonsten danke für die Info.

    – wvxvw

    25. November 2018 um 12:14 Uhr

  • Dies traf mich beim Upgrade einer Codebasis von einer 3.0.x-Version von pytest auf eine 4.x-Variante. Etwas älterer Code verwendet setup_class mit verspotteten Methoden und dergleichen, die modernisiert werden mussten. setup_class(self, foo, bar) –> setup_method(self,function,foo,bar)

    – jxramos

    24. Februar 2020 um 18:03 Uhr

Benutzeravatar von Kiran Vemuri
Kiran Vemuri

Das könnte helfen http://docs.pytest.org/en/latest/xunit_setup.html

In meiner Testsuite gruppiere ich meine Testfälle in Klassen. Für den Auf- und Abbau benötige ich für alle Testfälle in dieser Klasse die ich verwende setup_class(cls) und teardown_class(cls) Klassenmethoden.

Und für den Auf- und Abbau benötige ich für jeden Testfall die ich verwende setup_method(method) und teardown_method(methods)

Beispiel:

lh = <got log handler from logger module>

class TestClass:
    @classmethod
    def setup_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    @classmethod
    def teardown_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    def setup_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def teardown_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def test_tc1(self):
        <tc_content>
        assert 

    def test_tc2(self):
        <tc_content>
        assert

Wenn ich jetzt meine Tests ausführe und die TestClass-Ausführung beginnt, werden die Details für den Beginn der Ausführung, das Ende der Ausführung und das Gleiche für die Methoden protokolliert.

Sie können weitere Einrichtungs- und Abbauschritte hinzufügen, die Sie möglicherweise an den jeweiligen Standorten haben.

Ich hoffe es hilft!

  • Hallo @Kiran, was ist der Unterschied zwischen der setup_class vs setup_method?

    – Mr. Unnormalized Posterior

    10. September 2019 um 13:02 Uhr

  • @imsrgadich Wenn Sie Ihre Testfälle in Klassen organisieren, wird _class für die Setup- und Teardown-Schritte der Klasse verwendet und _method sind die jeweiligen Schritte für jede Testfallmethode.

    – Kiran Vemuri

    12. September 2019 um 5:04 Uhr

  • Verdammt … jetzt verstehe ich es! hing einige Stunden daran fest. Also, um die Dinge ins rechte Licht zu rücken. Das <setup/teardown>_class für die ganze Klasse. Hier können Dinge wie das Setzen eines Links zur DB oder das Laden der Datendatei sein. Und dann kann jeder Testfall sein eigenes Setup in Form von haben <setup/teardown>_method. Die Dinge sind jetzt viel klarer. Danke vielmals!

    – Mr. Unnormalized Posterior

    12. September 2019 um 11:07 Uhr


Benutzeravatar von ecoe
Öko

Wie @Bruno vorgeschlagen hat, ist die Verwendung von Pytest-Fixtures eine weitere Lösung, auf die für beide Testklassen oder sogar nur einfache Testfunktionen zugegriffen werden kann. Hier ist ein Beispiel zum Testen von Python2.7-Funktionen:

import pytest

@pytest.fixture(scope="function")
def some_resource(request):
    stuff_i_setup = ["I setup"]

    def some_teardown():
        stuff_i_setup[0] += " ... but now I'm torn down..."
        print stuff_i_setup[0]
    request.addfinalizer(some_teardown)

    return stuff_i_setup[0]

def test_1_that_needs_resource(some_resource):
    print some_resource + "... and now I'm testing things..."

Laufen also test_1... produziert:

I setup... and now I'm testing things...
I setup ... but now I'm torn down...

Beachte das stuff_i_setup wird in der Fixture referenziert, wodurch dieses Objekt sein kann setup und torn down für den Test, mit dem es interagiert. Sie können sich vorstellen, dass dies für ein dauerhaftes Objekt wie eine hypothetische Datenbank oder eine Verbindung nützlich sein könnte, die vor jedem Testlauf gelöscht werden muss, um sie isoliert zu halten.

Ihr Code sollte genau so funktionieren, wie Sie es erwarten, wenn Sie hinzufügen @classmethod Dekorateure.

@classmethod 
def setup_class(cls):
    "Runs once per class"

@classmethod 
def teardown_class(cls):
    "Runs at end of class"

Sehen http://pythontesting.net/framework/pytest/pytest-xunit-style-fixtures/

  • Dies ist ziemlich genau das, was in der Dokumentation erscheint. Das Problem, das ich mit dem Dokument hatte, war, dass ich Schwierigkeiten hatte, den Kontext zu verstehen: self wird traditionell als self bezeichnet, nicht cls, also kam mir das seltsam vor, außerhalb des Kontexts der Klasse selbst. Kiran (oben) liefert diesen Kontext.

    – Cognitiaclaeves

    17. April 2019 um 16:41 Uhr

  • @Cognitiaclaeves “selbst wird traditionell als selbst bezeichnet, nicht als cls” Ja, self wird für Instanzmethoden verwendet, wobei das erste Argument die spezifische Objektinstanz ist, auf der die Methodenoperation stattfindet, while cls wird verwendet für @classmethods, die an die Klasse gebunden sind und nicht an eine Instanz der Klasse (dh ein Objekt).

    – code_dredd

    6. August 2019 um 21:16 Uhr

Benutzeravatar von Kiran Sk
Kiran Sk

import pytest
class Test:
    @pytest.fixture()
    def setUp(self):
        print("setup")
        yield "resource"
        print("teardown")

    def test_that_depends_on_resource(self, setUp):
        print("testing {}".format(setUp))

Um zu laufen:

pytest nam_of_the_module.py -v 

  • Dies ist ziemlich genau das, was in der Dokumentation erscheint. Das Problem, das ich mit dem Dokument hatte, war, dass ich Schwierigkeiten hatte, den Kontext zu verstehen: self wird traditionell als self bezeichnet, nicht cls, also kam mir das seltsam vor, außerhalb des Kontexts der Klasse selbst. Kiran (oben) liefert diesen Kontext.

    – Cognitiaclaeves

    17. April 2019 um 16:41 Uhr

  • @Cognitiaclaeves “selbst wird traditionell als selbst bezeichnet, nicht als cls” Ja, self wird für Instanzmethoden verwendet, wobei das erste Argument die spezifische Objektinstanz ist, auf der die Methodenoperation stattfindet, while cls wird verwendet für @classmethods, die an die Klasse gebunden sind und nicht an eine Instanz der Klasse (dh ein Objekt).

    – code_dredd

    6. August 2019 um 21:16 Uhr

Benutzeravatar von Apteryx
Apteryx

Ich bin mir nicht sicher, ob ich die Einzelheiten der Verwendung von Selenium in Ihren ursprünglichen Fragen verstanden habe, aber falls Sie einfach nur gefragt haben, wie Sie einen klassischeren SetUp/TearDown-Stil verwenden können, unterstützt Pytest die meisten Unittest-Funktionen, sodass Sie Folgendes tun könnten:

import unittest


class TestHello(unittest.TestCase):

    def setUp(self):
        print('running setUp')

    def test_one(self):
        print('running test_one')

    def test_two(self):
        print('running test_two')

    def tearDown(self):
        print('running tearDown')

Was produziert:

$ pytest -s -v
====================== test session starts =======================
platform linux -- Python 3.8.2, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /gnu/store/nckjv3ccwdi6096j478gvns43ssbls2p-python-wrapper-3.8.2/bin/python
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('/tmp/test/.hypothesis/examples')
rootdir: /tmp/test
plugins: hypothesis-5.4.1
collected 2 items                                                

test_hw.py::TestHello::test_one running setUp
running test_one
running tearDown
PASSED
test_hw.py::TestHello::test_two running setUp
running test_two
running tearDown
PASSED

  • Ich denke, es sollte sein setup Anstatt von setUpzumindest für pytest-7.1.2.

    – Schade96

    9. Juli um 21:37 Uhr

  • @schade96 bist du sicher? Ich sehe eine solche Änderung nicht im Changelog (docs.pytest.org/en/7.1.x/changelog.html) und auf mindestens einen Bugfix verweist tearDown in 7.1.

    – Apteryx

    12. Oktober um 13:59 Uhr

1430320cookie-checkWie kann ich meine Pytest-Klasse mit Tests richtig einrichten und herunterfahren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy