Pytest-django: يبدو أن Pytest يتجاهل الإعدادات التي توسع ملفات الإعدادات الأخرى

تم إنشاؤها على ٢٥ سبتمبر ٢٠١٥  ·  9تعليقات  ·  مصدر: pytest-dev/pytest-django

لدي هيكل المشروع التالي:

myapp/settings/__init__.py
myapp/settings/base.py
myapp/settings/test.py

داخل base.py لدي إعداد يسمى REST_FRAMEWORK من مشروع إطار عمل Django REST. test.py بعمل from myapp.settings.base import * في الأعلى ثم يضيف بعض إعدادات قاعدة البيانات الخاصة به. الآن ، لسبب ما ، يتجاهل pytest تمامًا إعداد REST_FRAMEWORK على الرغم من تحميل الملف test.py ويمكنني طباعة محتويات REST_FRAMEWORK بداخله. يعمل Django كما هو متوقع.

إذا قمت بنسخ إعداد REST_FRAMEWORK يدويًا إلى ملف test.py بدلاً من الاعتماد على التمديد ، فستنجح اختباراتي. أيه أفكار؟ تبدو هذه حالة بسيطة لدرجة أنني يجب أن أفتقد شيئًا ما ولكن لا يمكنني تعقبه.

pytest 2.7.2 و pytest-django 2.8.0

التعليق الأكثر فائدة

اكتشفت أن قيمة DJANGO_SETTINGS_MODULE في pytest.ini لا تتجاوز متغير البيئة DJANGO_SETTINGS_MODULE . لدي أيضًا ملف إعدادات للاختبار مشتق من ملف إعدادات آخر - يستخدم pytest ملف الإعدادات الأساسي نظرًا لأن هذه هي القيمة في متغير البيئة.

ال 9 كومينتر

هل أنت متأكد من تعيين DJANGO_SETTINGS_MODULE بشكل صحيح؟

ها هو pytest.ini الخاص بي:

[pytest]
DJANGO_SETTINGS_MODULE=myapp.settings.test
norecursedirs=venv .git build

وقمت أيضًا بتعيينه في سطر الأوامر باستخدام --ds=myapp.settings.test دون جدوى

طيب غريب.
هل يمكنك إضافة import pdb; pdb.set_trace() قبل استيراد base ثم معرفة المكان الذي يتم استدعاؤه منه ( bt ) ، ثم s tep لرؤية ذلك ما الذي يجري.

من هنا يأتي:

$ py.test -vxsk test_public_api
> ~/projects/myapp/settings/test.py(2)<module>()
      1 import ipdb;ipdb.set_trace()
----> 2 from myapp.settings.base import *   # pylint: disable=W0614,W0401
      3

ipdb> bt
  ~/.virtualenvs/myapp/bin/py.test(11)<module>()
      7 from pytest import main
      8
      9 if __name__ == '__main__':
     10     sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
