تأملات في TDD. لماذا لم يتم الاعتراف بهذه المنهجية على نطاق واسع

مرحبا يا هبر!

لفترة طويلة وبالفشل تقريبًا ، كنا نبحث عن رأس مشرق يريد الإطاحة بالسيد كينت بيك في السوق - أي أننا نبحث عن شخص مستعد لكتابة كتاب عن TDD بالنسبة لنا. مع أمثلة حقيقية ، قصة عن المخاريط والإنجازات الخاصة بك. هناك عدد قليل جدًا من الكتب حول هذا الموضوع ، ولن تجادل في الكلاسيكيات ... ربما لهذا السبب لم نلتقي بهذا الرأس حتى الآن.

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



هذه ليست مقدمة للتطوير من خلال الاختبار. هنا سأقدم أفكاري الخاصة حول إعادة تشغيل هذا النظام والتحدث عن الصعوبات العملية لاختبار الوحدة.

المبرمج الأسطوري كينت بيك هو مؤلف منهجية TDD (التطوير من خلال الاختبار) بمعناه الحديث. ساهم كينت أيضًا ، جنبًا إلى جنب مع إريك جاما ، في إنشاء JUnit ، وهو إطار اختبار مستخدم على نطاق واسع.

في كتابه " شرح XP " (الإصدار الثاني) ، يصف كينت كيفية تكوين المبادئ عند تقاطع القيم والممارسات . إذا قمت ببناء قائمة بالمفاهيم واستبدلتهم بصيغة معينة ، فستحصل على تحول.

[KISS, Quality, YAGNI, ...] + [Testing, Specs, ...] == [TDD, ...] 

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

TDD هو مبدأ وانضباط يتم الالتزام به في مجتمع XP. هذا الانضباط عمره 19 عامًا بالفعل.

في هذه المقالة سوف أشارك رأيي حول كيفية تمكن TDD من الاندماج. ثم سأشارك الملاحظات الشخصية المثيرة للاهتمام التي ظهرت خلال جلسة TDD الخاصة بي. أخيرًا ، سأحاول شرح سبب عدم إصابة TDD بالصعوبة التي بدت عليها. دعنا نذهب.

TDD والبحوث والاحتراف

على مدى السنوات ال 19 الماضية ، كان الانضباط في TDD موضوع جدل في مجتمع البرمجة.
السؤال الأول الذي يطرحه عليك المحلل المحترف هو "ما هي نسبة المطورين الذين يستخدمون TDD اليوم؟" إذا سألت صديق روبرت مارتن (العم بوب) وصديق لكينت بيك حول هذا الموضوع ، فإن الإجابة ستكون "100٪".

Just Uncle Bob متأكد من أنه من المستحيل أن تعتبر نفسك محترفًا إذا لم تمارس التطوير من خلال الاختبار .

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

ومع ذلك ، لا يسأل أحد السؤال التالي: "بعد كل شيء ، الممارسة تعني" الاستخدام بوعي "- ولكن لا يسمح بالحكم على النسبة المئوية ، أليس كذلك؟" في رأيي الشخصي ، لم يتعامل معظم المبرمجين مع TDD حتى لأي فترة رمزية.

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

إذا لم نكن نعرف عدد الشركات التي تمارس TDD ، فإن السؤال التالي ينشأ: "ما مدى فعالية TDD ، بناءً على مزاياها القابلة للقياس"؟
سيكون من دواعي سرورك أنه تم إجراء عدد من الدراسات على مر السنين تؤكد فعالية TDD. من بينها تقارير موثوقة بالتأكيد من Microsoft و IBM وجامعة نورث كارولينا وجامعة هلسنكي .



رسم تعبيري مأخوذ من تقرير من جامعة هلسنكي.

إلى حد ما ، تثبت هذه التقارير أنه يمكن تقليل كثافة الخطأ بنسبة 40-60٪ ، الأمر الذي يتطلب المزيد من العمل ؛ يزيد وقت التشغيل بنسبة 15-35٪. هذه الأرقام بدأت بالفعل في تتبعها في الكتب والمنهجيات الصناعية الجديدة ، ولا سيما في مجتمع DevOps.

للإجابة جزئياً على هذه الأسئلة ، ننتقل إلى السؤال الأخير: "ما الذي يمكنني الاعتماد عليه عندما أبدأ في ممارسة TDD؟" للإجابة على ذلك ، صاغت ملاحظاتي الشخصية لـ TDD. دعنا ننتقل إليهم.

