Frage Python simuliert mehrere Rückgabewerte


Ich benutze Pythons mock.patch und möchte den Rückgabewert für jeden Anruf ändern. Hier ist der Vorbehalt: Die gepatchte Funktion hat keine Eingänge, daher kann ich den Rückgabewert nicht basierend auf der Eingabe ändern.

Hier ist mein Code als Referenz.

def get_boolean_response():
    response = io.prompt('y/n').lower()
    while response not in ('y', 'n', 'yes', 'no'):
        io.echo('Not a valid input. Try again'])
        response = io.prompt('y/n').lower()

    return response in ('y', 'yes')

Mein Testcode:

@mock.patch('io')
def test_get_boolean_response(self, mock_io):
    #setup
    mock_io.prompt.return_value = ['x','y']
    result = operations.get_boolean_response()

    #test
    self.assertTrue(result)
    self.assertEqual(mock_io.prompt.call_count, 2)

io.prompt ist nur eine plattformunabhängige (python 2 und 3) Version von "input". Letztendlich versuche ich die Benutzereingaben zu verspotten. Ich habe versucht, eine Liste für den Rückgabewert zu verwenden, aber das funktioniert nicht.

Sie können sehen, dass wenn der Rückgabewert etwas ungültiges ist, ich hier nur eine Endlosschleife bekomme. Also brauche ich einen Weg, um den Rückgabewert zu ändern, damit mein Test tatsächlich beendet wird.

(Eine andere Möglichkeit, diese Frage zu beantworten, könnte darin bestehen, zu erklären, wie ich Benutzereingaben in einem Unit-Test nachahmen könnte)


Nicht eine Dupe von diese Frage hauptsächlich, weil ich nicht in der Lage bin, die Eingaben zu variieren.

Einer der Kommentare der Antwort auf diese Frage ist in die gleiche Richtung, aber keine Antwort / Kommentar wurde zur Verfügung gestellt.


75
2017-07-22 20:25


Ursprung


Antworten:


Sie können eine zuweisen iterierbar zu side_effect, und der Schein gibt bei jedem Aufruf den nächsten Wert in der Sequenz zurück:

>>> from unittest.mock import Mock
>>> m = Mock()
>>> m.side_effect = ['foo', 'bar', 'baz']
>>> m()
'foo'
>>> m()
'bar'
>>> m()
'baz'

Zitieren der Mock() Dokumentation:

Ob Nebenwirkung Ist ein Iterable, dann wird jeder Aufruf des Mocks den nächsten Wert aus dem Iterablen zurückgeben.

Nebenbei, der Test response is not 'y' or 'n' or 'yes' or 'no' werden nicht Arbeit; Sie fragen, ob der Ausdruck (response is not 'y') ist wahr, oder 'y' ist wahr (immer der Fall, eine nicht leere Zeichenfolge ist immer wahr) usw. Die verschiedenen Ausdrücke auf beiden Seiten von or Betreiber sind unabhängig. Sehen Wie teste ich eine Variable gegen mehrere Werte?

Du solltest ebenfalls nicht nutzen is gegen eine Zeichenfolge testen. Der CPython-Interpreter kann Zeichenkettenobjekte wiederverwenden unter bestimmten Umständen, aber das ist kein Verhalten, auf das Sie zählen sollten.

Als solche verwenden Sie:

response not in ('y', 'n', 'yes', 'no')

stattdessen; das wird verwenden Gleichberechtigung Tests (==) um zu bestimmen, ob response Verweist auf eine Zeichenfolge mit demselben Inhalt (Wert).

Gleiches gilt für response == 'y' or 'yes'; benutzen response in ('y', 'yes') stattdessen.


147
2017-07-22 20:34