بيثون ونيتست وهمية:هل من الممكن أن يسخر من قيمة الحجج الافتراضية طريقة في وقت الاختبار?
-
21-12-2019 - |
سؤال
لدي طريقة تقبل الوسائط الافتراضية:
def build_url(endpoint, host=settings.DEFAULT_HOST):
return '{}{}'.format(host, endpoint)
لدي حالة اختبار تمارس هذه الطريقة:
class BuildUrlTestCase(TestCase):
def test_build_url(self):
""" If host and endpoint are supplied result should be 'host/endpoint' """
result = build_url('/end', 'host')
expected = 'host/end'
self.assertEqual(result,expected)
@patch('myapp.settings')
def test_build_url_with_default(self, mock_settings):
""" If only endpoint is supplied should default to settings"""
mock_settings.DEFAULT_HOST = 'domain'
result = build_url('/end')
expected = 'domain/end'
self.assertEqual(result,expected)
إذا قمت بإسقاط نقطة تصحيح في build_url
وفحص هذه السمة settings.DEFAULT_HOST
إرجاع قيمة سخر.ومع ذلك ، يستمر الاختبار في الفشل ويشير التأكيد إلى host
يتم تعيين القيمة من بلدي الفعلي settings.py
.أعرف أن هذا لأن host
يتم تعيين وسيطة الكلمات الرئيسية في وقت الاستيراد ولا يتم اعتبار وهمية.
المصحح
(Pdb) settings
<MagicMock name='settings' id='85761744'>
(Pdb) settings.DEFAULT_HOST
'domain'
(Pdb) host
'host-from-settings.com'
هل هناك طريقة لتجاوز هذه القيمة في وقت الاختبار حتى أتمكن من ممارسة المسار الافتراضي مع سخر settings
كائن?
المحلول
وظائف تخزين القيم الافتراضية المعلمة في func_defaults
السمة عندما يتم تعريف الدالة ، حتى تتمكن من تصحيح ذلك.شيء من هذا القبيل
def test_build_url(self):
""" If only endpoint is supplied should default to settings"""
# Use `func_defaults` in Python2.x and `__defaults__` in Python3.x.
with patch.object(build_url, 'func_defaults', ('domain',)):
result = build_url('/end')
expected = 'domain/end'
self.assertEqual(result,expected)
أنا استخدم patch.object
كمدير سياق بدلا من مصمم ديكور لتجنب تمرير كائن التصحيح غير الضروري كوسيطة إلى test_build_url
.
نصائح أخرى
لقد طبقت الإجابة الأخرى على هذا السؤال ، ولكن بعد مدير السياق ، لم تكن الوظيفة المصححة هي نفسها كما كانت من قبل.
تبدو وظيفتي المصححة كما يلي:
def f(foo=True):
pass
في اختباري ، فعلت هذا:
with patch.object(f, 'func_defaults', (False,)):
عند الاتصال f
بعد (وليس في) مدير السياق ، ذهب الافتراضي تماما بدلا من العودة إلى القيمة السابقة.الاتصال f
دون الحجج أعطى الخطأ TypeError: f() takes exactly 1 argument (0 given)
بدلا من ذلك ، أنا فقط فعلت هذا قبل الاختبار:
f.func_defaults = (False,)
وهذا بعد اختباري:
f.func_defaults = (True,)
طريقة بديلة للقيام بذلك:استخدام فونكتولس.جزئي لتوفير الوسائط" الافتراضية " التي تريدها.هذا ليس تقنيا نفس الشيء كما تجاوز لهم;ترى المكالمة-إي أرغ صريحة ، ولكن ليس من الضروري أن توفر المكالمة.هذا قريب بما فيه الكفاية في معظم الوقت ، ويفعل الشيء الصحيح بعد خروج مدير السياق:
# mymodule.py
def myfunction(arg=17):
return arg
# test_mymodule.py
from functools import partial
from mock import patch
import mymodule
class TestMyModule(TestCase):
def test_myfunc(self):
patched = partial(mymodule.myfunction, arg=23)
with patch('mymodule.myfunction', patched):
self.assertEqual(23, mymodule.myfunction()) # Passes; default overridden
self.assertEqual(17, mymodule.myfunction()) # Also passes; original default restored
أستخدم هذا لتجاوز مواقع ملفات التكوين الافتراضية عند الاختبار.الائتمان حيث يرجع ، حصلت على فكرة من دانيلو بارجن هنا