دليل استخدام PyTest: ما هو PyTest؟ (مع أمثلة)
⚡ ملخص ذكي
Pytest هو Python إطار عمل للاختبار يساعدك على كتابة اختبارات بسيطة وقابلة للتوسع لقواعد البيانات وواجهات برمجة التطبيقات وواجهات المستخدم. يدعم هذا الإطار التجهيزات، وتحديد المعلمات، والعلامات، والتشغيل المتوازي، وإعداد تقارير مفصلة عن التأكيدات، بدءًا من اختبارات الوحدة الأساسية وصولًا إلى الاختبارات الوظيفية المعقدة.

بيتيست يُعد أحد أكثر أطر الاختبار استخدامًا في Python نظام بيئي متكامل. يحافظ على اختصار كود الاختبار وسهولة قراءته، ويكتشف الاختبارات تلقائيًا، ويتطور من أول تأكيد إلى مجموعة اختبارات كاملة لقواعد البيانات وواجهات برمجة التطبيقات وواجهات المستخدم. تشرح الأقسام التالية عملية التثبيت والتأكيدات والتجهيزات والعلامات والمعايرة والتشغيل المتوازي مع أمثلة عملية.
ما هو Pytest؟
بيتيست هو إطار عمل للاختبار يتيح لك كتابة كود الاختبار باستخدام Python لغة برمجة. تساعدك على كتابة حالات اختبار بسيطة وقابلة للتطوير لقواعد البيانات، وواجهات برمجة التطبيقات، وحتى واجهات المستخدم. يُستخدم Pytest بشكل أساسي لكتابة اختبارات واجهات برمجة التطبيقات، وهو قابل للتطوير من اختبارات الوحدات البسيطة إلى الاختبارات الوظيفية المعقدة.
لماذا نستخدم Pytest؟
من مزايا pytest ما يلي:
- من السهل جدًا البدء به، نظرًا لبنيته البسيطة والواضحة.
- يمكن إجراء الاختبارات بالتوازي.
- يمكن تشغيل اختبار محدد أو مجموعة فرعية من الاختبارات.
- يكشف الاختبارات تلقائيًا.
- يمكن تخطي الاختبارات.
- المصدر المفتوح.
كيفية تثبيت Pytest
فيما يلي خطوات تثبيت pytest:
الخطوة 1) يمكنك تثبيت pytest باستخدام الأمر أدناه.
pip install pytest==2.9.1
بمجرد اكتمال التثبيت، يمكنك تأكيده باستخدام الأمر التالي.
py.test -h
سيؤدي هذا إلى عرض المساعدة.
مثال أساسي أولي لـ Pytest
الآن، ستتعلم كيفية استخدام pytest من خلال مثال أساسي لـ pytest.
أنشئ مجلدًا باسم study_pytest. ستُنشئ ملفات الاختبار داخل هذا المجلد. انتقل إلى هذا المجلد من خلال سطر الأوامر. أنشئ ملفًا باسم test_sample1.py داخل المجلد.
أضف الكود أدناه واحفظه.
import pytest def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed" def test_file1_method2(): x=5 y=6 assert x+1 == y,"test failed"
قم بتشغيل الاختبار باستخدام الأمر أدناه.
py.test
ستحصل على الناتج كما يلي.
test_sample1.py F.
============================================== FAILURES ========================================
____________________________________________ test_sample1 ______________________________________
def test_file1_method1():
x=5
y=6
assert x+1 == y,"test failed"
> assert x == y,"test failed"
E AssertionError: test failed
E assert 5 == 6
test_sample1.py:6: AssertionError
هنا، في الملف test_sample1.py، يشير الحرف F إلى الفشل، بينما تشير النقطة (.) إلى النجاح. في قسم حالات الفشل، يمكنك رؤية الطريقة (الطرق) الفاشلة وسطر الفشل. هنا، x==y تعني 5==6، وهذا خطأ.
بعد ذلك، ستتعرف على التأكيدات في pytest.
التأكيدات في Pytest
تُعدّ تأكيدات Pytest عمليات تحقق تُرجع إما حالة "صحيح" أو "خطأ". في Pytest، إذا فشل تأكيد في دالة اختبار، يتوقف تنفيذ تلك الدالة عند تلك النقطة. لا يتم تنفيذ باقي التعليمات البرمجية في دالة الاختبار، ويستمر Pytest مع دالة الاختبار التالية.
أمثلة على تأكيدات Pytest:
assert "hello" == "Hai" is an assertion failure. assert 4==4 is a successful assertion assert True is a successful assertion assert False is an assertion failure.
النظر في ما يلي.
assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
ضع هذا الكود في الدالة test_file1_method1() بدلاً من التأكيد أدناه.
assert x == y,"test failed"
تشغيل الاختبار سوف يعطي الفشل كما خطأ التأكيد: فشل الاختبار x=5 y=6.
كيف يتعرف برنامج Pytest على ملفات الاختبار وطرق الاختبار
بشكل افتراضي، لا يتعرف pytest إلا على أسماء الملفات التي تبدأ بـ امتحان_ أو تنتهي بـ _اختبار كملفات الاختبار. مع ذلك، يمكننا ذكر أسماء ملفات أخرى صراحةً (سيتم شرح ذلك لاحقًا). يتطلب Pytest أن تبدأ أسماء طرق الاختبار بـ تجربه بالعربييتم تجاهل جميع أسماء الطرق الأخرى، حتى لو طلبنا صراحةً تشغيل تلك الطرق.
اطلع على بعض الأمثلة لأسماء ملفات pytest الصحيحة وغير الصحيحة.
test_login.py - valid login_test.py - valid testlogin.py -invalid logintest.py -invalid
ملاحظة: نعم، يمكننا أن نطلب صراحةً من pytest اختيار testlogin.py و logintest.py.
اطلع على بعض الأمثلة على طرق اختبار pytest الصحيحة وغير الصحيحة.
def test_file1_method1(): - valid def testfile1_method1(): - valid def file1_method1(): - invalid
ملاحظة: حتى لو ذكرنا صراحةً file1_method1()، فلن يقوم pytest بتشغيل هذه الطريقة.
تشغيل اختبارات متعددة من ملف معين وملفات متعددة
يوجد حاليًا داخل المجلد study_pytest ملف باسم test_sample1.py. لنفترض أن لدينا عدة ملفات، مثل test_sample2.py و test_sample3.py. لتشغيل جميع الاختبارات من جميع الملفات في المجلد والمجلدات الفرعية، يكفي تشغيل أمر pytest.
py.test
سيؤدي هذا إلى تشغيل جميع أسماء الملفات التي تبدأ بـ test_ وأسماء الملفات التي تنتهي بـ _test في ذلك المجلد والمجلدات الفرعية الموجودة أسفل ذلك المجلد.
لتشغيل الاختبارات من ملف معين فقط، يمكننا استخدام py.test .
py.test test_sample1.py
تشغيل جزء من الاختبار الكامل باستخدام Pytest
أحيانًا لا نرغب في تشغيل مجموعة الاختبارات بأكملها. يسمح لنا Pytest بتشغيل اختبارات محددة. يمكننا القيام بذلك بطريقتين:
- الحبوping أسماء الاختبارات عن طريق مطابقة السلاسل الفرعية.
- الحبوping من الاختبارات بواسطة المؤشرات.
لدينا بالفعل ملف test_sample1.py. أنشئ ملفًا باسم test_sample2.py وأضف إليه الكود التالي.
def test_file2_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) def test_file2_method2(): x=5 y=6 assert x+1 == y,"test failed"
لذا لدينا ما يلي حاليًا.
• test_sample1.py • test_file1_method1() • test_file1_method2() • test_sample2.py • test_file2_method1() • test_file2_method2()
الخيار 1) إجراء الاختبارات عن طريق مطابقة السلاسل الفرعية
هنا، لتشغيل جميع الاختبارات التي تحتوي على method1 في اسمها، علينا تشغيل الأمر أدناه.
py.test -k method1 -v
-k <expression> is used to represent the substring to match
-v increases the verbosity
لذا فإن تشغيل الأمر py.test -k method1 -v سيعطيك النتيجة التالية.
test_sample2.py::test_file2_method1 FAILED
test_sample1.py::test_file1_method1 FAILED
============================================== FAILURES ==============================================
_________________________________________ test_file2_method1 _________________________________________
def test_file2_method1():
x=5
y=6
assert x+1 == y,"test failed"
> assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E AssertionError: test failed because x=5 y=6
E assert 5 == 6
test_sample2.py:5: AssertionError
_________________________________________ test_file1_method1 _________________________________________
@pytest.mark.only
def test_file1_method1():
x=5
y=6
assert x+1 == y,"test failed"
> assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E AssertionError: test failed because x=5 y=6
E assert 5 == 6
test_sample1.py:8: AssertionError
================================= 2 tests deselected by '-kmethod1' ==================================
=============================== 2 failed, 2 deselected in 0.02 seconds ===============================
هنا يمكنك أن ترى، قرب النهاية، تم إلغاء تحديد اختبارين بواسطة "-kmethod2"، وهما test_file1_method2 و test_file2_method2.
جرب الجري بمجموعات مختلفة مثل ما يلي.
py.test -k method -v - will run all the four methods py.test -k methods -v – will not run any test as there is no test name matches the substring 'methods'
الخيار 2) إجراء الاختبارات بواسطة العلامات
يُتيح لنا Pytest تحديد سمات متنوعة لأساليب الاختبار باستخدام علامات pytest، @pytest.mark. لاستخدام هذه العلامات في ملف الاختبار، نحتاج إلى استيراد pytest إلى ملفات الاختبار. سنُطبّق هنا أسماء علامات مختلفة على أساليب الاختبار، ونُشغّل اختبارات مُحددة بناءً على هذه الأسماء. يُمكننا تعريف العلامات لكل اسم اختبار باستخدام ما يلي.
@pytest.mark.<name>.
نُعرّف مجموعتي العلامات set1 و set2 في دوال الاختبار، وسنُشغّل الاختبار باستخدام اسمي هاتين المجموعتين. حدّث ملفات الاختبار باستخدام الكود التالي.
test_sample1.py
import pytest @pytest.mark.set1 def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) @pytest.mark.set2 def test_file1_method2(): x=5 y=6 assert x+1 == y,"test failed"
test_sample2.py
import pytest @pytest.mark.set1 def test_file2_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) @pytest.mark.set1 def test_file2_method2(): x=5 y=6 assert x+1 == y,"test failed"
يمكننا تشغيل الاختبار المحدد باستخدام الأمر أدناه.
py.test -m <name> -m <name> mentions the marker name
شغّل الأمر py.test -m set1. سيؤدي هذا إلى تشغيل الدوال test_file1_method1 و test_file2_method1 و test_file2_method2. أما تشغيل الأمر py.test -m set2 فسيؤدي إلى تشغيل الدالة test_file1_method2.
تشغيل الاختبارات بالتوازي باستخدام Pytest
عادةً، تحتوي مجموعة الاختبارات على ملفات اختبار متعددة ومئات من طرق الاختبار، مما يستغرق وقتًا طويلاً لتنفيذها. يتيح لنا Pytest تشغيل الاختبارات بالتوازي. وللقيام بذلك، نحتاج أولاً إلى تثبيت pytest-xdist عن طريق تشغيل الأمر الموضح أدناه.
pip install pytest-xdist
يمكنك تشغيل الاختبارات الآن باستخدام الأمر التالي.
py.test -n 4
هنا، -ن يُشغّل الاختبارات باستخدام عدة عمال. في الأمر أعلاه، سيكون هناك أربعة عمال لتشغيل الاختبارات.
تركيبات بيتيست
تُستخدم التجهيزات البرمجية عندما نرغب في تشغيل جزء من التعليمات البرمجية قبل كل دالة اختبار. لذا، بدلاً من تكرار نفس التعليمات البرمجية في كل اختبار، نقوم بتعريف التجهيزات البرمجية. عادةً ما تُستخدم التجهيزات البرمجية لتهيئة اتصالات قاعدة البيانات، وتمرير البيانات الأساسية. URLوهكذا. يتم تمييز طريقة ما كأداة اختبار pytest عن طريق وضع علامة عليها بما يلي.
@pytest.fixture
يمكن لطريقة الاختبار استخدام أداة اختبار pytest عن طريق تحديدها كمعامل إدخال. أنشئ ملفًا جديدًا باسم test_basic_fixture.py يحتوي على الكود التالي.
import pytest @pytest.fixture def supply_AA_BB_CC(): aa=25 bb =35 cc=45 return [aa,bb,cc] def test_comparewithAA(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
هنا:
- لدينا وحدة تركيبية باسم supply_AA_BB_CC. تُرجع هذه الطريقة قائمة بثلاث قيم.
- لدينا ثلاث طرق اختبار للمقارنة مع كل قيمة من القيم.
تحتوي كل دالة من دوال الاختبار على وسيط إدخال يتطابق اسمه مع إحدى الأدوات المتاحة. ثم يستدعي Pytest دالة الأداة المناسبة، وتُخزَّن القيم المُعادة في وسيط الإدخال، وهي هنا القائمة [25,35,45]. تُستخدم عناصر القائمة بعد ذلك في دوال الاختبار للمقارنة. الآن، شغّل الاختبار وشاهد النتيجة.
py.test test_basic_fixture
test_basic_fixture.py::test_comparewithAA FAILED
test_basic_fixture.py::test_comparewithBB PASSED
test_basic_fixture.py::test_comparewithCC FAILED
============================================== FAILURES ==============================================
_________________________________________ test_comparewithAA _________________________________________
supply_AA_BB_CC = [25, 35, 45]
def test_comparewithAA(supply_AA_BB_CC):
zz=35
> assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"
E AssertionError: aa and zz comparison failed
E assert 25 == 35
test_basic_fixture.py:10: AssertionError
_________________________________________ test_comparewithCC _________________________________________
supply_AA_BB_CC = [25, 35, 45]
def test_comparewithCC(supply_AA_BB_CC):
zz=35
> assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
E AssertionError: cc and zz comparison failed
E assert 45 == 35
test_basic_fixture.py:16: AssertionError
================================= 2 failed, 1 passed in 0.05 seconds =================================
نجح الاختبار test_comparewithBB، لأن zz=BB=35، وفشل الاختباران المتبقيان.
يقتصر نطاق دالة fixture على ملف الاختبار الذي تم تعريفها فيه. إذا حاولنا الوصول إلى fixture في ملف اختبار آخر، فسنحصل على خطأ يشير إلى fixture. لم يتم العثور على 'supply_AA_BB_CC' بالنسبة لطرق الاختبار في الملفات الأخرى.
لاستخدام نفس الإعداد مع ملفات اختبار متعددة، نُنشئ دوال الإعداد في ملف يُسمى conftest.py. لنرى ذلك من خلال مثال pytest التالي. أنشئ ثلاثة ملفات: conftest.py و test_basic_fixture.py و test_basic_fixture2.py، باستخدام الكود التالي.
conftest.py
import pytest @pytest.fixture def supply_AA_BB_CC(): aa=25 bb =35 cc=45 return [aa,bb,cc]
test_basic_fixture.py
import pytest def test_comparewithAA(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
test_basic_fixture2.py
import pytest def test_comparewithAA_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
سيبحث Pytest عن عنصر الاختبار في ملف الاختبار أولاً، وإذا لم يجده، فسيبحث عنه في ملف conftest.py. شغّل الاختبار باستخدام الأمر py.test -k test_comparewith -v للحصول على النتيجة الموضحة أدناه.
test_basic_fixture.py::test_comparewithAA FAILED test_basic_fixture.py::test_comparewithBB PASSED test_basic_fixture.py::test_comparewithCC FAILED test_basic_fixture2.py::test_comparewithAA_file2 PASSED test_basic_fixture2.py::test_comparewithBB_file2 FAILED test_basic_fixture2.py::test_comparewithCC_file2 FAILED
اختبار Pytest المعلمات
الغرض من استخدام المعاملات في الاختبار هو تشغيله على مجموعات متعددة من الوسائط. يمكننا فعل ذلك باستخدام @pytest.mark.parametrize. سنرى ذلك في مثال pytest التالي. هنا، سنمرر ثلاثة وسائط إلى دالة اختبار. ستقوم هذه الدالة بجمع الوسيطين الأولين ومقارنة النتيجة بالوسيط الثالث. أنشئ ملف الاختبار test_addition.py باستخدام الكود التالي.
import pytest @pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)]) def test_add(input1, input2, output): assert input1+input2 == output,"failed"
تقبل دالة الاختبار هنا ثلاثة وسائط: input1 و input2 و output. تقوم الدالة بجمع input1 و input2 ومقارنة المجموع مع output. لنُجرِ الاختبار باستخدام الأمر py.test -k test_add -v ونرى النتيجة.
test_addition.py::test_add[5-5-10] PASSED
test_addition.py::test_add[3-5-12] FAILED
============================================== FAILURES ==============================================
__________________________________________ test_add[3-5-12] __________________________________________
input1 = 3, input2 = 5, output = 12
@pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)])
def test_add(input1, input2, output):
> assert input1+input2 == output,"failed"
E AssertionError: failed
E assert (3 + 5) == 12
test_addition.py:5: AssertionError
يمكنك أن ترى أن الاختبارات قد أجريت مرتين، إحداهما للتحقق من أن 5+5 ==10 والأخرى للتحقق من أن 3+5 ==12.
test_addition.py::test_add[5-5-10] تم اجتيازه
test_addition.py::test_add[3-5-12] فشل
اختبارات Pytest Xfail و Skip
ستكون هناك بعض الحالات التي لا نرغب فيها بتنفيذ اختبار، أو حالة اختبار لا يكون ذلك ذا صلة في وقت معين. في هذه الحالات، لدينا خيار إما إلغاء الاختبار أو تخطي الاختبارات. سيتم تنفيذ الاختبار الذي تم إلغاؤه، لكنه لن يُحتسب ضمن الاختبارات الفاشلة أو الناجحة. لن يكون هناك أي tracيتم عرض رسالة خطأ في حال فشل الاختبار. يمكننا استخدام خاصية xfail لاختبارات الاختبار باستخدام @pytest.mark.xfail. تخطيping يعني وجود علامة "-" في خانة "الاختبار" أن الاختبار لن يُنفذ. يمكننا تخطي الاختبارات باستخدام @pytest.mark.skip. عدّل ملف test_addition.py باستخدام الكود التالي.
import pytest @pytest.mark.skip def test_add_1(): assert 100+200 == 400,"failed" @pytest.mark.skip def test_add_2(): assert 100+200 == 300,"failed" @pytest.mark.xfail def test_add_3(): assert 15+13 == 28,"failed" @pytest.mark.xfail def test_add_4(): assert 15+13 == 100,"failed" def test_add_5(): assert 3+2 == 5,"failed" def test_add_6(): assert 3+2 == 6,"failed"
هنا:
- تم تخطي test_add_1 وtest_add_2 ولن يتم تنفيذهما.
- تم تصنيف الاختبارين test_add_3 و test_add_4 على أنهما فشلا. سيتم تنفيذ هذين الاختبارين وسيكونان جزءًا من اختبارات الفشل (xfailed) أو اختبارات النجاح (xpassed). لن يكون هناك أي tracاسترداد الأموال في حالة الفشل.
- سيتم تنفيذ الاختبارين test_add_5 و test_add_6، وسيُبلغ الاختبار test_add_6 عن فشل العملية. traceback while test_add_5 pass.
قم بتنفيذ الاختبار باستخدام الأمر py.test test_addition.py -v وشاهد النتيجة.
test_addition.py::test_add_1 SKIPPED
test_addition.py::test_add_2 SKIPPED
test_addition.py::test_add_3 XPASS
test_addition.py::test_add_4 xfail
test_addition.py::test_add_5 PASSED
test_addition.py::test_add_6 FAILED
============================================== FAILURES ==============================================
_____________________________________________ test_add_6 _____________________________________________
def test_add_6():
> assert 3+2 == 6,"failed"
E AssertionError: failed
E assert (3 + 2) == 6
test_addition.py:24: AssertionError
================ 1 failed, 1 passed, 2 skipped, 1 xfailed, 1 xpassed in 0.07 seconds =================
النتائج بتنسيق XML
يمكننا إنشاء نتائج الاختبار بصيغة XML، والتي يمكننا إرسالها إلى خوادم التكامل المستمر لمزيد من المعالجة. يتم ذلك باستخدام الأمر `py.test test_sample1.py -v –junitxml=”result.xml”.` سيسجل الملف `result.xml` نتيجة تنفيذ الاختبار. تجد أدناه مثالاً على ملف `result.xml`.
<?xml version="1.0" encoding="UTF-8"?> <testsuite errors="0" failures="1" name="pytest" skips="0" tests="2" time="0.046"> <testcase classname="test_sample1" file="test_sample1.py" line="3" name="test_file1_method1" time="0.001384973526"> <failure message="AssertionError:test failed because x=5 y=6 assert 5 ==6"> @pytest.mark.set1 def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" > assert x == y,"test failed because x=" + str(x) + " y=" + str(y) E AssertionError: test failed because x=5 y=6 E assert 5 == 6 test_sample1.py:9: AssertionError </failure> </testcase> <testcase classname="test_sample1" file="test_sample1.py" line="10" name="test_file1_method2" time="0.000830173492432" /> </testsuite>
من نرى اختبارين، فشل أحدهما. أسفل ذلك، يمكنك الاطلاع على تفاصيل كل اختبار تم تنفيذه. علامة.
إطار عمل Pytest لاختبار واجهة برمجة التطبيقات (API).
سنقوم الآن بإنشاء إطار عمل pytest صغير لاختبار واجهة برمجة التطبيقات (API). واجهة برمجة التطبيقات المستخدمة هنا مجانية من reqres.inيوفر هذا الموقع الإلكتروني واجهة برمجة تطبيقات قابلة للاختبار فقط، ولا يخزن بياناتنا. سنكتب هنا بعض الاختبارات لما يلي:
- قائمة ببعض المستخدمين.
- تسجيل الدخول باستخدام حسابات المستخدمين.
أنشئ الملفات التالية باستخدام الكود المُعطى. أولًا، يحتوي ملف conftest.py على مُلحق يُوفّر الأساس. URL لجميع طرق الاختبار.
import pytest @pytest.fixture def supply_url(): return "https://reqres.in/api"
بعد ذلك، يحتوي الملف test_list_user.py على طرق الاختبار لعرض قائمة المستخدمين الصالحين وغير الصالحين.
- تقوم الدالة test_list_valid_user باختبار جلب بيانات المستخدم الصالحة والتحقق من الاستجابة.
- تقوم الدالة test_list_invaliduser باختبار جلب بيانات المستخدم غير الصالحة والتحقق من الاستجابة.
import pytest import requests import json @pytest.mark.parametrize("userid, firstname",[(1,"George"),(2,"Janet")]) def test_list_valid_user(supply_url,userid,firstname): url = supply_url + "/users/" + str(userid) resp = requests.get(url) j = json.loads(resp.text) assert resp.status_code == 200, resp.text assert j['data']['id'] == userid, resp.text assert j['data']['first_name'] == firstname, resp.text def test_list_invaliduser(supply_url): url = supply_url + "/users/50" resp = requests.get(url) assert resp.status_code == 404, resp.text
ثم، يحتوي ملف test_login_user.py على طرق الاختبار لاختبار وظيفة تسجيل الدخول.
- تقوم الدالة test_login_valid باختبار محاولة تسجيل الدخول الصحيحة باستخدام البريد الإلكتروني وكلمة المرور.
- يختبر الأمر test_login_no_password محاولة تسجيل الدخول غير الصحيحة بدون إدخال كلمة مرور.
- يختبر الأمر test_login_no_email محاولة تسجيل الدخول غير الصالحة بدون إرسال بريد إلكتروني.
import pytest import requests import json def test_login_valid(supply_url): url = supply_url + "/login/" data = {'email':'test@test.com','password':'something'} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 200, resp.text assert j['token'] == "QpwL5tke4Pnpja7X", resp.text def test_login_no_password(supply_url): url = supply_url + "/login/" data = {'email':'test@test.com'} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 400, resp.text assert j['error'] == "Missing password", resp.text def test_login_no_email(supply_url): url = supply_url + "/login/" data = {} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 400, resp.text assert j['error'] == "Missing email or username", resp.text
قم بتشغيل الاختبار باستخدام py.test -v وشاهد النتيجة كما يلي.
test_list_user.py::test_list_valid_user[1-George] PASSED test_list_user.py::test_list_valid_user[2-Janet] PASSED test_list_user.py::test_list_invaliduser PASSED test_login_user.py::test_login_valid PASSED test_login_user.py::test_login_no_password PASSED test_login_user.py::test_login_no_email PASSED
قم بتحديث الاختبارات وجرّب مخرجات متنوعة.