1. يتطلب TDD نهج شفهي

عند ممارسة TDD ، نبدأ في مواجهة ظاهرة "تعيين الهدف". ببساطة ، تعد المشاريع الموجزة مثل إعداد اختبارات فاشلة وناجحة تحديًا فكريًا خطيرًا للمطور. يجب على المطور أن يوضح بوضوح: "أعتقد أن هذا الاختبار سينجح" و "أعتقد أن هذا الاختبار سيفشل" أو "لست متأكدًا ، دعني أفكر بعد تجربة هذا النهج".

أصبح IDE للمطور تلك البطة المطاطية التي تتوسل للتحدث معها بنشاط. كحد أدنى ، في شركات TDD ، يجب أن تدمج المحادثات من هذا النوع في ضجة مستمرة.

فكر أولاً - ثم اتخذ خطوتك التالية (أو الخطوات).

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

2. مضخات TDD ذاكرة المحرك

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

احصل على ورقة الغش بمثل هذه الاختصارات. احصل على أقصى استفادة من اختصارات لوحة المفاتيح في IDE لجعل الحلقات فعالة. ثم استمر في البحث.

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

3. يتطلب TDD القليل على الأقل من التفكير في أفعالهم مقدما

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

بينما تجلس في العمل وتنتهي بـ "اجلس" ​​آخر - حاول أيضًا جعل طقوس الخروج من هذا. فكر واذكر أولاً. العب معها. سرد المزيد. ثم تابع ، افكر. احتفل. كرر عدة مرات. ثم فكر مرة أخرى وتوقف.

كن حازمًا بشأن العمل. تتبع ما تم بالفعل - حدد المربعات. لا تطوى أبدًا حتى يكون هناك واحد على الأقل. فكر!

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

 //   // "" ->   // "a" ->   // "aa" ->  // "racecar" ->  // "Racecar" ->  //   //    

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

4. يعتمد TDD على التواصل مع الزملاء

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

يمكن أن يؤدي التمثيل بدون TDD إلى عمليات تنفيذ معقدة للغاية. العمل بأسلوب TDD ، ولكن بدون تفكير ، بدون قائمة ، لا يقل خطورة.

إذا رأيت أن هناك فجوات في قائمة الاختبار ، قف واقول بصوت عالٍ.

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

5. يتطلب TDD معمارية تكرارية

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

بالطبع ، بناء عمارة على أساس الاختبارات أمر غير منطقي. وافق العم بوب نفسه مع خبراء آخرين على أن ذلك لم يكن جيدًا. مطلوب خريطة أكثر شمولاً ، ولكنها ليست بعيدة جدًا عن قوائم الاختبارات التي طورتها "في الميدان".

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

أنشئ خريطة أكبر للمؤسسة بأكملها. المساعدة على رؤية الأشياء قليلاً في المنظور. تأكد من أنك أنت والفريق تتحرك في نفس الدورة.

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

6. يكشف TDD عن هشاشة اختبارات الوحدة والتدهور في التنفيذ

اختبارات الوحدة لها ميزة واحدة ممتعة ، و TDD يمنحها بالكامل. لا يسمحون بإثبات صحتها. عملت EV Dijkstra على هذه المشكلة وناقشت كيف يمكن إثبات الرياضيات في حالتنا التي من شأنها سد هذه الفجوة.

على سبيل المثال ، في المثال التالي ، يتم حل جميع الاختبارات المتعلقة بمتلازمة افتراضية ناقصة تمليها منطق الأعمال. تم تطوير مثال باستخدام منهجية TDD.

 //    @Test fun `Given "", then it does not validate`() { "".validate().shouldBeFalse() } @Test fun `Given "a", then it does not validate`() { "a".validate().shouldBeFalse() } @Test fun `Given "aa", then it validates`() { "aa".validate().shouldBeTrue() } @Test fun `Given "abba", then it validates`() { "abba".validate().shouldBeTrue() } @Test fun `Given "racecar", then it validates`() { "racecar".validate().shouldBeTrue() } @Test fun `Given "Racecar", then it validates`() { "Racecar".validate().shouldBeTrue() } 

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

 //   ,      fun String.validate() = if (isEmpty() || length == 1) false else toLowerCase() == toLowerCase().reversed() //   ,    fun String.validate() = length > 1 length > 1 

length > 1 يمكن أن يسمى التنفيذ المنحل . يكفي حل المهمة ، ولكن في حد ذاتها لا تبلغ عن أي مشكلة نحاول حلها.

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

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

TDD لها فوائدها ، لكن هذه المنهجية يمكن أن تصرفنا عن بناء قلاع رملية غير ضرورية. نعم ، هذا قيد ، ولكن بفضله ، يمكنك التحرك بشكل أسرع وأكثر موثوقية. ربما هذا ما كان يفكر به العم بوب عند وصف ما يعنيه ، من وجهة نظره ، أن تكون محترفًا .

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

7. يوضح TDD الحلقة العكسية لبيانات الاختبار

خذ خطوة أخرى. لفهم الظاهرتين التاليتين ، ندرس الأحداث المتكررة الغريبة. للبدء ، دعنا نلقي نظرة سريعة على FizzBuzz. هنا قائمة الاختبارات لدينا.

 //    9  15. [OK] //  ,  3,  Fizz  . // ... 

ذهبنا بضع خطوات إلى الأمام. الآن فشل اختبارنا.

 @Test fun `Given numbers, replace those divisible by 3 with "Fizz"`() { val machine = FizzBuzz() assertEquals(machine.print(), "?") } class FizzBuzz { fun print(): String { var output = "" for (i in 9..15) { output += if (i % 3 == 0) { "Fizz " } else "${i} " } return output.trim() } } Expected <Fizz 10 11 Fizz 13 14 Fizz>, actual <?>. 

بطبيعة الحال ، إذا قمنا بتكرار بيانات التوكيد المتوقعة في assertEquals ، فسيتم تحقيق النتيجة المرجوة ، ويتم إجراء الاختبار.

في بعض الأحيان تعطي الاختبارات الفاشلة النتيجة الصحيحة اللازمة لاجتياز الاختبار. لا أعرف ماذا أسمي مثل هذه الأحداث ... ربما اختبار الفودو . عدد المرات التي تصادف فيها رؤية هذا - يعتمد جزئيًا على كسلك وآدابك عند الاختبار ، لكنني لاحظت مثل هذه الأشياء عدة مرات عندما يحاول الشخص الحصول على تنفيذ يعمل بشكل طبيعي مع مجموعات بيانات جاهزة ويمكن التنبؤ بها.

8. يوضح TDD تسلسل التحولات

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

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

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



تسلسل التحولات. يجب أن تسعى دائمًا للحصول على أبسط خيار (في أعلى القائمة).

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

TPP أو تحليل العم بوب ، إذا جاز التعبير ، هي واحدة من أكثر الظواهر المثيرة للاهتمام والتكنولوجية والمثيرة التي تتم ملاحظتها حاليًا.

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

بهذا نختتم قصة ملاحظاتي الأولية. ومع ذلك ، في الجزء الأخير من المقالة ، أود أن أعود إلى السؤال الذي نسينا الإجابة عليه في البداية: "ما هي النسبة المئوية للمبرمجين المحترفين الذين يستخدمون TDD اليوم؟" سأجيب: "أعتقد أن هناك القليل منهم". أود التحقيق في هذا السؤال أدناه ومحاولة شرح السبب.

هل TDD راسخ في الممارسة؟

لسوء الحظ لا. ذاتيًا ، يبدو أن النسبة المئوية لمؤيديها منخفضة ، وأنا أستمر في البحث عن البيانات. تجربتي في التوظيف ، وقيادة الفريق ، والتنمية الذاتية (التي تبهرني) تسمح لي بإبداء الملاحظات التالية.

السبب 1: عدم الاتصال بثقافة الاختبار الحقيقية

يمكنني أن أفترض بشكل معقول أن معظم المطورين لم تتح لهم الفرصة للتعلم والعمل في ثقافة اختبار حقيقية.

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

أولئك الذين كانوا محظوظين لاختبار أنفسهم في ثقافة الاختبار هذه ، على سبيل المثال ، أتيحت لي الفرصة لتقديم مثل هذه الملاحظات. .

2:

TDD, , xUnit Patterns Effective Unit Testing . , -, , , . .

. , . . , , , … .

3:

: , , . , , ; - , – .

4:

, , TDD . , .

, , : « , ». : , « » — .

– .

الخلاصة

XP – , . – , . TDD.

, , . «» , , – , .



XP Explained. , , .

, - .

, – , . , , , .

, , , .

TDD « » , . TDD . TDD .

. TDD , . TDD — , , . , TDD , . , .

 @Test fun `Given software, when we build, then we expect tests`() { build(software) shoudHave tests } 

, TDD – , , . . , , , .

Source: https://habr.com/ru/post/ar427853/


All Articles