في
المقالة حول اختبار الأساليب العامة ، تطرقت إلى اختبار الوحدة لمنطق الصف الخاص. أعتقد أنه سيكون من المفيد إعادة الأطروحة ، لأن الأغلبية ، في رأيي ، أدركت أننا نتحدث عن اختبار الأساليب الخاصة ، على الرغم من أنها كانت تتعلق بالمنطق الخاص. في هذه المقالة أريد توضيح الأطروحة الرئيسية بمثال عملي. تحت القات مثال مع القليل من التحليل.
مثال على الأسهم
لتوضيح المشكلة ، توصلت إلى مثال. تم أخذ فكرته من مشروع حقيقي واحد. من الناحية المثالية ، كما قد يلاحظ شخص ما ، يجب كتابة الفصل بشكل مختلف. ولكن الآن لن يعيد أحد كتابته (أو إعادة البناء) ، لأنه سيكلف هذا الكثير من الوقت لتحرير واختبار ما يعمل. لذلك ، لن تتم الموافقة عليه. في هذه الحالة ، تحتاج إلى تغيير الرمز ويجب أن تكون التغييرات صحيحة. وهكذا ، هنا هو الرمز. يتركز المنطق المهم في أسلوب ProcessMessage. الهدف: تقديم إشارة جديدة لمنطق الأعمال في معالجة الرسائل. هذا العلم له منطق غير تافه.
كيف ستقوم بتطبيق واختبار العلم؟
using System; using System.Threading.Tasks; using System.Threading; using System.Messaging; namespace PublicMethodNottrivialSample { public class MessageProcessorService { private object _lockObject = new object(); private CancellationTokenSource _cancellationSource; private Action _receiveMessage; private int _listenerThreads = 5; public void Start() { lock (_lockObject) { _cancellationSource = new CancellationTokenSource(); Task.Factory.StartNew(() => InitializeReceiveLoop(_cancellationSource.Token), _cancellationSource.Token); } } private void InitializeReceiveLoop(CancellationToken cancellationToken) { _receiveMessage = () => { while (!cancellationToken.IsCancellationRequested) { using (MessageQueueTransaction msgTx = new MessageQueueTransaction()) { try { msgTx.Begin();
يوضح الفصل أن الطريقة العامة الوحيدة هي Start (). يمكنك اختباره إذا قمت بتغيير التوقيع ، ولكن في هذه الحالة ستتغير الواجهة العامة. بالإضافة إلى ذلك ، ستحتاج إلى تغيير العديد من الطرق لإرجاع سلاسل العمليات ثم الانتظار حتى يكتمل في الاختبار.
ولكن ، كما نتذكر ، كان المطلب يتعلق فقط بتنفيذ العلم في عملية معالجة الرسالة ، ولا يعني تغييرًا في تشغيل آلية استقبال الرسائل. لذلك ، بغض النظر عمن يقوم بالتغييرات ، أتوقع أنه سيتم إصلاح طريقة واحدة فقط ، وسوف يرتبط اختبار الوحدة فقط بالمنطق المتغير. لتحقيق ذلك ، يبقى البقاء في إطار المبدأ صعبًا: سيتبين أن الاختبار غير تافه ، الأمر الذي سيترتب عليه إما رفض كتابته ، أو رمز معقد. هذه هي الطريقة التي يبدأ بها الاختبار من خلال الطريقة العامة. ثم يكتب شخص ما عاطفيًا: "TDD وقت طويل" أو "العميل لا يدفع" أو "الاختبارات لا تعمل بشكل جيد".
بشكل عام ، من الضروري اختبار مثل هذا الرمز ، ولكن ليس مع اختبارات الوحدة ، ولكن مع اختبارات التكامل.
"أنت الداما ، أو اذهب"
بالطبع ، من الضروري كتابة اختبار وحدة للمنطق المتغير. أعتقد أن المعضلة ، في هذه الحالة ، هي اختيار الطريقة الأقل تكلفة لكتابة اختبار ، بدلاً من رمز مفيد. أعني هنا حقيقة أنه مهما فعلت: إعادة بيع ديون طريقة عامة أو حل آخر - ستقوم بذلك من أجل كتابة اختبار ، وليس حل المتطلبات من مهمة العميل. في هذه الحالة ، من المستحسن تقييم التكلفة والأثر. بالإضافة إلى الحل أعلاه مع إعادة الهيكلة ، هناك العديد من الحلول البديلة. أحمل كل شيء ، سنناقش أدناه إيجابيات وسلبيات:
- يمكن اختبار الطريقة الخاصة
- يمكن نشر هذه الطريقة للجمهور
- يمكن أن تكون داخلية
- يمكن سحبها إلى فصل منفصل كطريقة عامة
إذا قارنا الطرق الثلاثة الأولى بالحل من خلال الطريقة العامة ، لكن جميعها تتطلب تكاليف عمل أقل (مع الخصوصية ليست حقيقة). أيضا ، كلهم ، في الواقع ، هم نفس الحل ، مع اختلافات أسلوبية طفيفة. لأن سيتم الحصول على النتيجة بأي شكل من الأشكال ، لذلك ، في رأيي ، لا ينبغي أن يعتمد الاختيار لصالح أحد هذه الحلول على القدرات التقنية للغة ، ولكن على ما تريد عرضه للمطورين الآخرين:
- إذا كان من الممكن تشغيل الطريقة من أي مكان في الحل وكانت جزءًا من سلوك الفصل ، فاجعلها عامة واسحبها إلى واجهة الفصل ؛
- إذا كان من الممكن استخدام الطريقة من أي فئة أخرى ، ولكن فقط داخل هذا التجميع ، فقم بتنفيذها داخليًا ؛
- إذا كان يمكن استخدام الطريقة فقط داخل الفئة الرئيسية ، حيث يمكن استدعاؤها من أي طريقة أخرى ، فاجعلها محمية داخليًا .
يمكن جعل الطرق الداخلية مرئية لتجميع الاختبار باستخدام السمة InternalsVisibleTo واستدعاؤها كالمعتاد. هذا النهج يجعل اختبارات الكتابة أسهل ، وستكون النتيجة هي نفسها.
اختبار عملية الرسالة
دعنا نعود إلى المهمة. باتباع النهج أعلاه ، سأقوم ببعض التغييرات:
- سيجعل ProcessMessage عامًا
- ستنشئ طريقة داخلية محمية جديدة لمنطق العلم (مثل GetFlagValue)
- سيكتب اختبارات GetFlagValue لجميع الحالات
- أود أن أكتب اختبارًا لـ ProcessMessage للتأكد من استخدام GetFlagValue بشكل صحيح: يتم تمرير المعلمات بشكل صحيح ويتم استخدامها حقًا
سأوضح أنني لن أكتب اختبارات الوحدة لجميع حالات استخدام GetFlagValue في طريقة ProcessMessage ، بشرط أن اختبرت هذه الحالات في اختبارات وحدة GetFlagValue. في حالة الحالات غير المغطاة يجب إضافتها. في هذه الحالة ، يبقى النهج الرئيسي:
- يتم تغطية جميع الحالات من خلال اختبارات وحدة GetFlagValue
- اختبارات وحدة ProcessMessage تتحقق من استخدام أسلوب العلامة بشكل صحيح
أعتقد أنه وفقًا لذلك ، يمكنك كتابة اختبار وحدة واحد فقط لـ ProcessMessage وعدة اختبارات أخرى لـ GetFlagValue.
شيء من هذا القبيل. آرائكم