رجوع التالي 
حيلة قوية خارج الصندوق ، ستتحسن عندما تضيف مزيجًا من الإضافات إليها. قاعدة كود pytest مبنية على الإعدادات والإضافات ، وهناك روابط متوفرة للتعديل والتحسينات من خلال الإضافات.

الأمثلة في هذا الكتاب مكتوبة باستخدام Python 3.6 و pytest 3.2. يدعم pytest 3.2 Python 2.6 و 2.7 و Python 3.3+.
تتوفر شفرة المصدر لمشروع المهام ، وكذلك لجميع الاختبارات الموضحة في هذا الكتاب ، على الرابط في صفحة الويب للكتاب على pragprog.com . لا تحتاج إلى تنزيل الكود المصدري لفهم كود الاختبار ؛ يتم تقديم رمز الاختبار في شكل مناسب في الأمثلة. ولكن من أجل متابعة مهام المشروع ، أو تكييف أمثلة الاختبار لاختبار المشروع الخاص بك (يديك غير مقيدة!) ، يجب عليك الانتقال إلى صفحة الويب الخاصة بالكتاب وتنزيل العمل. هناك ، على صفحة الكتاب على شبكة الإنترنت ، هناك رابط لرسائل خطأ ومنتدى مناقشة .
تحت المفسد هي قائمة من المقالات في هذه السلسلة.
دعنا نذهب أبعد من ذلك!
قد تفاجأ عندما علمت أنك قد كتبت بالفعل بعض الإضافات إذا كنت قد عملت في الفصول السابقة في هذا الكتاب. في كل مرة تقوم فيها بوضع تركيبات و / أو وظائف ربط في ملف conftest.py
ذي المستوى conftest.py
للمشروع ، تقوم بإنشاء conftest
إضافي conftest
محلي. إنه مجرد عمل إضافي قليل لتحويل هذه الملفات conftest.py
إلى مكونات إضافية conftest.py
للتثبيت والتي يمكنك مشاركتها بين المشاريع ، أو مع أشخاص آخرين ، أو مع العالم.
نبدأ هذا الفصل من خلال الإجابة على سؤال البحث عن الإضافات الخارجية. هناك عدد قليل جدًا من الإضافات المتاحة ، لذلك هناك فرصة جيدة أن يقوم شخص ما بالفعل بكتابة التغييرات التي تريد pytest
في pytest
. نظرًا لأننا سننظر في المكونات الإضافية مفتوحة المصدر ، إذا كان المكوّن الإضافي يفعل ما تريد القيام به تقريبًا ، ولكن ليس تمامًا ، يمكنك تطويره أو استخدامه كمرجع لإنشاء المكون الإضافي الخاص بك. على الرغم من أن هذا الفصل يدور حول إنشاء الإضافات الخاصة بك ، إلا أن الملحق 3 ، المكون الإضافي Sampler Pack ، في الصفحة 163 مدرج لإعطائك مذاقًا ممكنًا.
ستتعلم في هذا الفصل كيفية إنشاء مكونات إضافية ، وسأريك الاتجاه الصحيح للاختبار والتعبئة والتوزيع. موضوع التعبئة والتغليف والتعبئة Python الكامل واسع للغاية ويدعي أنه كتاب خاص به ، لذلك لن نغطي كل شيء. ولكن ستحصل على معلومات كافية لتتمكن من تبادل المكونات الإضافية مع فريقك. سأتحدث أيضًا عن بعض الطرق البسيطة لإنشاء مكونات إضافية بدعم PyPI وأقل قدر من العمل.
البحث عن الإضافات
يمكنك العثور على ملحقات pytest لجهة خارجية في عدة أماكن. تتوفر المكونات الإضافية المدرجة في الملحق 3 ، البرنامج المساعد Sampler Pack ، في الصفحة 163 ، للتنزيل من PyPI. ومع ذلك ، ليس هذا هو المكان الوحيد لإيجاد الإضافات pytest كبيرة.
https://docs.pytest.org/en/latest/plugins.html
يحتوي موقع وثائق pytest الرئيسي على صفحة تتحدث عن تثبيت واستخدام مكونات pytest وتسرد بعض الإضافات الشائعة.
https://pypi.python.org
يعد Python Package Index (PyPI) مكانًا رائعًا للحصول على الكثير من حزم Python ، ولكنه أيضًا مكان رائع للبحث عن الإضافات pytest. عند البحث عن الإضافات pytest ، ما عليك سوى إدخال "pytest" أو "pytest" أو "pytest" في حقل البحث ، نظرًا لأن معظم الإضافات pytest إما تبدأ بـ "pytest -" أو تنتهي بـ "pytest".
https://github.com/pytest-dev
مجموعة pytest-dev على GitHub هي المكان الذي يتم فيه تخزين شفرة مصدر pytest. بالإضافة إلى ذلك ، يمكنك هنا العثور على ملحقات pytest الشائعة التي يجب دعمها على المدى الطويل من قبل فريق pytest kernel.
تثبيت البرنامج المساعد
يتم تثبيت الإضافات Pytest مع نقطة ، مثل حزم بيثون الأخرى. ومع ذلك،
يمكنك استخدام pip بعدة طرق لتثبيت المكونات الإضافية.
تثبيت من PyPI
نظرًا لأن PyPI هو الموقع الافتراضي لـ pip ، فإن تثبيت المكونات الإضافية من PyPI هو أسهل طريقة. لنقم بتثبيت البرنامج المساعد pytest-cov
:
$ pip install pytest-cov
سيتم تثبيت أحدث إصدار ثابت من PyPI.
تثبيت نسخة محددة من PyPI
إذا كنت تريد إصدارًا معينًا من المكون الإضافي ، فيمكنك تحديد الإصدار بعد ==
:
$ pip install pytest-cov==2.4.0
التثبيت من ملف .tar.gz أو .whl
يتم توزيع حزم PyPI كملفات مضغوطة ذات الامتدادات .tar.gz
و / أو .whl
. وغالبا ما يشار إليها على أنها كرات القطران والعجلات. إذا كنت تواجه مشكلات في محاولة العمل مع PyPI مباشرةً (والتي يمكن أن تحدث مع جدران الحماية ومضاعفات الشبكة الأخرى) ، يمكنك تنزيل إما .tar.gz
أو .whl
من هذا أو ذاك.
لا تحتاج إلى فك أو الرقص مع الدف ؛ مجرد نقطة نقطة في ذلك:
$ pip install pytest-cov-2.4.0.tar.gz # or $ pip install pytest_cov-2.4.0-py2.py3-none-any.whl
التثبيت من الدليل المحلي
يمكنك الحصول على المكونات الإضافية للمكونات الإضافية (وحزم Python الأخرى) في دليل محلي أو مشترك .whl
أو .whl
واستخدام هذا بدلاً من PyPI لتثبيت المكونات الإضافية:
$ mkdir some_plugins $ cp pytest_cov-2.4.0-py2.py3-none-any.whl some_plugins/ $ pip install --no-index --find-links=./some_plugins/ pytest-cov
--no-index
يخبر pip
بعدم الاتصال بـ PyPI. --find-links=./some_plugins/
يخبر pip بالبحث في دليل some_plugins
. هذه الطريقة مفيدة بشكل خاص إذا كان لديك كل من الإضافات الخاصة بالجهات الخارجية والإضافات الخاصة بك مخزنة محليًا ، وكذلك إذا كنت تنشئ بيئات افتراضية جديدة للتكامل المستمر أو مع السميات. (سنتحدث عن كل من السمية والتكامل المستمر في الفصل 7 ، باستخدام pytest مع أدوات أخرى ، في الصفحة 125.)
يرجى ملاحظة أنه باستخدام طريقة تثبيت الدليل المحلي ، يمكنك تثبيت العديد من الإصدارات وتحديد الإصدار الذي تريده عن طريق إضافة == ورقم الإصدار:
$ pip install --no-index --find-links=./some_plugins/ pytest-cov==2.4.0
تثبيت من مستودع بوابة
يمكنك تثبيت المكونات الإضافية مباشرة من مستودع Git في هذه الحالة GitHub:
$ pip install git+https://github.com/pytest-dev/pytest-cov
يمكنك أيضًا تحديد علامة الإصدار:
$ pip install git+https://github.com/pytest-dev/pytest-cov@v2.4.0
أو يمكنك تحديد فرع:
$ pip install git+https://github.com/pytest-dev/pytest-cov@master
يعد التثبيت من مستودع Git مفيدًا بشكل خاص إذا كنت تقوم بتخزين عملك في Git أو إذا كان الإصدار المطلوب من البرنامج المساعد أو البرنامج المساعد مفقودًا من PyPI.
ملاحظة المترجم:
يدعم pip التثبيت من Git و Mercurial و Subversion و Bazaar ويحدد نوع VCS باستخدام بادئات url: "git +" و "hg +" و "svn +" و "bzr +".
راجع وثائق PyPI لمزيد من التفاصيل.
كتابة الإضافات الخاصة بك
تحتوي العديد من المكونات الإضافية لجهات خارجية على الكثير من التعليمات البرمجية. هذا أحد الأسباب التي تجعلنا نستخدمها لتوفير الوقت لنا لتطوير كل هذا بمفردنا. ومع ذلك ، بالنسبة لكودك المحدد ، ستأتي بلا شك بتجهيزات وتعديلات خاصة لمساعدتك في اختباره. من خلال إنشاء مكون إضافي ، يمكنك مشاركة العديد من التركيبات التي تريد مشاركتها بسهولة بين عدة مشاريع. يمكنك مشاركة هذه التغييرات مع العديد من المشاريع - وربما مع بقية العالم - من خلال تطوير المكونات الإضافية الخاصة بك وتوزيعها. هذا سهل جدا للقيام به. في هذا القسم ، سنضع تعديلًا صغيرًا لسلوك pytest ، ونضعه كمكون إضافي ، ونختبره ونفكر في كيفية توزيعه.
يمكن أن تشمل الإضافات وظائف ربط التي تعدل سلوك pytest. منذ تم تصميم pytest للسماح للمكونات الإضافية بتغيير سلوك pytest بشكل طفيف ، تتوفر العديد من وظائف الخطاف. السنانير ل pytest مدرجة في موقع وثائق pytest . في مثالنا ، سننشئ مكونًا إضافيًا يغير مظهر حالة الاختبار. إضافة معلمة سطر الأوامر لتمكين هذا السلوك الجديد. إضافة نص إلى رأس الإخراج. على وجه الخصوص ، سوف نقوم بتغيير جميع مؤشرات حالة FAILED (الفاشلة) إلى "OPPORTUNITY (المحتملين) للتحسين" ، وتغيير F إلى O ، وإضافة "شكرًا لتشغيل الاختبارات" على الرأس. للقيام بذلك ، سوف نستخدم خيار - --nice
.
للحفاظ على تغييرات السلوك منفصلة عن مناقشة ميكانيكا البرنامج المساعد ، سنقوم بإجراء تغييرات على conftest.py قبل تحويلها إلى مكون إضافي قابل لإعادة التوزيع. لا تحتاج إلى تشغيل الإضافات بهذه الطريقة. ولكن غالبًا ما تكون التغييرات التي تنوي استخدامها في مشروع واحد فقط مفيدة بما يكفي للمشاركة وتحويلها إلى مكون إضافي. لذلك ، نبدأ بإضافة وظيفة إلى ملف conftest.py ، وبعد ذلك ، بعد أن يعمل كل شيء في conftest.py ، ننقل الكود إلى الحزمة.
العودة إلى مشروع المهام. في قسم "انتظار الاستثناءات" في الصفحة 30 ، كتبنا العديد من الاختبارات التي فحصت ما إذا كانت هناك استثناءات تم طرحها إذا قام شخص ما بالاتصال بوظيفة API بشكل غير صحيح. يبدو أننا فقدنا بعض حالات الخطأ المحتملة على الأقل.
إليك بضعة اختبارات أخرى:
ch5 / a /asks_proj / tests / func / test_api_exceptions.py
""" API wrong.""" import pytest import tasks from tasks import Task @pytest.mark.usefixtures('tasks_db') class TestAdd(): """, tasks.add().""" def test_missing_summary(self): """ , summary missing.""" with pytest.raises(ValueError): tasks.add(Task(owner='bob')) def test_done_not_bool(self): """ , done bool.""" with pytest.raises(ValueError): tasks.add(Task(summary='summary', done='True'))
دعنا نركضهم للتحقق مما إذا كانوا يجتازون:
$ cd /path/to/code/ch5/a/tasks_proj $ pytest ===================== test session starts ====================== collected 57 items tests/func/test_add.py ... tests/func/test_add_variety.py ............................ tests/func/test_add_variety2.py ............ tests/func/test_api_exceptions.py .F....... tests/func/test_unique_id.py . tests/unit/test_task.py .... =========================== FAILURES =========================== __________________ TestAdd.test_done_not_bool __________________ self = <func.test_api_exceptions.TestAdd object at 0x103a71a20> def test_done_not_bool(self): """Should raise an exception if done is not a bool.""" with pytest.raises(ValueError): > tasks.add(Task(summary='summary', done='True')) E Failed: DID NOT RAISE <class 'ValueError'> tests/func/test_api_exceptions.py:20: Failed ============= 1 failed, 56 passed in 0.28 seconds ==============
دعونا تشغيله مرة أخرى مع -v
للحصول على التفاصيل. نظرًا لأنك قد شاهدت التتبع بالفعل ، يمكنك إيقاف تشغيله بالضغط على --tb=no
.
الآن دعنا نركز على الاختبارات الجديدة باستخدام -k TestAdd
، والذي يعمل لأنه لا توجد اختبارات أخرى بأسماء تحتوي على "TestAdd".
يمكننا "إسقاط كل شيء" ومحاولة إصلاح هذا الاختبار (وسنفعله لاحقًا) ، ولكن الآن سنركز على محاولة جعل الإخفاقات أكثر متعة للمطورين.
لنبدأ بإضافة رسالة شكر إلى الرأس ، والتي يمكنك إجراؤها باستخدام ربط pytest_report_header()
يسمى pytest_report_header()
.
ch5 / b /asks_proj / tests / conftest.py
def pytest_report_header(): """ .""" return "Thanks for running the tests."
من الواضح أن كتابة ملاحظة شكرا غبية للغاية. ومع ذلك ، يمكن توسيع القدرة على إضافة معلومات إلى الرأس. يمكنك إضافة اسم مستخدم ، والإشارة إلى المعدات المستخدمة والإصدارات التي سيتم اختبارها. بشكل عام ، يمكن إدراج كل شيء يمكنك تحويله إلى سلسلة في عنوان الاختبار.
بعد ذلك ، سنقوم بتغيير تقرير حالة الاختبار لتغيير F
إلى O
و FAILED
إلى OPPORTUNITY for improvement
. هناك ربط يسمح لهذه العلاقة: pytest_report_teststatus()
:
ch5 / b /asks_proj / tests / conftest.py
def pytest_report_teststatus(report): """ .""" if report.when == 'call' and report.failed: return (report.outcome, 'O', 'OPPORTUNITY for improvement')
والآن لدينا فقط الحل الذي كنا نبحث عنه. تُظهر جلسة اختبار بدون علامة - --verbose
O
للفشل ، أي أن التحسينات ممكنة:
$ cd /path/to/code/ch5/b/tasks_proj/tests/func $ pytest --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py .O ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.06 seconds =======
باستخدام علامة -v
أو - --verbose
سيكون أفضل:
$ pytest -v --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py::TestAdd::test_missing_summary PASSED test_api_exceptions.py::TestAdd::test_done_not_bool OPPORTUNITY for improvement ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.07 seconds =======
التغيير الأخير الذي --nice,
هو إضافة معلمة سطر الأوامر ، - --nice,
بحيث تحدث التغييرات في وضعنا فقط إذا استبدلت - --nice
:
def pytest_addoption(parser): """ nice --nice.""" group = parser.getgroup('nice') group.addoption("--nice", action="store_true", help="nice: turn failures into opportunities") def pytest_report_header(): """ .""" if pytest.config.getoption('nice'): return "Thanks for running the tests." def pytest_report_teststatus(report): """ .""" if report.when == 'call': if report.failed and pytest.config.getoption('nice'): return (report.outcome, 'O', 'OPPORTUNITY for improvement')
تجدر الإشارة إلى أننا في هذا البرنامج المساعد نستخدم فقط عدد من السنانير. هناك العديد من الأشياء الأخرى التي يمكن العثور عليها على موقع وثائق Pytest الرئيسي .
الآن يمكننا اختبار البرنامج المساعد يدويًا عن طريق تشغيله في مثالنا. أولاً ، بدون الخيار --nice
، للتأكد من عرض اسم المستخدم فقط:
$ cd /path/to/code/ch5/c/tasks_proj/tests/func $ pytest --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== collected 9 items test_api_exceptions.py .F ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.07 seconds =======
الآن مع - --nice
:
$ pytest --nice --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py .O ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.07 seconds =======
الآن مع - --nice
--verbose
:
$ pytest -v --nice --tb=no test_api_exceptions.py -k TestAdd ===================== test session starts ====================== Thanks for running the tests. collected 9 items test_api_exceptions.py::TestAdd::test_missing_summary PASSED test_api_exceptions.py::TestAdd::test_done_not_bool OPPORTUNITY for improvement ====================== 7 tests deselected ====================== ======= 1 failed, 1 passed, 7 deselected in 0.06 seconds =======
! ممتاز تم إجراء جميع التغييرات التي أردنا إجراؤها في حوالي عشرة سطور من التعليمات البرمجية لملف conftest.py
. بعد ذلك ، سننقل هذا الرمز إلى بنية البرنامج المساعد.
إنشاء مكون إضافي قابل للتثبيت
يتم تعريف عملية مشاركة المكونات الإضافية مع المستخدمين الآخرين بشكل واضح. حتى إذا لم تقم بتشغيل المكون الإضافي الخاص بك في PyPI ، فسوف يسهل عليك تنفيذ هذه العملية قراءة الكود من الإضافات مفتوحة المصدر ، وستتاح لك المزيد من الفرص لتقييم ما إذا كانت ستساعدك أم لا.
سيكون من غير الضروري تغطية عبوات بيثون وتوزيعها بالكامل في هذا الكتاب ، لأن هذا الموضوع موثق جيدًا في مكان آخر. هنا وهنا وهنا باللغة الروسية. ومع ذلك ، فإن الانتقال من المكون الإضافي للتكوين المحلي الذي أنشأناه في القسم السابق إلى شيء تم تثبيته باستخدام pip ليس بالأمر الهين. .
أولاً ، نحتاج إلى إنشاء دليل جديد لاستضافة رمز المكون الإضافي الخاص بنا. لا يهم ما تسميه ، ولكن بما أننا نقوم بإنشاء مكون إضافي للعلم الجميل ، دعنا نسميه pytest-nice. سيكون لدينا ملفان في هذا الدليل الجديد: pytest_nice.py و setup.py. (ستتم مناقشة كتالوج الاختبار في قسم "اختبار المكونات الإضافية" في الصفحة 105.)
│ LICENSE │ pytest_nice.py │ setup.py │ └───tests │ conftest.py │ test_nice.py
في pytest_nice.py
، نضع المحتويات الدقيقة ل conftest.py الخاصة بنا والتي ارتبطت بهذه الوظيفة ( tasks_proj/tests/conftest.py
من tasks_proj/tests/conftest.py
):
ch5 / pytest-nice / pytest_nice.py
""" pytest-nice .""" import pytest def pytest_addoption(parser): """ nice --nice.""" group = parser.getgroup('nice') group.addoption("--nice", action="store_true", help="nice: turn FAILED into OPPORTUNITY for improvement") def pytest_report_header(): """ .""" if pytest.config.getoption('nice'): return "Thanks for running the tests." def pytest_report_teststatus(report): """ .""" if report.when == 'call': if report.failed and pytest.config.getoption('nice'): return (report.outcome, 'O', 'OPPORTUNITY for improvement')
في setup.py
نحتاج إلى الحد الأدنى من مكالمات setup()
:
ch5 / pytest-nice / setup.py
"""Setup pytest-nice plugin.""" from setuptools import setup setup( name='pytest-nice', version='0.1.0', description=' Pytest, FAILURE into OPPORTUNITY', url='https:////////', author=' ', author_email='your_email@somewhere.com', license='proprietary', py_modules=['pytest_nice'], install_requires=['pytest'], entry_points={'pytest11': ['nice = pytest_nice', ], }, )
ستحتاج إلى مزيد من المعلومات في الإعدادات إذا كنت ستوزعها على جمهور واسع أو على الإنترنت. ومع ذلك ، بالنسبة لفريق صغير أو فقط لنفسك ، سيكون هذا كافياً.
يمكنك تضمين بعض المعلمات الأخرى setup()
؛ وهنا لدينا فقط الحقول المطلوبة. حقل الإصدار هو إصدار هذا البرنامج المساعد. والأمر متروك لك تمامًا عند طرح الإصدار. حقل عنوان URL مطلوب. يمكنك تركه فارغًا ، لكنك ستتلقى تحذيرًا. يمكن استبدال author_email
author
author_email
بـ "جهة maintainer
و "جهة maintainer_email
، ولكن يجب أن يكون هناك أحد هذه الأزواج. حقل license
هو حقل نص قصير. قد يكون أحد تراخيص المصادر المفتوحة ، اسمك أو شركتك ، أو شيء مناسب لك. يسرد py_modules
pytest_nice
الوحيد لهذا البرنامج المساعد. على الرغم من أن هذه قائمة ، ويمكنك تضمين أكثر من وحدة واحدة ، إذا كان لدي أكثر من وحدة ، فإنني سوف أستخدم الحزمة وأضع كل الوحدات في دليل واحد.
حتى الآن ، تعد جميع خيارات setup()
قياسية وتستخدمها جميع أدوات تثبيت Python. الجزء الذي يختلف عن الإضافات Pytest هو المعلمة entry_points
. لقد أدرجنا entry_points={'pytest11': ['nice = pytest_nice', ], },.
تعتبر وظيفة entry_points
قياسية لـ setuptools
، لكن pytest11 هي المعرف الخاص الذي تبحث عنه pytest. في هذا السطر ، أخبر pytest أن الاسم nice
هو المكون الإضافي الخاص بنا ، و pytest_nice
اسم الوحدة النمطية التي يعيش فيها المكون الإضافي الخاص بنا. إذا استخدمنا الحزمة ، فسيكون إدخالنا هنا:
لم أتحدث عن ملف README.rst
. بعض أشكال README هو شرط setuptools. إذا فاتتك ذلك ، فستحصل على هذا:
... warning: sdist: standard file not found: should have one of README, README.rst, README.txt ...
يعد حفظ README كطريقة قياسية لتضمين بعض معلومات المشروع فكرة جيدة على أي حال. إليكم ما أضعه في ملف pytest-nice:
ch5 / pytest-nice / README.rst
pytest-nice : A pytest plugin ============================= pytest . -------- - , pytest. - ``--nice`` , : - ``F`` ``O`` - ``-v``, ``FAILURE`` ``OPPORTUNITY for improvement`` ------------ , Pytest .tar.gz PATH, : :: $ pip install PATH/pytest-nice-0.1.0.tar.gz $ pip install --no-index --find-links PATH pytest-nice ----- :: $ pytest --nice
هناك العديد من الآراء حول ما يجب أن يكون في ملف README. هذا هو الإصدار اقتصاص بشدة ، لكنه يعمل.
اختبار الإضافات
الإضافات هي الكود الذي يجب اختباره مثل أي كود آخر. ومع ذلك ، فإن اختبار التغييرات في أداة الاختبار أكثر تعقيدًا قليلاً. عندما طورنا رمز البرنامج المساعد في قسم "كتابة المكونات الإضافية الخاصة بك" ، في الصفحة 98 ، قمنا بفحصه يدويًا باستخدام ملف اختبار عينة ، وقم بتشغيله مع pytest والتحقق من الإخراج للتأكد من صحته. يمكننا أن نفعل الشيء نفسه في الوضع التلقائي باستخدام مكون إضافي يسمى pytester
، والذي يأتي مع pytest ولكن يتم تعطيله بشكل افتراضي.
يوجد ملفان في دليل الاختبار الخاص بنا لـ pytest-nice: conftest.py
و test_nice.py
. لاستخدام pytester
، نحتاج إلى إضافة سطر واحد فقط إلى conftest.py
:
ch5 / pytest-لطيفة / اختبارات / conftest.py
"""pytester is needed for testing plugins.""" pytest_plugins = 'pytester'
يتضمن هذا الخط البرنامج المساعد pytester
. سوف نستخدم لاعبا اساسيا يسمى testdir
، والذي يصبح متاحا عندما pytester
تشغيل pytester
.
غالبًا ما تأخذ اختبارات المكونات الإضافية النموذج الذي وصفناه يدويًا:
- تقديم ملف اختبار مثال.
- تشغيل pytest مع أو بدون بعض المعلمات في الدليل الذي يحتوي على ملف العينة.
- تحقق الإخراج.
- ممكن ، للتحقق من رمز النتيجة هو 0 لجميع التمريرات ، 1 لبعض الإخفاقات.
لنلقِ نظرة على مثال واحد:
ch5 / pytest-nice / tests / test_nice.py
def test_pass_fail(testdir):
تقوم أداة اختبار testdir
تلقائيًا بإنشاء دليل مؤقت لاستضافة ملفات الاختبار. يحتوي على طريقة makepyfile()
تسمح لك بوضع محتويات ملف اختبار ، وفي هذه الحالة ، نقوم بإنشاء اختبارين: أحدهما يمر والآخر لا يمر .
نقوم بتشغيل pytest لملف اختبار جديد باستخدام testdir.runpytest()
. يمكنك تمرير المعلمات إذا كنت تريد. يمكن اعتبار قيمة الإرجاع لاحقًا وهي من النوع RunResult .
عادة أنا أنظر إلى stdout
ret
. , , , fnmatch_lines
, , , , ret
0 1 . , fnmatch_lines
, . . , , :
ch5/pytest-nice/tests/test_nice.py
@pytest.fixture() def sample_test(testdir): testdir.makepyfile(""" def test_pass(): assert 1 == 1 def test_fail(): assert 1 == 2 """) return testdir
, , sample_test
, . :
ch5/pytest-nice/tests/test_nice.py
def test_with_nice(sample_test): result = sample_test.runpytest('--nice') result.stdout.fnmatch_lines(['*.O', ])
. , :
ch5/pytest-nice/tests/test_nice.py
def test_header(sample_test): result = sample_test.runpytest('--nice') result.stdout.fnmatch_lines(['Thanks for running the tests.']) def test_header_not_nice(sample_test): result = sample_test.runpytest() thanks_message = 'Thanks for running the tests.' assert thanks_message not in result.stdout.str()
, , .
:
ch5/pytest-nice/tests/test_nice.py
def test_help_message(testdir): result = testdir.runpytest('--help')
, , , .
pytest-nice
, . .zip.gz
, :
$ cd /path/to/code/ch5/pytest-nice/ $ pip install . Processing /path/to/code/ch5/pytest-nice Requirement already satisfied: pytest in /path/to/venv/lib/python3.6/site-packages (from pytest-nice==0.1.0) Requirement already satisfied: py>=1.4.33 in /path/to/venv/lib/python3.6/site-packages (from pytest->pytest-nice==0.1.0) Requirement already satisfied: setuptools in /path/to/venv/lib/python3.6/site-packages (from pytest->pytest-nice==0.1.0) Building wheels for collected packages: pytest-nice Running setup.py bdist_wheel for pytest-nice ... done ... Successfully built pytest-nice Installing collected packages: pytest-nice Successfully installed pytest-nice-0.1.0
, , :
$ pytest -v ===================== test session starts ====================== plugins: nice-0.1.0 collected 7 items tests/test_nice.py::test_pass_fail PASSED tests/test_nice.py::test_with_nice PASSED tests/test_nice.py::test_with_nice_verbose PASSED tests/test_nice.py::test_not_nice_verbose PASSED tests/test_nice.py::test_header PASSED tests/test_nice.py::test_header_not_nice PASSED tests/test_nice.py::test_help_message PASSED =================== 7 passed in 0.34 seconds ===================
. : , . .
platform win32 -- Python 3.6.5, pytest-3.9.3, py-1.7.0, pluggy-0.8.0 -- c:\venv36\scripts\python.exe collected 7 items tests/test_nice.py::test_pass_fail FAILED [ 14%] tests/test_nice.py::test_with_nice OPPORTUNITY for improvement [ 28%] tests/test_nice.py::test_with_nice_verbose OPPORTUNITY for improvement [ 42%] tests/test_nice.py::test_not_nice_verbose FAILED [ 57%] tests/test_nice.py::test_header PASSED [ 71%] tests/test_nice.py::test_header_not_nice PASSED [ 85%] tests/test_nice.py::test_help_message PASSED [100%] ================================== FAILURES =================================== _______________________________ test_pass_fail ________________________________
result.stdout.fnmatch_lines([ '*.F', # . for Pass, F for Fail ])
في
result.stdout.fnmatch_lines([ '*.F*', # . for Pass, F for Fail ])
*
F
test_with_nice
, test_with_nice_verbose
, test_not_nice_verbose
pytest.
c
'test_with_nice.py .O [100%]'
.
,
RemovedInPytest4Warning: usage of Session.Class is deprecated, please use pytest.Class instead
!
(venv36) c:\_BOOKS_\pytest_si\bopytest-code\code\ch5\pytest-nice>pytest -v ============================= test session starts ============================= platform win32 -- Python 3.6.5, pytest-3.9.3, py-1.7.0, pluggy-0.8.0 -- c:\venv36\scripts\python.exe cachedir: .pytest_cache rootdir: c:\_BOOKS_\pytest_si\bopytest-code\code\ch5\pytest-nice, inifile: plugins: nice-0.1.0 collected 7 items tests/test_nice.py::test_pass_fail PASSED [ 14%] tests/test_nice.py::test_with_nice PASSED [ 28%] tests/test_nice.py::test_with_nice_verbose PASSED [ 42%] tests/test_nice.py::test_not_nice_verbose PASSED [ 57%] tests/test_nice.py::test_header PASSED [ 71%] tests/test_nice.py::test_header_not_nice PASSED [ 85%] tests/test_nice.py::test_help_message PASSED [100%] ============================== warnings summary =============================== tests/test_nice.py::test_pass_fail c:\venv36\lib\site-packages\_pytest\compat.py:332: RemovedInPytest4Warning: usage of Session.Class is deprecated, please use pytest.Class instead return getattr(object, name, default)
الصيحة! . (pytest-nice), Python
pytest-:
$ pip uninstall pytest-nice Uninstalling pytest-nice-0.1.0: Would remove: \path\to\venv\lib\site-packages\pytest_nice-0.1.0.dist-info\* ... Proceed (y/n)? y Successfully uninstalled pytest-nice-0.1.0
— , pytest, PyPI.
, . , setup.py :
$ cd /path/to/code/ch5/pytest-nice $ python setup.py sdist running sdist running egg_info creating pytest_nice.egg-info ... running check creating pytest-nice-0.1.0 ... creating dist Creating tar archive ... $ ls dist pytest-nice-0.1.0.tar.gz
( , sdist source distribution — “ .”)
pytest-nice dist pytest-nice-0.1.0.tar.gz
.
, , :
$ pip install dist/pytest-nice-0.1.0.tar.gz Processing ./dist/pytest-nice-0.1.0.tar.gz ... Installing collected packages: pytest-nice Successfully installed pytest-nice-0.1.0
.tar.gz
, .
pip
, , , , , , .tar.gz
. , pytest-nice-0.1.0.tar.gz
myplugins
.
pytest-nice
myplugins
:
$ pip install --no-index --find-links myplugins pytest-nice
--no-index
pip
PyPI, , .
The --find-links myplugins tells PyPI to look in myplugins for packages to install. And of course, pytest-nice is what we want to install.
--find-links myplugins
PyPI myplugins
. , pytest-nice
— , .
myplugins
, , --upgrade
:
$ pip install --upgrade --no-index --find-links myplugins pytest-nice
pip
, --no-index --find-links myplugins
.
PyPI
, , . , . , , , Python Packaging .
pytest, — cookiecutter-pytest-plugin
:
$ pip install cookiecutter $ cookiecutter https://github.com/pytest-dev/cookiecutter-pytest-plugin
. , . ; , , . pytest, , .
تمارين
ch4/cache/test_slower.py
autouse fixture, check_duration()
. 4. .
- pytest-slower, , , « » . 102.
- , pytest-slower , .
- .
- Python Package Index «pytest-». pytest, .
- Tasks.
ما التالي
conftest.py
. , pytest, pytest.ini
. , , .
رجوع التالي 