---> 11     sys.exit(main())

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/config.py(32)main()
     30     """
     31     try:
---> 32         config = _prepareconfig(args, plugins)
     33     except ConftestImportFailure:
     34         e = sys.exc_info()[1]

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/config.py(85)_prepareconfig()
     83                 pluginmanager.register(plugin)
     84         return pluginmanager.hook.pytest_cmdline_parse(
---> 85                 pluginmanager=pluginmanager, args=args)
     86     except Exception:
     87         pluginmanager.ensure_shutdown()

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(521)__call__()
    519
    520     def __call__(self, **kwargs):
--> 521         return self._docall(self.methods, kwargs)
    522
    523     def callextra(self, methods, **kwargs):

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(528)_docall()
    526     def _docall(self, methods, kwargs):
    527         return MultiCall(methods, kwargs,
--> 528                          firstresult=self.firstresult).execute()
    529
    530

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(393)execute()
    391             args = [all_kwargs[argname] for argname in varnames(method)]
    392             if hasattr(method, "hookwrapper"):
--> 393                 return wrapped_call(method(*args), self.execute)
    394             res = method(*args)
    395             if res is not None:

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(107)wrapped_call()
    105     except StopIteration:
    106         raise_wrapfail(wrap_controller, "did not yield")
--> 107     call_outcome = CallOutcome(func)
    108     try:
    109         wrap_controller.send(call_outcome)

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(123)__init__()
    121     def __init__(self, func):
    122         try:
--> 123             self.result = func()
    124         except BaseException:
    125             self.excinfo = sys.exc_info()

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(394)execute()
    392             if hasattr(method, "hookwrapper"):
    393                 return wrapped_call(method(*args), self.execute)
--> 394             res = method(*args)
    395             if res is not None:
    396                 self.results.append(res)

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/config.py(636)pytest_cmdline_parse()
    634     def pytest_cmdline_parse(self, pluginmanager, args):
    635         assert self == pluginmanager.config, (self, pluginmanager.config)
--> 636         self.parse(args)
    637         return self
    638

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/config.py(746)parse()
    744                 "can only parse cmdline args at most once per Config object")
    745         self._origargs = args
--> 746         self._preparse(args)
    747         # XXX deprecated hook:
    748         self.hook.pytest_cmdline_preparse(config=self, args=args)

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/config.py(718)_preparse()
    716         try:
    717             self.hook.pytest_load_initial_conftests(early_config=self,
--> 718                     args=args, parser=self._parser)
    719         except ConftestImportFailure:
    720             e = sys.exc_info()[1]

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(521)__call__()
    519
    520     def __call__(self, **kwargs):
--> 521         return self._docall(self.methods, kwargs)
    522
    523     def callextra(self, methods, **kwargs):

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(528)_docall()
    526     def _docall(self, methods, kwargs):
    527         return MultiCall(methods, kwargs,
--> 528                          firstresult=self.firstresult).execute()
    529
    530

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(393)execute()
    391             args = [all_kwargs[argname] for argname in varnames(method)]
    392             if hasattr(method, "hookwrapper"):
--> 393                 return wrapped_call(method(*args), self.execute)
    394             res = method(*args)
    395             if res is not None:

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(107)wrapped_call()
    105     except StopIteration:
    106         raise_wrapfail(wrap_controller, "did not yield")
--> 107     call_outcome = CallOutcome(func)
    108     try:
    109         wrap_controller.send(call_outcome)

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(123)__init__()
    121     def __init__(self, func):
    122         try:
--> 123             self.result = func()
    124         except BaseException:
    125             self.excinfo = sys.exc_info()

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/_pytest/core.py(394)execute()
    392             if hasattr(method, "hookwrapper"):
    393                 return wrapped_call(method(*args), self.execute)
--> 394             res = method(*args)
    395             if res is not None:
    396                 self.results.append(res)

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/pytest_django/plugin.py(87)pytest_load_initial_conftests()
     85 if pytest.__version__[:3] >= "2.4":
     86     def pytest_load_initial_conftests(early_config, parser, args):
---> 87         _load_settings(early_config, parser.parse_known_args(args))
     88
     89

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/pytest_django/plugin.py(79)_load_settings()
     77         from django.conf import settings
     78         try:
---> 79             settings.DATABASES
     80         except ImportError:
     81             e = sys.exc_info()[1]

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/django/conf/__init__.py(48)__getattr__()
     46     def __getattr__(self, name):
     47         if self._wrapped is empty:
---> 48             self._setup(name)
     49         return getattr(self._wrapped, name)
     50

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/django/conf/__init__.py(44)_setup()
     42                 % (desc, ENVIRONMENT_VARIABLE))
     43
---> 44         self._wrapped = Settings(settings_module)
     45
     46     def __getattr__(self, name):

  ~/.virtualenvs/myapp/local/lib/python2.7/site-packages/django/conf/__init__.py(92)__init__()
     90         self.SETTINGS_MODULE = settings_module
     91
---> 92         mod = importlib.import_module(self.SETTINGS_MODULE)
     93
     94         tuple_settings = (

  /usr/lib/python2.7/importlib/__init__.py(37)import_module()
     34                 break
     35             level += 1
     36         name = _resolve_name(name[level:], package, level)
---> 37     __import__(name)
     38     return sys.modules[name]

> ~/projects/myapp/settings/test.py(2)<module>()
      1 import ipdb;ipdb.set_trace()
----> 2 from myapp.settings.base import *   # pylint: disable=W0614,W0401
      3
      4 DEBUG = False
      5 TEMPLATE_DEBUG = DEBUG

وبمجرد أن أتخطى عملية الاستيراد REST_FRAMEWORK متاحًا ولديه الإعدادات الصحيحة من base.py . بمجرد أن أخطو في هذا الملف وينتقل إلى إعدادات django الداخلية ، يمكنني الحصول على الإعدادات. REST_FRAMEWORK وهو صحيح أيضًا. ولكن إذا ضغطت على c لمواصلة الاختبار ، فإنه يفشل مع وجود أخطاء تشير إلى أنه لا يعمل بالفعل مع القيم المستوردة من base.py . القيم من DATABASES stick ، ​​فقط ليست من REST_FRAMEWORK .

هل يمكنك تقليل هذا إلى الحد الأدنى من المشروع باستخدام ملفات إعدادات متعددة حيث يمكن تكرار المشكلة؟

اكتشفت أن قيمة DJANGO_SETTINGS_MODULE في pytest.ini لا تتجاوز متغير البيئة DJANGO_SETTINGS_MODULE . لدي أيضًا ملف إعدادات للاختبار مشتق من ملف إعدادات آخر - يستخدم pytest ملف الإعدادات الأساسي نظرًا لأن هذه هي القيمة في متغير البيئة.

@ smcoll صحيح. يبدو أن قيمة ENV تتجاوز قيمة INI / config:

https://github.com/pytest-dev/pytest-django/blob/877cd711b61b06385e0eb5900acf8eb775244810/pytest_django/plugin.py#L292 -L300

بالنسبة لنا ، نحن قادرون على عمل الأشياء عبر DJANGO_SETTINGS_MODULE=config.settings.test pytest لأننا نقوم بتشغيل الأشياء محليًا باستخدام Docker / Compose والذي يتم تعيينه افتراضيًا على config.settings.local في ENV.

أشعر أن pytest-django يفعل الشيء الصحيح ولكني أتساءل أيضًا عما إذا كان يجب أن يفوق التكوين البيئة المحيطة؟

لقد حصلت للتو على القليل من هذه القضية. أعتقد أن التكوين يجب أن يتفوق على البيئة ، شخصيًا ...

ترتيب الاكتشاف موثق هنا .

يعد envvar تقليديًا أقوى من ملف التكوين ، لذلك هذا هو السلوك المتوقع ، وبسبب التوافق مع الإصدارات السابقة من غير المرجح أن يتغير على أي حال.

طريقة واحدة لخداع هذا هو الاستخدام

[pytest]
addopts = --ds=my_settings

بدلاً من إعداد DJANGO_SETTINGS_MODULE . يكون لعلم سطر الأوامر الأسبقية على أي شيء آخر.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات