طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 245 · ضمان جودة تطبيقات الويب
الدرس 14 · الوحدة 7: أدوات اختبار البرمجيات

الأدوات الصناعية: JUnit و PHPUnit و NUnit

إطارٌ لكل لغة، ومبدأٌ واحد يجمعها: كيف تقرأ أيّ اختبارٍ مهما كانت لغته؟ ⏱ نحو 40 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تعرف أطر اختبار الوحدة لكل لغة.
  • تقرأ اختبارًا بأيّ لغة من عائلة xUnit.
  • تطبّق نمط AAA.
  • تدرك أن المبدأ واحد عبر اللغات.

١الفكرة واحدة، اللغة تختلف

تعلّمت الاختبار ببايثون. لكنّ تطبيقات الويب تُكتَب بلغاتٍ شتّى، ولكلٍّ إطار اختبار وحدةٍ من عائلة xUnit نفسها — المصطلحات نفسها (TestCase، assert، setUp)، والصياغة تختلف:

اللغةإطار اختبار الوحدةيُستخدم في
JavaJUnitالواجهات الخلفية بـ Spring
PHPPHPUnitتطبيقات Laravel و WordPress
C# / .NETNUnit / xUnitخوادم ASP.NET
JavaScriptJestالواجهات والـ Node
Pythonunittest / PyTestDjango و Flask

مَن فهم المبدأ ببايثون يقرأ أيّها بسهولة: assertEqual هي assertEquals هي expect(...).toBe. تتعلّم الفكرة مرّة، وتطبّقها بأيّ لغة.

٢الاختبار نفسه بثلاث لغات

اختبار دالة جمعٍ بسيطة. لاحظ تطابق البنية: ترتيب-تنفيذ-تأكيد (Arrange-Act-Assert):

// JUnit — Java
public class CalcTest { @Test public void testAdd() { assertEquals(5, Calc.add(2, 3)); } }
// PHPUnit — PHP
class CalcTest extends TestCase { public function testAdd() { $this->assertEquals(5, Calc::add(2, 3)); } }
main.py
import unittestdef add(a, b): return a + b class CalcTest(unittest.TestCase):    def test_add(self):        self.assertEqual(add(2, 3), 5) import sysunittest.main(argv=[""], exit=False,    testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
Shell×
>>> %Run main.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
NO TESTS RAN
>>>

ثلاث لغات، بنيةٌ واحدة. الوحيد الذي يعمل هنا هو بايثون (في متصفحك)، لكنك الآن تقرأ الثلاثة.

٣نمط AAA: ترتيب، تنفيذ، تأكيد

كل اختبارٍ جيّد يتبع ثلاث خطوات واضحة، مهما كانت اللغة:

الخطوةالمعنىمثال
Arrange ترتيبجهّز المدخلات والبيئةcart = Cart()
Act تنفيذاستدعِ ما تختبرهcart.add("x")
Assert تأكيدتحقّق من النتيجةassertEqual(cart.total(), 1)

توقّع وتحقّق

إطار اختبار الوحدة في PHP:

إطار اختبار الوحدة في Java:

عائلة أطر اختبار الوحدة تسمّى:

نمط AAA يعني:

الخلاصة

تحدٍّ برمجي: طبّق AAA

متوسط

اكتب اختبار unittest لدالة join_name متّبعًا نمط AAA بوضوح (ترتيب ثم تنفيذ ثم تأكيد)، ثم شغّله. اختبر join_name("سعود","الحربي")=="سعود الحربي".

المطلوب:
  • رتّب المدخلات، ثم استدعِ الدالة، ثم أكّد النتيجة.
  • شغّل بالمُشغّل المعطى.

ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:

main.py
import unittestdef join_name(first, last):    return first + " " + last# اكتب اختبارًا بنمط AAA ثم شغّلهimport sys
المطلوب×
----------------------------------------------------------------------
Ran 0 tests in 0.000s
NO TESTS RAN
💡 تلميح 1
رتّب: first, last = ... ثم نفّذ: result = join_name(...).
💡 تلميح 2
أكّد: self.assertEqual(result, "سعود الحربي").

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

main.py
import unittestdef join_name(first, last):    return first + " " + lastclass TestJoin(unittest.TestCase):    def test_full_name(self):        first, last = "سعود", "الحربي"      # Arrange        result = join_name(first, last)       # Act        self.assertEqual(result, "سعود الحربي")  # Assertimport sysrunner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)unittest.main(argv=[""], exit=False, testRunner=runner)
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس