Soru Python çoklu dönüş değerleri ile alay ediyor


Pitonlar mock.patch kullanıyorum ve her arama için dönüş değerini değiştirmek istiyorum. İşte uyarı: Yamalı olan işlevde giriş yok, bu yüzden girişe bağlı olarak dönüş değerini değiştiremiyorum.

İşte referans için benim kodum.

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

Test kodum:

@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 sadece "giriş" in bir platform bağımsız (python 2 ve 3) sürümüdür. Sonuç olarak, kullanıcıların girişini denemeye çalışıyorum. Dönüş değeri için bir liste kullanmayı denedim, ancak bu işe yaramıyor.

Dönüş değeri geçersiz bir şey olduğunda, burada sadece sonsuz bir döngü alacağımı görebilirsiniz. Bu yüzden sonuçta dönüş değerini değiştirmenin bir yoluna ihtiyacım var, böylece testim gerçekten bitiyor.

(Bu soruyu cevaplamanın bir başka yolu, bir birim testinde kullanıcı girdisini nasıl taklit edebileceğimi açıklamak olabilir)


Bir çift değil bu soru esas olarak girdileri değiştirme yeteneğine sahip olmadığım için.

Yanıtın yorumlarından biri bu soru aynı hat boyunca, ancak hiçbir cevap / yorum sağlanmadı.


76
2017-07-22 20:25


Menşei


response is not 'y' or 'n' or 'yes' or 'no' içinde değil düşündüğün şeyi yapıyor. Görmek Bir değişkeni birden çok değere karşı nasıl test ederim? ve sen yapmalısın değil kullanım is string değerlerini karşılaştırmak için == karşılaştırmak değerlernesne kimlikleri değil. - Martijn Pieters♦
Ayrıca burada dikkatli ol. Kullanmaya çalışıyor gibisin is Dize değişmezlerini karşılaştırır. Bunu yapma. Çalışması (bazen), sadece CPython'daki bir uygulama detayıdır. Ayrıca, response is not 'y' or 'n' or 'yes' or 'no' Muhtemelen düşündüğün şeyi yapmıyor ... - mgilson


Cevaplar:


Bir iterable için side_effectve alay, her çağrıldığında sıradaki sonraki değeri döndürür:

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

Alıntı yapmak Mock() belgeleme:

Eğer yan etki yinelenen bir şeydir, sonra alayın her bir çağrısı bir sonraki değeri iterable'dan döndürür.

Bir yana, test response is not 'y' or 'n' or 'yes' or 'no' irade değil iş; ifadenin olup olmadığını soruyorsun (response is not 'y') doğru veya 'y' true (her zaman durum, boş olmayan bir dize her zaman doğrudur), vb. Her iki tarafındaki çeşitli ifadeler or operatörler bağımsız. Görmek Bir değişkeni birden çok değere karşı nasıl test ederim?

Malısın Ayrıca kullanmaz is bir dizgeye karşı test etmek. CPython yorumlayıcısı Mayıs ayı string nesnelerini yeniden kullan belirli koşullar altındaama bu, güvenmeniz gereken bir davranış değildir.

Gibi, kullanın:

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

yerine; bu kullanacak eşitlik testler==) belirlemek için response Aynı içeriğe sahip bir dize başvurur (değer).

Aynısı için de geçerlidir response == 'y' or 'yes'; kullanım response in ('y', 'yes') yerine.


149
2017-07-22 20:34



Bunu standartla yapmanın bir yolu var mı mock? MagicMock ile patch'i standart alayla yaptığım gibi kullanmanın bir yolu var mı? - Nick Humrich
@Humdinger: Bu stardard'ın bir özelliği Mock sınıf. - Martijn Pieters♦
@Humdinger: bununla birlikte not al mock.patch() kullanmak için varsayılan MagicMock, bir alt sınıfı Mock. - Martijn Pieters♦
Liste atama sadece python 3 ile çalışmaktadır. Python 2.7 ile test etme Bunun yerine bir yineleyici kullanmam gerekiyor (m.side_effect = iter(['foo', 'bar', 'baz'])). - user686249
@ user686249: Bunu gerçekten üretebilirim, çünkü bir yöntemden alıntı yapmak lambda (bir işlev), bir değil MagicMock. Bir işlev nesnesi olamaz var özellikleri, yani side_effect nitelik vardır yinelenen olmak. Yöntemi böyle belirtmemeliydin. Daha iyi kullanım mock.patch.object(requests.Session, 'post'); Bu, yönteme uygun şekilde otomatik olarak ekleyen bir yamalı nesneye neden olur. ve destekler side_effect uygun şekilde. - Martijn Pieters♦