---
title: "التحقق المكرر"
type: "test-smell"
slug: "duplicate-assert"
url: "http://localhost:3000/ar/test-smells/duplicate-assert.md"
category: "روائح التحقق"
description: "تتحقق طريقة اختبار واحدة من نفس الشرط أكثر من مرة — بتكرار تحقق متطابق أو إعادة فحص منطق مكافئ — بدلاً من إزالة الفحص الزائد عن الحاجة أو تقسيم الحالات المتميزة إلى اختبارات مركزة خاصة بها."
---
# التحقق المكرر

> تتحقق طريقة اختبار واحدة من نفس الشرط أكثر من مرة — بتكرار تحقق متطابق أو إعادة فحص منطق مكافئ — بدلاً من إزالة الفحص الزائد عن الحاجة أو تقسيم الحالات المتميزة إلى اختبارات مركزة خاصة بها.

## Signs and Symptoms

ترى **نفس التحقق يظهر مرتين** (نفس المطابِق، ونفس الوسائط) في اختبار واحد، أو عدة كتل تحقق منسوخة ومحشوة تختلف فقط في القيم الثابتة وتختبر _نفس_ السلوك مجدداً. العلامات الدالة:

* يظهر سطر تحقق متطابق حرفياً مرتين أو أكثر في جسم الاختبار.
* العديد من استدعاءات `expect(...)`/`assertEquals(...)` التي تختبر نفس الشرط بمدخلات مختلفة، وكلها مكدسة في طريقة واحدة يصف اسمها سيناريو واحداً فقط.
* تحققات متبقية من تصحيح الأخطاء ("دعني أتحقق أيضاً من X") والتي لم يتم تنظيفها أبداً.
* اسم الاختبار (مثل `testXmlSanitizer`) لا يعطي أي تلميح حول أي من فحوصاته الكثيرة قد فشل.

```js
test('sanitizer accepts valid input', () => {
  expect(isValid('plain text')).toBe(true);
  expect(isValid('with spaces')).toBe(true);
  expect(isValid('Fritz-box')).toBe(true);   // "الشرطة صالحة"
  expect(isValid('Fritz-box')).toBe(true);   // <-- تكرار متطابق تماماً، لا يضيف شيئاً
  expect(isValid('<script>')).toBe(false);
});

```

سطر `Fritz-box` المكرر هو المثال النموذجي للتحقق المكرر؛ الرائحة الأوسع هي أن طريقة واحدة تجمع بصمت العديد من الفحوصات لنفس الشرط تحت اسم واحد.

## Reasons for the Problem

**لماذا يحدث ذلك**

* **النسخ واللصق.** يتم تكرار كتلة التحقق وتغيير القيم الثابتة (أو حتى عدم تغيير أي شيء).
* **بقايا تصحيح الأخطاء.** تُترك التحققات الإضافية التي تمت إضافتها لاستكشاف السلوك دون إزالتها.
* **التجميع.** يقوم المطورون باختبار "طريقة واحدة" عن طريق تكديم كل الحالات في اختبار واحد بدلاً من تقسيمها، مما ينتج عنه فحوصات متكررة وشبه متطابقة.

**لماذا يضر ذلك**

* **الثقة الزائفة.** التحقق المكرر والمتطابق تماماً يضيف _صفراً_ من التغطية — فلا يمكن أن يفشل أبداً طالما نجح توأمه — ومع ذلك فإنه يجعل الاختبار يبدو أكثر شمولاً مما هو عليه في الواقع.
* **صعوبة تشخيص الفشل.** عندما تتشارك عدة تحققات متشابهة الشكل في طريقة واحدة، فإن تقرير الفشل يشير إلى الطريقة ككل، وليس إلى المدخل المحدد الذي تسبب في العطل. والأسوأ من ذلك أن الاختبار بالإعدادات الافتراضية يتوقف عند أول تحقق يفشل، لذا لا يتم تشغيل التحققات المكررة اللاحقة أبداً — فتقوم بإصلاح واحد، وتعيد التشغيل، لتصطدم بالتالي (وهذا يتداخل مع _روليت التحقق_).
* **ضعف سهولة القراءة.** لا يمكن للقارئ معرفة ما إذا كان التكرار مقصوداً (حالات متميزة) أم خطأً (تكرار حقيقي)، ويوثق اسم الاختبار شرطاً واحداً فقط من بين شروط متعددة.
* **تكلفة الصيانة.** غير السلوك قيد الاختبار وسيتعين عليك البحث عن كل تحقق مكرر وتحديثه؛ وإذا فاتك أحدها، تصبح مجموعة الاختبارات غير متسقة.

## Treatment

1. **احذف التكرارات المتطابقة تماماً.** إذا كان هناك تحقق متطابق بايت بايت مع تحقق آخر في نفس الاختبار، فقم بإزالته — فهو عبء زائد وليس تغطية.
2. **اجعل الحالات المتكافئة بارامترية (Parameterize).** عندما تكون "التكرارات" هي في الواقع _نفس_ الشرط بمدخلات _مختلفة_، قم بتحويلها إلى جدول أو اختبار بارامتري (`test.each` في Jest/Vitest، أو `@ParameterizedTest` في JUnit 5). يتم الإبلاغ عن كل صف وتسميته بشكل منفصل، مما يسهل تحديد المدخلات المسببة للفشل بدقة.
3. **قسّم الشروط المختلفة تماماً** إلى اختبارات منفصلة، يحمل كل منها اسماً يوضح ما يتحقق منه (مثل `accepts hyphenated host names`، أو `rejects script tags`).
4. **التسمية حسب الغرض.** يجب أن يصف اسم الاختبار سلوكاً واحداً؛ وإذا لم تتمكن من ذلك، فهذه إشارة للتقسيم.

```js
// قبل — تحققات مكررة / مجمعة في اختبار واحد غامض
test('isValid', () => {
  expect(isValid('plain text')).toBe(true);
  expect(isValid('with spaces')).toBe(true);
  expect(isValid('Fritz-box')).toBe(true);
  expect(isValid('Fritz-box')).toBe(true); // مكرر
  expect(isValid('<script>')).toBe(false);
});

// بعد — تحقق واحد، ويتم تسمية كل حالة والإبلاغ عنها بشكل مستقل
test.each([
  ['plain text', true],
  ['with spaces', true],
  ['Fritz-box',  true],   // الشرطة صالحة
  ['<script>',   false],  // يرفض كود الترميز (markup)
])('isValid(%j) === %s', (input, expected) => {
  expect(isValid(input)).toBe(expected);
});

```

لقد اختفى الصف المكرر، وأصبحت المدخلات المتميزة واضحة، ويحدد الفشل الحالة بدقة.
