Pertanyaan Python mencampur beberapa nilai pengembalian


Saya menggunakan python mock.patch dan ingin mengubah nilai kembalian untuk setiap panggilan. Inilah peringatannya: fungsi yang ditambal tidak memiliki input, jadi saya tidak dapat mengubah nilai kembalian berdasarkan masukan.

Ini kode saya untuk referensi.

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')

Kode pengujian saya:

@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 hanya versi platform independen (python 2 dan 3) dari "input". Jadi pada akhirnya saya mencoba untuk mengejek input pengguna. Saya telah mencoba menggunakan daftar untuk mengembalikan nilai, tetapi itu tidak berhasil.

Anda dapat melihat bahwa jika nilai kembalian adalah sesuatu yang tidak valid, saya hanya akan mendapatkan pengulangan tanpa batas di sini. Jadi saya perlu suatu cara untuk akhirnya mengubah nilai kembalian, sehingga pengujian saya benar-benar selesai.

(Cara lain yang mungkin untuk menjawab pertanyaan ini dapat menjelaskan bagaimana saya dapat meniru input pengguna dalam tes unit)


Bukan dup pertanyaan ini terutama karena saya tidak memiliki kemampuan untuk memvariasikan input.

Salah satu komentar dari Jawaban di pertanyaan ini berada di jalur yang sama, tetapi tidak ada jawaban / komentar yang diberikan.


75
2017-07-22 20:25


asal


Jawaban:


Anda dapat menetapkan iterable untuk side_effect, dan tiruan akan mengembalikan nilai berikutnya dalam urutan setiap kali dipanggil:

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

Mengutip Mock() dokumentasi:

Jika efek samping adalah iterable maka setiap panggilan ke tiruan akan mengembalikan nilai berikutnya dari iterable.

Sebagai tambahan, ujian response is not 'y' or 'n' or 'yes' or 'no' akan tidak kerja; Anda bertanya apakah ungkapan itu (response is not 'y') itu benar, atau 'y' adalah benar (selalu demikian, string tidak kosong selalu benar), dll. Berbagai ekspresi di kedua sisi or operator adalah independen. Lihat Bagaimana cara menguji satu variabel terhadap beberapa nilai?

Kamu harus juga tidak digunakan is untuk menguji string. Penerjemah CPython mungkin menggunakan kembali objek string dalam kondisi tertentu, tetapi ini bukan perilaku yang harus Anda andalkan.

Dengan demikian, gunakan:

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

sebagai gantinya; ini akan digunakan persamaan tes (==) untuk menentukan apakah response mereferensikan string dengan konten (nilai) yang sama.

Hal yang sama berlaku untuk response == 'y' or 'yes'; menggunakan response in ('y', 'yes') sebagai gantinya.


147
2017-07-22 20:34