2016-07-20 18 views
1

Ich habe mehrere pytest Testfälle, die fast identische Setup benötigen, also möchte ich sie wiederverwenden ein Gerät, um die Dinge trocken zu halten. Die Einrichtung umfasst das Erstellen eines neuen Tickets in einem externen Ticketverfolgungssystem, dann interagieren die Testfälle mit dem Ticket basierend auf den Daten, und schließlich bereinigt das Gerät das Ticket, indem es das Ticket schließt. Die Herausforderung besteht darin, dass jeder Testfall leicht unterschiedliche Daten benötigt, die im Ticket vorbereitet werden.AttributError bei der Verwendung von request.function in pytest Yield Fixture

Jeder Testfall hat unterschiedliche Aufrufe und unterschiedliche Assertions, so dass ich sie nicht alle zu einem einzigen parametrisierten Testfall mit einer einzigen Testvorrichtung kombinieren kann. Die Parametrierung des Fixtures selbst würde dazu führen, dass jeder Testfall mit jeder Permutation der Fixture-Daten abläuft, was zu vielen irrelevanten Testfehlern führt.

Was ich tun möchte, ist eine Variable im Testfall zu setzen, dann muss das Gerät diese Variable verwenden, um die Testdaten beim Erstellen des Tickets einzurichten. Ich habe versucht request.function zu verwenden, wie in den pytest fixture docs angegeben, aber ich bekomme immer wieder:

=================================== ERRORS =================================== 
    ____________________ ERROR at setup of TestMCVE.test_stuff ___________________ 

request = <SubRequest 'ticket' for <Function 'test_stuff'>> 

    @pytest.yield_fixture 
    def ticket(request): 
>  ticket_summary = getattr(request.function, "summary") 
E  AttributeError: 'function' object has no attribute 'summary' 

tests\test_mcve.py:11: AttributeError 

Mein Code ist:

import pytest 


def ticket_system_api(summary): 
    # stub for MCVE purposes 
    return summary 


@pytest.yield_fixture 
def ticket(request): 
    ticket_summary = getattr(request.function, "summary") 
    new_ticket = ticket_system_api(summary=ticket_summary) 
    yield new_ticket 


class TestMCVE: 
    def test_stuff(self, ticket): 
     summary = 'xyz' 
     # do real things here, except MCVE 
     assert 'xyz' == ticket 

Ich habe versucht, mit request.node statt request.function sowie binding the summary variable per this answer, Ändern summary = 'xyz' zu test_stuff.summary = 'xyz' aber diese scheitern immer noch mit dem gleichen AttributeError.

Wie kann ich die Funktion Level-Daten an das Gerät übergeben?

+1

Statements vor in „Ticket“ Befestigung ergeben würde – AlokThakur

+0

Hier vor der Erschaffung der „Zusammenfassung“ Objekt ausgeführt werden, 'ticket' wird zunächst als Testfunktion ausgeführt werden. Nach Abschluss der Fixture Execution würde 'summary' initialisiert werden. Kannst du 'ticket' nicht als normale Funktion anstelle von Fixture benutzen? –

Antwort

1

Sie können dies mit indirect parametrization erreichen. Die API (und die Dokumentation) könnte freundlicher sein, aber die Funktionalität, die Sie wollen, ist da.

Ihr Beispiel war sehr nah und kleinere Verbesserungen waren erforderlich. Werfen Sie einen Blick:

import pytest 


def ticket_system_api(summary): 
    # stub for MCVE purposes 
    return summary 


@pytest.fixture 
def ticket(request): 
    # NOTE: This will raise `AttributeError` if the fixture 
    # doesn't receive a parameter. 
    ticket_summary = request.param 
    new_ticket = ticket_system_api(summary=ticket_summary) 
    return new_ticket 


class TestMCVE: 
    @pytest.mark.parametrize('ticket', ('abc',), indirect=True) 
    def test_abc(self, ticket): 
     # do real things here, except MCVE 
     assert ticket == 'abc' 

    @pytest.mark.parametrize('ticket', ('xyz',), indirect=True) 
    def test_xyz(self, ticket): 
     # do real things here, except MCVE 
     assert ticket == 'xyz'