كيف يمكنني منع اختبارات وحدتي من طلب المعرفة حول التنفيذ الداخلي عند استخدام الكائنات الوهمية؟

StackOverflow https://stackoverflow.com/questions/3448121

سؤال

ما زلت في مراحل التعلم فيما يتعلق باختبار الوحدة وخاصة فيما يتعلق بالسخر (أنا أستخدم باسكالموك و دنيت إطار أعمال). شيء واحد تعثرت عليه الآن هو أنني لم أتمكن من إيجاد طريقة للتغلب على تفاصيل التنفيذ المتشددة للفئة/الواجهة التي تم اختبارها في اختبار الوحدة الخاص بي وهذا مجرد خطأ ...

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

ومع ذلك ، من أجل ضمان تصرف النقطة تمامًا مثل الشيء الحقيقي عند الوصول إليه من قبل الفئة التي تم اختبارها ، يتعين على اختبارات الوحدة الخاصة بي إعداد الكائن الوهمي من خلال تحديد مكالمات الطريقة المتوقعة بشكل صريح وقيم الإرجاع المتوقعة بواسطة الفئة التي تم اختبارها. هذا يعني أنه إذا كان عليّ أن أضطر إلى إجراء تغييرات على واجهة طبقة الوصول أو إلى الطريقة التي تستخدم بها الفئة المختبرة تلك الطبقة واجهه المستخدم من الفصل الذي أنا أختبره في الواقع لم يتغير على الإطلاق. هل هذا شيء سيتعين علي فقط العيش معه عند استخدام السخرية أم أن هناك طريقة أفضل لتصميم الاعتماد على الفصل الذي من شأنه تجنب هذا؟

هل كانت مفيدة؟

المحلول

هل هذا شيء سيتعين علي فقط العيش معه عند استخدام السخرية أم أن هناك طريقة أفضل لتصميم الاعتماد على الفصل الذي من شأنه تجنب هذا؟

في كثير من الأحيان تجبرك في الأوقات (أطر عمل حساسة مثل JMock) على حساب التفاصيل التي لا تتعلق مباشرة بالسلوك الذي تحاول اختبار ولديه الكثير من المكالمات/التبعيات.

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

هذا يعني أنه إذا كان عليّ أن أضطر إلى إجراء تغييرات على واجهة طبقة الوصول أو إلى الطريقة التي تستخدم بها الفئة المختبرة تلك الطبقة التي سيتعين علي أيضًا تغيير اختبارات الوحدة للفئة التي تستخدم هذه الواجهة داخليًا على الرغم من أن الواجهة من الفصل الذي أنا أختبره في الواقع لم يتغير على الإطلاق.

أليس الهدف من كتابة طبقة الوصول المستخرجة لتجنب ذلك؟ بشكل عام ، بعد مبدأ مفتوح/مغلق, ، واجهة من هذا النوع لا ينبغي تغيير ولا ينبغي أن يكسر العقد مع الفصل الذي يستهلكه ، وبالتالي لن يكسر اختبارات وحدتك أيضًا. الآن إذا قمت بتغيير ترتيب مكالمات الطريقة ، أو اضطررت إلى إجراء مكالمات جديدة إلى الطبقة المستخرفة ، فعندئذ ، نعم ، خاصة مع بعض الأطر ، ستنهار توقعاتك الوهمية. هذا مجرد جزء من تكلفة استخدام السخرية ، وهو مقبول تمامًا. لكن الواجهة نفسها ، بشكل عام ، تظل مستقرة.

نصائح أخرى

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

صيح.

التغييرات على واجهة طبقة الوصول أو إلى الطريقة التي تستخدمها الفئة المختبرة تلك الطبقة التي سيتعين علي أيضًا تغيير اختبارات الوحدة

صيح.

على الرغم من أن واجهة الفئة التي أختبرها في الواقع لم تتغير على الإطلاق.

"في الواقع الاختبار"؟ تقصد فئة الواجهة المكشوفة؟ هذا جيّد.

تعني الطريقة التي تستخدم بها فئة "اختبار" (واجهة) طبقة الوصول أنك غيرت الواجهة الداخلية إلى طبقة الوصول. تتطلب تغييرات الواجهة (حتى تلك الداخلية) تغييرات في الاختبار وقد تؤدي إلى الكسر إذا ارتكبت خطأً.

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

ليس من المفترض أن يكون الاختبار "قويًا". من المفترض أن تكون هشة. إذا قمت بإجراء تغيير يغير السلوك الداخلي ، فإن الأشياء تستطيع فترة راحة. إذا كانت اختباراتك قوية جدًا ، فلن يختبروا أي شيء - فسيعملون فقط. وهذا خطأ.

يجب أن تعمل الاختبارات فقط للسبب الصحيح المحدد.

فقط لوضع بعض الأسماء على مثالك ،

  • يقوم RegistryBasedDictionary بتنفيذ قاموس الدور (الواجهة).
  • RegistryBasedDictionary لديه اعتماد على الدور ، الذي تم تنفيذه بواسطة RegistryWinapiWrapper.

أنت مهتم حاليًا باختبار RegistryBasedDictionary. ستؤدي اختبارات الوحدة إلى ضخ التبعية الوهمية لدور التسجيل وستختبر التفاعل المتوقع مع التبعيات.

  • الحيلة هنا لتجنب صيانة الاختبار غير الضرورية هي "حدد بالضبط ما يجب أن يحدث .. وليس أكثر." (من عند كتاب غوس (يجب قراءتها من أجل TDD النكهة السهلية) ، لذلك إذا لم يكن أمر استدعاء طريقة التبعية مهمًا ، فلا تحددها في الاختبار. هذا يجعلك حرة في تغيير ترتيب المكالمات في التنفيذ.)
  • تصميم الأدوار بحيث لا تحتوي على أي تسرب من التطبيقات الفعلية - الحفاظ على الأدوار التنفيذ-Agnostic.

السبب الوحيد لتغيير اختبارات RegistryBasedDictionary ، سيكون تغييرًا في سلوك RegistryBasedDictionary وليس في أي من تبعياته. لذلك إذا كان التفاعل مع تبعياته أو تغيير الأدوار/العقود ، يجب تحديث الاختبارات. هذا هو سعر الاختبارات القائمة على التفاعل التي تحتاج إلى دفعها ، من أجل المرونة للاختبار في عزلة. ولكن في الممارسة العملية ، لا يحدث ذلك في كثير من الأحيان.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top