Transcript for:
ملاحظات حول كورس اختبار البرمجيات باستخدام Pytest

السلام عليكم و أهلا بكم في كورس جديد إن شاء الله حلو و مفيد الكورس بتاع النهاردة مهم جدا و هنتعلم فيه حاجة كتير من المبتدئين بيخفلوا عنها أو ماعرفوش إنها موجودة أصلا الحاجة دي هي التستنج إزاي أختبر الكود بتاع المشروع بتاعي فالأوبجيكتيف بتاع الكورس اللي إنت بتشوفه ده إن إنت تفهم وتعرف تستخدم حاجة اسمها البي تست عشان تعرف تعمل تستنج أو تختبر البيثون كود بتاعك بطريقة فعالة طيب إيه هو التستنج وليه أصلا التستنج حاجة مهمة ببساطة التستنج هو عملية أن أنا أتأكد أن الكود بتاعي بيشتغل بشكل صحيح بيحقق المتطلبات بتاعته وخالي من المشاكل طبعا التستنج بيساعدني أن أنا اكتشف البوكز بدري قبل مطلق الـ software بتاعي لأن الناس تستخدمه ده طبعا مهم جدا عشان الناس ما تاخدش انطباع وحش عن الـ software بتاعي هيوفر علي وقت وفلوس كتير جدا ده بيحسن الكود quality و reliability يعني الاعتمادية بتاعت الكود والجودة بتاعته يسهل علي أن أستطيع في كودي أن أقوم بعمل تغييرات بسهولة بدون أن أقوم بمشاركة شيئاً في شكل البرنامج الحالي أو في وظيفة البرنامج الحالية هذا يسهل أن أزود الإنتاجية للمستخدمين الذين يعملون على البرنامج أو الـ Software لأنهم يركزون على الأشياء المهمة ويكونوا لا يتألمون طوال الوقت أنني قمت بالتغيير هذا سأقوم بمشاركة هنا ولكن لا أعرف أنه يمكن أن يحدث مشاكل وهكذا فهذا طبعاً عندما يكونون متأمنين من هذه الوضع، يتعلمون من ثقةهم ويجعل المشاركين الذين يعملون على المشروع بشكل عام يتركزون في الأشياء المهمة التي يجب أن تركز عليها وبالتالي كل هذا يؤدي إلى تجربة المستخدم في تحسين هذا المستخدم حسناً، سنتعلم ماذا بالأخص في هذا الفيديو أو في هذا الكورس سنتعلم كيفية إستخدام بايتست سنشرح المنظمة أو الهيكل الأساسي لكيفية تصميم التصميم سنتعلم كيفية استخدام الأسرشنز لكي نتعلم كيفية تحديث أو تجربة المستخدمين مثلاً، لدينا فنكتورم يجب أن يعمل بطريقة معينة لذلك نريد تجربة هذا سنعلم شيء يسمى Assertions لكي نفعل هذا سنعلم كيفية تشغيل هذه التست وعند تشغيلها يظهر لنا تقرير سنعلم كيفية قراءة وتفهم تقرير هذا كل التفاصيل التي تحتوي عليها سنتعلم ما هي التفاصيل الأفضل لأنني أسمي ونظم الفايلات والفنكتورم هنتعلم حاجة اسمها لدي مهمة وازاي استخدمها وامتى اصلا محتاج استخدمها وطبعا هنعمل تستنج او هنعمل امثلة كتير عملية على الفونكشنز وعلى الكلاسز هنختبر فونكشنز وحنختبر كلاسز اللي مطلوب منك عشان تفهم الكورس ده مطلوب يكون عندك اساسيات البرمجة مضمون فيها طبعا الأساسيات البرمجة والأووبي وتكون بتعرف تبرمج بلغة بايثون حبيبقولك ان عندنا كورس مدفوع بيعلمك البرمجة من الصفر يركز معك انه هو يبني لك اساس قوي جدا في البرامجة يخليك قادر تتعمك في اي مجال بعد كده ويركز كمان معك بالتحديد ان انت تحترف بايثون تعرف كل تفاصيل لغة بايثون عندنا تمارين ومشاريع بعد كل درس عندنا مجتمع خاص عشان يساعدك طول رحلتك التعليمية ما تحسش ان انت لوحدك تلاقي حد بيجاوب على اسئلتك لو قعت في مشكلة تلاقي حد معاك في هذه المشكلة ما تبقاش تايه كده مع نفسك وخلاص اتأكد ان انت تبص على الرابط الموجود في الوصف وفي اول كومنت حديك خصم 55% وتأكد أنك تتصفح الموقع بالكامل من الأول للآخر تشوف المحتوى كله تشوف أراء الناس تشوف المنهجية وتفهمها كويس وتنزل للآخر عشان قسم الأسئلة ده غالباً بيبقى فيه أسئلة في بالك أنت عايز إجابات لها هتلاقيها موجودة تحت خالص بس كده دي كانت كل حاجة أتمنى إن شاء الله تستفيد من الكورس ده سلام عليكم أنا إسلام ودي قناة كودزيلا خلينا نبدأ مع بعض على طول وعايزين دلوقتي نعمل install لبي تست عشان نعرف نقدر نستخدمه طبعا أنا هنا بستخدم ريبليت، أنت مو مش لازم تستخدم ريبليت، هو ريبليت مجاني بتعمل عليه حساب مجانا وبتختار بايثون وبتبدأ تبرمج معايا ممكن تستخدم فيجيول ستوديو كود، باي تشارم، أين كان اللي أنت بتستخدمه مش هيفرق اللي هيفرق دلوقتي أن أنت تروح لو بتستخدم MacOS تفتح الترمينل، لو بتستخدم Windows تفتح الكماند لاين، لو بتستخدم ريبليت تفتح الشيل عشان عايزين نعمل install لبي تست، عشان نعمل install لبي تست هنكتب pip install بي تست بالشكل ده زي ما بنعمل install لمعظم الحاجات في بايثون الموديولز وكده سنضغط على Enter وعندما يقوم بإنشاءه سوف يجد أنه قد تحقق المطالب ستجد أنه قام بعمل بعض الأشياء السريعة وقال لك أنه قد قام بإنشاءه لكي تتأكد أنه قام بإنشاءه بنجاح ستقول pi test-version سيتكتب لك هنا نسخة من pi test التي تستخدمها أو التي توجد بها طبعا لكي نقوم بغوص في موضوع التست يجب أن يكون لدينا تفعيل نقوم بعمل تفعيل لكي نختبر ونرى أنه يعمل بطريقة صحيحة فلنذهب معاً لنقوم بعمل ملف جديد لو كنت على الكمبيوتر فسوف تقوم بعمل ملف جديد في المشروع الموجود فيه أو المشروع الذي توجد فيه وسوف نسمي هذا الملف معاً سوف نبدأ معاً في هذا الملف بكتابة فنكتون يسمى سوف نقول هذا الفنكتون يأخذ اثنين أداءً وطبعاً سأشرح لك كل شيء في الوقت الثاني مهمة الفونكشن ده ان انا اديله first name اسم اولي و last name اسم عيلة و يطلعهم لي بشكل معين هنشوف الشكل ده مع بعض دلوقتي فخلينا مبدأ نكتب document string نعرف او نوصف بيها الفونكشن ده سنكتب هنا generate a formatted full name يعني أريد أن أخذ first name و last name وأعمل أو أطلع full name اسم كامل formatted منصق بطريقة معينة ما هي الطريقة هذه؟ سأقول لك سنقوم بعمل variable اسمه full name الفريبل هذا عبارة عن f string محطوط جواه first اللي هو الاسم الأولي space بعدين last اللي هو اسم العيلة بالشكل ده وبعدين بكل بساطة أريد أن أعمل return return للfull name ده.title الفونكشن بتاع تايتل بتعمل ايه؟ طبعا لو انت معنا في الكورس المدفوع هتبقى عارف لو مش عارف هتروح على جوجل تبحث لان مهم جدا كمبرمج يكون عندك مهرة البحث هتكتب تايتل فونكشن ام بايثون هيتلعلك على طول هي بتعمل ايه وامثل عليها وكده مش عايز اكون ريخم يعني ولكن البحث مهم ولكن تايتل ببساطة بتاخد اول حرف من كل سترينج بتخليه كابيتل يعني لو عنده مثلا اسم حمادة كفتة بالشكل ده لو ندهت عليه تايتل بالشكل ده فالنتيجة هتكون كالقاتي حمادة كفتة الـH أول حرف من الـString بقى Capital وأول حرف من الـString ده بقى Capital هو كمان فده اللي تايتل بتعمله فأنا هنا الفانكشن بتاعي بكل بساطة بتاخد اسم أولي 2 parameters First وLast بتعملي فورمات للكلام ده بتحطولي في String الاتنين جنب بعض وبعدين بعمل له Return بأن الاسم ده أول حرف من كل اسم فيهم بيكون Capital أو Uppercase طبعا عشان أتأكد أن الفانكشن ده شغال والدنيا كلها تمام هروح في main.py أقول أنا عايز أستخدم الفانكشن ده فعايز أقول إيه From name underscore function بالشكل ده الملف بتاعي اللي أنا كتبت فيه الفونكشن عايز أعمل import للفونكشن اللي هو اسمه get formatted underscore name هنعمل برنامج بسيط سريع جدا يستخدم الفونكشن ده فعايزين هنا نقول print بالشكل ده ونفتح string ونقول له enter حرف الكيو any time to quit لو دخلت حرف الكيو البرنامج هيقفل طفين البرنامج ده هنكتبه هما بعد ما تستعجلش هنقول while true هنعمل while loop بـ Condition True لكي يستمر بعمل البرنامج طوال الوقت حتى يضغط الـ user بـ Q عندما يضغط الـ Q سأقوم بعمل Break سأخرج من الـ while loop فالبرنامج ينتهي ما الذي يفعل هذا البرنامج؟ لدي variable اسمه first وفيه فنكشن input أريد أن أخذ مدخل من الـ user وأقول له please give me a first name أعطيني اسم أولي ثم أريد أن أرى if first إذا كان هذا المدخل هو حرف الـ Q بهذا الشكل وطبعا هنا equal equal أريد أن أقوم بعمل Break عايز أخرج من الـ loop عشان البرنامج ينتهي طيب غير كده خليني أعمل copy paste للكلام ده عشان نعمل نفس الكلام للـ last عايز أعمل متغير اسمه last وقوله please give me a last name وهنا أسأل if last equal q برضو حعمل break طب بعد ما خدت الـ first name والـ last name عايز أعمل إيه؟ عايز بقى أستخدم الفنكشن اللي أنا عملته import ده فحاجي هنا أقول formatted هعمل variable كده اسمه formatted underscore name وأقول ده بيساوي إيه؟ بيساوي get formatted name وحتديله الـ first اللي أنا خدت فيها مدخل والـ last اللي أنا خدت فيها مدخل كل ده أنا لسه جوه الـ while loop وبعد كده هعمل print بقى للكلام ده f-string اللي عزيز كده وممكن أعمل backslash t عشان أعمل tab وأقول الـ formatted name وأفتح curly braces وأحط جوهها الـ variable اللي أنا لسه عامله ده اللي هو formatted name نروح مع بعض على الـ console عشان نجرب الكلام اللي عزيز ده ونعمل run وأنا جوه main.py هيقول لي please give me a first name فحقول له مثلاً حمادة بالشكل ده please give me a last name حقول له كفتة فسيقول لي فورماتد نيم حمادة كفتة يبقى زي الفل خد حمادة وكفتة حطهم جنب بعض زي ما أنا كنت متوقع وأول حرف من كل اسم أو من كل سترينج بقى كابيتل يبقى الماثود دي أو الفونكشن دي بتشتغل بالشكل اللي أنا متوقعه وبتشتغل بشكل سليم طبعا كل ما حدديله حاجة هنا إسلام مثلا محفوظ بالشكل ده هيقول لي إسلام محفوظ وحيرجعهم طبعا لما دوس كيو بالشكل ده البرنامج بتاعي خلاص هينتهي ويقفل عشان لما بعمل كيو يقوم بعمل توقف ويخرج من اللوب فبعد اللوب لا يوجد شيء يتم تنفيذه فهذا يعني ان البرنامج انتهى فنكشن بسيط جدا وبرنامج بسيط جدا اي شخص تعلم اساسيات بسيطة جدا مثل انك تطبع شيء انك تستخدم لووب انك تستخدم if condition انك تعمل فنكشن يستطيع ان يعمل شيء مثل هذا بمنتهى البساطة لا يوجد اي تعقيد في الموضوع ما اريد ان افعله الان ان افرد ان اردت ان اعمل تعديل في هذا الفنكشن وانه اخذت اولا وآخرا واسم الأسفل ايضا يعني تأخذ برامتر ثاني أنني أريد اسم أولي، اسم وسطي، واسم العيلة وبقيت هنا أعرض الأول، ثم الأدل، ثم الأخير، تمام؟ لو أنا غيرت الفنكشن بالشكل هذا، وعملت فيه هذا التعديل، وقمت هنا دعني أمسح ما موجود في هذا المنطقة، وقمت بعمل تحديد وقلت مثلاً حمادة، ثم كفتة، ستجد أن الأمر ضرب، حصل خطأ لماذا؟ لأنني عدلت الفنكشن، غيرت في الطريقة التي يعمل بها الفنكشن طب انا عايز اعمل التعديلات دي من غير مبوز الأساس بتاع الفونكشن عشان لو عندي كود موجود من قبل كده في البرنامج اللي أنا بكتبه بيستخدم الفونكشن في حالته الأولية أو الفونكشن قبل ما يحصل عليه تعديل مش عايز الكود ده يضرب لأن أنا كده هخلق مشاكل لو أنا بتخيل بقى الموضوع على سكيل أكبر أو على حجم أكبر مشروع كبير فونكشن بيستخدم في حتة كتير جدا رحت أنا غيرت فيه حاجة رح ضرب لي بقى إيه في كل الحتة دي فدي حاجة أنا عايز أتجنبها وهنا بقى ييجي دور التست أو دور الاختبارات كيف يمكنني القيام بهذا وكيف يمكنني التغيير وأكون متأكد أن كل شيء يعمل بشكل سليم وليس هناك شيء ضربت لذلك دعونا نذهب الآن ونعود للميثود كما كانت بدون أي تغيير وطبعاً كذا ستعمل بشكل عادي جداً ولكن أريد أن أتحدث سريعاً عن شيء يسمى unit test ما هو unit test؟ لكي أعرف أنه بشكل عام التستنج يوجد اتجاهات كثيرة أو يوجد أشياء كثيرة فكرة unit test لو سنترجمها هو اختبار الوحدة معناه ما؟ يعني أنني أختبر جزء معين من الفنكشن أرى إنه يعمل بطريقة صحيحة أم لا هل يرجع أو يخرج المطلوب منه أو ما أنا متوقعه أم لا هذا هو unit testing جزء معين من الفنكشن عندما يكون هناك كثير من unit test هذا يكون شيء يسمى test case ولو كنت قد قمت بعمل unit functions كافية أو كنت قمت بعمل كثير من unit functions بحسب أنني أختبر كل أجزاء الفنكشن هذا يعني أنني قمت بعمل test case full coverage test case تغطي الفنكشن كله تأكدني أن كل أجزاء الـ Function تعمل بشكل صحيح حتى نرى الموضوع بشكل عملي ونكون متخيلينه دعونا نكتب أول unit test عندنا أول اختبار للوحدة عندنا وحتى نفعل ذلك سنقوم بعمل ملف جديد سنسمي هذا الملف test underscore name underscore function dot pi اسم معبر جداً لماذا؟ لأنني أقوم بعمل test واختبر الملف الذي يسمى name function صح؟ لذلك سميت هذا الملف test underscore name function أول شيء أريده هو أن أستدعي الـ function التي سأقوم بعملها test فأريد أن أقول from name from name underscore function.py آسف من غير.py أريد أن أقوم بعمل import get underscore formatted name أقوم بعمل import للـ function التي أعرفها هنا لكي أستطيع أن أقوم بعمل test لها و أستطيع أن أختبرها في هذا الملف سأكتب الآن الـ function في هذا الاختبار ثم سأشرح كل شيء فيه فمبدئياً سأقوم بعمل definition وسأسميه test underscore first underscore last name بالشكل ده وخليكوا فاكرين نحن هنا بنعمل ايه حاجة اسمها unit test بعمل function تختبر جزء معين من الفانكشن اللي انا بحاول اختبره ده تختبر جزئية معينة فيه تشوف هي شغالة صح ولا لا فده كده اول unit test عندي ماشي سميته ايه test underscore first underscore last underscore name هعمل document string اوصف فيه التست فانكشن ده المفروض يكون بيعمل ايه فانا هنا مثلا عايز اقول do names like حمادة كفتة work هل هذا مخرج ممكن اتوقعه من الفنكشن اللي انا باختبره وحاجة هنا اعمل variable اسمه formattedName وانده عليه الفنكشن اقول get underscore formatted underscore name وادلو values افتراضية قيم افتراضية اكني هنا اديلو ايه اكني اديلو first والlast زي ما عملت هنا كده مشان هنا عملت formattedName ونداهت على الفنكشن وادتو first والlast اللي كنت اواخدهم من الامبوت صح اللي كنت اواخدهم من البرنامج اللي انا عملته انا عايز اعمل حاجة مشابهة هنا فهنا انا هديله قيمة افتراضية هقول ان انا مثلا هديله حمادة بالشكل ده وهديله كفتة بالشكل ده زي ما بالضبط دخلت في البرنامج الاساسي بتاعي مش لازم بالضبط ممكن اي حاجة تانية بس بما ان انا هنا بتوقع مخرج بشكل معين فانا عايز اديله المدخلات بنفس الحاجة اللي اتطلعلي المفروض الشكل ده كان ممكن يبقى دي اسمها مثلا اشرف بطيخة اشرف بطيخة ساعتها كنت أنا هكتب هنا كده أشرف بطيخة بالشكل ده فهي مش فرقة المهم أن أنا عايز أجي دلوقتي أعمل بقى حاجة اسمها assertion assert دي كيوورد جديدة هنشرحها دلوقتي أقول هل الformatted name ده الformatted name الvariable ده اللي هيرجع فيه القيمة اللي هترجع فيه بعد ما الفونكشن ده يتنفذ هيكون كالأتي هيكون بالشكل ده أشرف بطيخة كده يعني إيه assert يعني أنا بفترض وهنا لازم تبقى equal equal دي زي conditional statement حاجة يا هترجع true يا هترجع false ودايما الassertions بتكون كده حاجة لازم هترجع true أو false أنا بعمل افتراض عايز أشوف هو صحيح ولا غلط عشان على هذا الأساس هعرف التست نجح ولا لا الاختبار بتاع الفونكشن بتاعي نجح ولا لا في هذه الحالة أنا بختبر إيه بختبر get formatted name لما هياخد قيم بالشكل ده هل النتيجة اللي هتطلع هتكون بالشكل ده هل هيتخزن هنا هنا سيكون هذا المستخدم بعد استخدام الفنكشن هذا هو أول شيء سنرى معاً الآن ملحوظة أريد أن أقولها لماذا تسمينا الفنكشن بهذا الشكل؟ مبدئياً لازم تعرف حاجة أي تست فونكشن وإنت بتستخدم Pytest لازم تسميه بالشكل ده test underscore بعدين مش مهم اللي باقي يعني الباقي إنت ممكن تفتي فيه براحتك ولكن إحنا دايماً بنحاول نخلي الموضوع معبر فبما إن ده unit test بيختبر جزئية معينة في الفونكشن بتشتغل صحة ولا لأ بيختبر هل الfirst والlast name بيشتغلوا بشكل صحيح ولا لأ فأنا بحاول أخلي الاسم معبر عشان لو أنا عندي بعد كده مئات ال-tests طبعاً ملف التستة بيبقاش فيه تست واحد بس لو بنتكلم على مشروع وقعي ومشروع كبير فلما يكون عندي مئات التست واشغلها واشوف التقرير اللي بيطلع لي لما يكون اسم التست معبر حفهم التست ده بيختبر ايه على طول على عكس ان انا اقول مثلا تست underscore x ايه معنى x دي مش فاهم فاهم قصدي فاهم الفكرة فدائما بنحاول نستخدم اسامي معبرة ولكن المهم ان احنا نستخدم كلمة تست underscore عشان لما بستخدم pi test هو بيروح automatically بشكل automatic يشوف كل الفانكشنز اللي بتبدأ بكلمة تست underscore فبيعرف ان دي تيست فونكشنز فبيروح يستدعيها ويشغلها فدي الحاجة المهمة اللي مفروض تعرفها طيب عايز بقى اشغل التيست ها حمستني هقولك تمام روحة الشيل تمام ممكن نعمل هنا clear عشان نمسح الكلام ده وعشان تشغل التيست اتأكد بس ان انت لو انت مثلا على الماك جوه الترمينل انت في الديركتوري او في الفولدر اللي فيه المشروع لو انت على الكماند لاين انت برضو في الديركتوري او في الفولدر اللي فيه المشروع لو انت على ريبلت مش فرقها تروح هشيل على طول نعتبرها في المشروع وهو اسم الـ Replet ستكتب بس Pytest ثم تضغط Enter سيظهر لك المخرجات الآتية دعنا نشرحها سريعاً أول جزئية هو يقول لك ما هو الـ Platform التي تستخدمه هنا لـ Replet تستخدم Linux لو كنت على Mac سيكتب لك MacOS لو عند Windows سيكتب لك Windows لو على Linux سيكتب لك Linux بعد ذلك يقول لك ما هي المستخدمة من الPython على ريبلت هنا يوجد الـPython Version يمكن أن تكون لديك مجموعة من الPython يقول لك أيضا ما هي الموجودة من الPyTest هذه هي التفاصيل التي في الأول بعد ذلك هنا الـRoot Directory الـDirectory التي تقوم بتحديثها هذا هو المكان الذي نحن فيه هذا هو المجموعة التي نحن فيه PyTest Crash Course هذا يمكن أن يكون لديك على Windows مثلا D slash project slash Python بعد ذلك اسم المجموعة التي تقوم بعملها وهكذا مثلا على الماك برضو أي أن كان الفولدر اللي انت جواه فدي الـ Directory اللي احنا موجودين جواها بعد هنا هنا بعد كده هنا Collected one item يعني ايه عدد الـ Tests اللي اشتغلت فاحنا هنا عندنا تيست واحد بس عشان كده بيقول لي one item تيست واحد وبعدين بيكتب لي اسم الملف اللي هو شغله اللي هو test__name__function النقطة الخضر اللي معناه اللي هنا دي معناها ان الملف ده كان جوا تيست واحد وان التيست ده عدى بنجاح فالنقطة الخضر دي لو كان في تيست تانية كان في نقط تانية و المية في المية بتوضح برضو الموضوع عندي تست واحد عده بنجاح مية في المية وهنا برضو بيقول لي one passed تست واحد عده كله تمام وقل وقت الاستغراقه فكده انا عندي التست ده نجح يعني معناها الفونكشن دي فعلا بتقدي الوظيفة بتاعتها لو ادتها first name و last name على هذه الهيئة بترجعلي مخرج شبه ده طيب خلينا بقى نعمل التعديل اللي كنا عايزين نعمله بحيث ان التست ده يفشل نشوف شكل التست لما يفشل هيكون عامل ازاي فخلونا نيجي هنا كده الفرست دي نحط هنا middle بالشكل ده ونيجي هنا ونحط middle بالشكل ده فدلوقتي الطريقة اللي الفونكشن بتشتغل بيها تغيرت أنا غيرت في الفونكشن والتست لسه زي ما هو لو أنا جيت هنا عملت clear عشان بس أمسح اللي موجود ده ورحت شغلت boy test إيه اللي هيحصل آه هيقول لي التست failed وحلاقي هنا F كده معناها failed فشل 100% بالأحمر فشل 100% وحلاقي هنا أن هو بيكتب لي الفونكشن كله ولكن سألاحظ أنه يقوم بعمل علامة أكبر منها مثل مؤشر أو إدارة ساهم على السطر الذي أدى إلى أن يفشل التحدي فالتحدي الذي أقوم به هو أن هذا المفتاح فشل بسبب هذا السطر فما الذي يحدث في هذا السطر؟ أقوم بإغلاقه على المفتاح و أغلقه بأثنين أردوان لماذا فشل هذا؟ لأن هذا المفتاح يأخذ ثلاثة و ليس اثنين فهو بدأ يشرح لي حتى هذا المفتاح هنا يقول لي هو مفتاح أهو، ما هو نوع هذا المفتاح؟ طيب مفتاح، خطأ في النوع missing one argument يفتقد أو يفتكر argument كمان اللي هي last لأننا هنا عندي first middle last في تعريف الفنكشن أنا لما ندهت عليه ادته قيمتين بس فهو خد القيمة دي حطها في first خد القيمة دي حطها في middle وملقاش حاجة يحطها في last فعشان كده بيقول لي missing required position of argument last طب أنا ازاي اعالج المشكلة دي ممكن واحد ييجي يقول لك قاير في التست ستتغير في التست كيف أعلم سأضع هنا اسم middle سأضع argument 2 أسميه أشرف حمادة بطيخة أقوم بوصفه أنه يجب أن يظهر الـ output أضع حمادة هنا أقوم بعمل clear ثم أعمل باي تيست كما ترى كما قلت لك تستعدت وعملت الفنكشن وكل شيء تماما لكن هناك شيء مهم أخفلت عنه أنني لو شغلت البرنامج نفسه البرنامج لا يستخدم الفنكشن بشكل قديم تمام؟ أو تستعدت وكل شيء لكن لو جئت إلى الكونسول دعني أمسح كده وأعمل مرة أخرى وأقول أول أسم أشرف ثم أسم ثاني حمادة أو أسم آخر لقيت انه ضرب ليه؟ لانه هنا بيتوقع مني مدخلين بس لسه برضو مش ثلاثة زي ما انا عدلت هنا ففرحتي انت رحت عدلت في التست عشان مجرد يطلع لك pass او ان هو التست عدى لكن انت بوصت الكود في حتة تانية عندك جزء في البرنامج لسه بيستخدم الفونكشن في شكله القديم فانت ما استفدتش حاجة لما عدلت التست بالشكل ده طب ايه الصح بقى اللي انا اعمله؟ الصح ان انت تروح تعدل في الفونكشن نفسه بطريقة ما تخليه يشتغل في الحالتين يعني تخليه يشتغل في الحالة دي ان هو بياخد اتنين arguments بس وتخليه يشتغل في حالة ان هو ممكن يقبل برضو ثلاثة arguments وتعمل unit test تانية بالتست الحالة المختلفة دي يعني نرجع هنا التست ده كما هو كان عليه ان هو بيتست حالة الفرست واللاست بس ونعمل unit test تانية بالتست حالة الفرست والميدل واللاست طيب الموضوع يلقبط شوية خلينا واحدة واحدة نروح نعمله مع بعض انا مبدايا عشان اخلي الفونكشن ده بيشتغل بالطريقتين يجب أن أجعل middle هو عدد مختلف أو مختلف من الأرقام شيء لا يجب أن يكون إختياري لكي أفعل هذا يجب أن يكون هذا المعدن في النهاية لا يمكن أن يكون هناك مدى مختلف و في النهاية هنا يمكنني أن أقول middle و لكي أجعل optional إختياري يعني في وقت أن أضعه على المنطقة لا يجب أن أحدده يجب أن أقوم به في مقرنة المنطقة في وقت تعريف المنطقة شيء يسمى default value قيمة افتراضية هو يأخذها لو أنا محددتوش، لو أنا مددتلوش قيمة بنفسي فهنا القيمة الافتراضية هتكون empty string لو أنا محددتش قيمة للميدل وأنا بندها على الفانكشن فهو بشكل افتراضي هياخد empty string طب ساعاتها محتاج غاير شوية في الطريقة اللي الفانكشن بيشتغل بيها فعايز أقول if middle، لو middle دي بترو يبقى أنا عايز أعمل إيه؟ يبقى أنا عايز أخلي الفول نيم بالشكل ده خلينا ندخل دي كده جواها، يبقى الفول نيم بيكون first بعدين middle، بعدين last، يعني إيه middle بترو؟ هذا يعني أنه أجعلها قيمة في الوقت الذي أستخدمها أو أستخدم الفنكشن لأنها لو كانت صحيحة لن تكون مجرد مجرد مجرد هذا المجرد مجرد يقوم بالتحقق لقيمة خاطئة شيء خاطئ لذا في حالة أنها تصبح فارغة فقط لن أدخل هنا ويجب أن أقوم بعمل إلا بما أنني لم أحدد مجرد مجرد مجرد لذلك في حالة أن المجرد مجرد مجرد مجرد صحيح؟ يمكن أن أمسح هذا هكذا يمكن أن يتعامل الفنكشن مع المجرد مجرد مجرد مجرد يمكن أن يتعامل مع الحالتين ولو أردت أن أختبر هذا يمكنني تقوم بعمل unit test أخرى تختبر جزئية middle name هنا unit test يختبر last و first معاً أو first و last إذا أردت تختبر first و last و middle سأقوم بعمل unit test أخرى سأقوم بعمل test underscore اتفقنا أن كل تفاعلات الـ test يجب أن تبدأ بكلمة test underscore وسأسميه first underscore last underscore middle underscore name لكي يكون الاسم معبر أنا هنا بختبر إيه؟ إن الفيرست واللاست والميدل بيشتغلوا ممكن أعمل كوبي للكلام ده ولكن مع بعض التعديلات البسيطة عايز أقول مثلاً هل الأسامي مثل خليني أمسح ده كده حمادة، مانجة، فراولة فراولة بالشكل ده بيشتغل واضح إن أنا جعان شوية معلش وحاجة هنا أدي له إيه؟ أدي له الثلاثة بقى arguments هدي له حمادة، وهادي له فراولة اللي هو الـ last name وبعدين هدي له إيه؟ هدي له مانجة وهو middle name لأنه لو فاكر الترتيب عندي كده first بعدين last بعدين middle فfirst بعدين last بعدين middle المفروض المخرج يبقى شكله عامل إزاي؟ يبقى شكله بالشكل ده حمادة مانجة فراولة يبقى أنا كده عملت 2 unit tests الملف التست كيس بتاعي موجود جوا 2 unit tests لو جيت هنا عملت clear وشوف التست دي هتشتغل ولا لأ هقول pi test ودوس enter حلاق ان الدنيا تمام الاثنين تستشتغلوا بشكل زي الفول معناها ان انا كده اقدر استخدم الفونكشن في الحالتين فلو جيت هنا في البرنامج الاساسي بقى بتاعي هنا في الكونسول ومسحت كده وعملت run وجيت اول مرة دخلت مثلا حمادة منجا فانا كده اديت له two parameters او two arguments بس فهيطلع لي حمادة منجا وهيشتغل بشكل سليم وزي الفول كده يبقى احنا غطينا الفكرة بتاعة التستنج بشكل اساسي بالنسبة للفونكشنز لسه بقى محتاجين نشوف التستنج على يجب أن نتعرف على أنواع أخرى من الـ Assertions لأنه ليس هذا النوع الوحيد من الـ Assertions هناك أخرى أخرى كثيراً ويجب أن نتعرف على فكرة الـ Fixture وما هي الـ Fixture ومماذا أستخدمها قبل أن نقوم بكل هذا سيكون هناك تمارين على هذه الجزئية لكي نتأكد أنكم تعرفون استخدام التستنج مع أفكار أخرى ولكن إذا كنت تشاهد هنا على اليوتيوب دعونا ننتقل للجزء الثاني من الكورس ونتحدث عن تقديم الكلاس والمثالات فيه حتى الآن نتعلم كيف نكتب تقديم الكلاس في الواقع وسنقوم بنفس الكلام في الكلاس الموضوع مهم جداً لأنه عندما تكون لديك تقديم في الكلاس يمكنك أن تكون مستريحاً أن تغير في الكلاس أو تقوم بإعادة أو إعادة بعض التعديلات بدون أن تتبوز بما يقوم الكلاس بذلك أو بمعنى التحالف الثالث في الكلاس السلوك الحالي في الكلاس وكيف يعمل ولكن دعونا نبدأ نتعرف على أنواع أكتر من الأسيرشنز لأن إحنا لحد دلوقتي شفنا أنواع واحد بس زي ما عملنا أسيرت هنا وأسيرت هنا بالشكل ده فيه أنواع تانية كتير جدا للأسيرشنز خلينا نستعرض بعضها دلوقتي ومبدئيا خليك عرفها كده قعدة أي حاجة ممكن تبقى conditional statement أي حاجة ممكن ترجع true أو false فهي ممكن تبقى assertion بمعنى إيه؟ خلينا نفترض إن إحنا عندنا values مثلا الvalues دي A و B A and B أي values بقى strings, integers, anything ومبدئيا فأنا مثلاً ممكن أقول assert A equal equal B هل A بتساوي B؟ ممكن كمان أقول assert A مثلاً not equal B A لا تساوي B هو يعمل يعمل لي auto complete بيضهقني وهنا نكتب assert بالشكل ده ممكن كمان نقول assert A يعني عايز أتأكد هل value A ده بيرجع true ولا لا ممكن كمان أقول assert not A ممكن كمان أشوف هل assert A أكبر من B ولا لا وطبعا كل بقى الـ Greater than وال-less than comparisons يعني أكبر من أو يساوي أو أصغر من أو يساوي وهكذا بالشكل ده مثلا وهكذا أصغر من أو يساوي أصغر من بس وهكذا كل دي زي ما إحنا شايفين conditional statements كل دي حاجات حترجع true أو false طيب ممكن أشوف إيه كمان؟ ممكن أقول assert element أو item مثلا in collection يعني إيه؟ يعني الـ item دي ممكن تبقى حاجة جوه list بشوف هي موجودة جوه list ولا لا حاجة جوه مثلا تطل جوه ديكشنري جوه سترينج جوه ست كل دي عبارة عن collections ممكن اعمل assert item not in طب امثلة سريعة على ده ايه ممكن اقول مثلا assert to in واعمل مثلا list فيها 1 2 3 او 1 2 او 3 بالشكل ده عايز اشوف الاتنين موجودة جوه هنا ولا لا ممكن اقول مثلا assert my underscore list equal equal 1 2 3 بالشكل ده او 1 3 4 عايز اشوف هل الليست اللي اسمها my list بتساوي 1 3 4 ولا لا يمكن أن يكون دكشنري و أريد أن أرى هل هذا الدكشنري يأتي بأي نوع من المال أم لا مثلاً نام هذا يساوي حمادة و عندي عمر مثلاً و هذا العمر بالشكل هذا و هذا العمر 40 مثلاً أريد أن أرى هل هذا الدكشنري يساوي هذه المال أم لا أمكن أن أقوم بعمل أسرت للنسبة للمستوى الموجود في المجموعة المعينة أريد أن أقول أن لنسبة للمستوى الموجود في المجموعة الموجود في المجموعة الموجودة هل هو 3 أم لا أرى المنسبة أو عدد الألمانت الموجودة في المجموعة الموجودة أرى المنسبة أو عدد الألمانت الموجودة في المجموعة الموجودة يمكنني استخدام فنكشن مثل sorted مثلاً أريد أن أرى هل المنطقة التي لدي عندما أطبق عليها فنكشن sorted هل ستكون الماليات التي تحتوي عليها بهذا الشكل أم لا؟ يمكنني أن أريد أن أتأكد من الماليات التي تحتوي عليها بمجموعة دكشنري فأستخدم فنكشن list و أقول مثلاً myDictionary.keys بهذا الشكل وأريد أن أرى هل هذا سيساوي الماليات التي تحتوي عليها بمجموعة الـ name والماليات التي تحتوي عليها بمجموعة الـ age أريد أن أرى هل هم هم هم في دكشنري أم لا؟ وطبعاً هنا يوجد أيضاً equal أيضاً أريد أن أرى هل هناك مجال مختلف أو مجال من مجال مختلف أم لا فأستطيع استخدام مجال مختلف بهذا الشكل وأرى هل هناك مجال مختلف أو مجال مختلف أم لا فكل هذه أمثلة يمكنك أن تقوم بإصلاحها بخيالك حتى الصبح أي شيء من الآخر يمكن أن يكون مؤسفاً أو يمكنك أن تكتب مثل موضوع مستقل وترجعه محق أو مخلص فأنا أستطيع استخدامها كمجال مختلف أستطيع استخدامها كاختبار أو افتراض أرى من خلاله شيء معين سيتحقق أم لا بعد الوقت نبدأ نعمل class لكي نتست عليه ونرى عملياً كيف سيكون الموضوع وكما قلنا سيكون شبيه بموضوع الfunction لأن class في النهاية تحتوي على بعض الميثوث أنا أريد تست على هذه الميثوث ولكن هناك بعض الاختلافات البسيطة التي سنرىها معاً فدعونا نقفل الملفات المفتوحة هنا ونمسح المين الموجود هنا لكي نكتب جواب برنامج جديد ولكن أولاً دعونا نأتي هنا ونعمل ملف جديد وهو bank__account.py ونعمل class عبارة عن bank account حساب بنكي فحاجة هنا أعمل class هسميه bank account بالشكل ده هعمل initialization method هتاخد طبعا self وهتاخد initial balance initial underscore balance الرصيد الأولي وده هيكون بيساوي default value صفر لو أنا محددتش ال initial balance فهو هيكون عبارة عن صفر في الأول بعد كده هقول self.balance كده equal initial underscore balance وعايز اعمل 2 methods بسط جداً إداع وسحب فحاجة هنا اعمل deposit الإداع deposit بالشكل ده يأخذ و و الكمية أو الأمونت التي أريد أن أدعيها أحتاج أولاً إلى تأكيد أن هذه الكمية أكبر من صفر لأنني لا أستطيع أن أضع صفر ولو كانت الكمية أكبر من صفر فأريد أن أضع self.balance أريد أن أزود على الـ balance هذا الأمونت أريد أن أضع هذا الأمونت داخل الـ balance أو هذا المال داخل الرصيد وفي النهاية أريد أن أقوم بـ return self.balance أريد أن أرجع الـ balance بعد أن قمت بالتحديد أذهب بعد الوقت لنقوم بعمل فنكشن السحب ويأخذ ايضا self ويأخذ ايضا amount انا اريد ان ازعج كم من الـA وهنا الـcondition سيختلف قليلا يجب ان القيمة التي احاول ازعجها تكون موجودة في الحساب وتكون اكبر من 0 فهنا اقوم بعمل if condition اقول 0 يجب ان الـamount تكون اكبر من 0 ويجب ان تكون اصغر من او تساوي الـself.balance لانه لا يمكن ازعج اي شيء اكبر من الرصيد الذي املك لكن ممكن أسحب حاجة أصغر من الرصيد اللي عندي أو تساوي كل الرصيد اللي عندي ساعتها هقول تمام self.balance هشيل منه الأمونت اللي أنا سحبتها دي عايز أشيل من رصيدي الكمية اللي أنا سحبتها وبعدين عايز أعمل return self.balance بالشكل ده لو رحت بقى في المين عايز أكتب برنامج بيشغلي الكلس ده أو بيستخدم الكلس ده فأول حاجة عايز أعمله import طبعاً فهقول from bank account عايز أعمل import للbank account الكلس ده و بعدين عايز ايجي اقول هنا balance بيساوي 100 مثلا و هاروح دلوقتي اعمل حساب هعمل object من ال class هنداه على ال bank account بالشكل ده و هتديله ال balance لان هنا عندي في ال initialization method هو بياخد initial balance صح و بيحطها في ال self.balance فانا هنا اديته ال balance اللي هو عبارة عن 100 و عملت object من ال class و من غير بقى معاقض اخد inputs من ال user و كده و اقول له عايز تعمل ايه deposit او withdraw او مش عارف ايه المفروض يكون البرنامج كده ولكن احنا هنعمل حاجة بسيطة عشان احنا هدفنا هنا مش ان احنا نكتب كود في المين هدفنا ان احنا نكتب tests فمش عايز اطول عليكم خلينا بس نعمل print كده if statement نقول مثلا ال initial balance الرصيد الاولي و نيجي هنا نقول account.balance بالشكل ده و بعدين نحاكي عملية الدبوزيت فاك اننا بنعمل deposit هعمل برضو if string كده و هقول مثلا depositing 50 أن أنا أضع مثلاً 50 وأنا سأضع هنا على ال account.DepositMethod بالشكل هذا وسأعطيها 50 وبعدها سأقوم بنفس الكلام بالنسبة لل Withdraw فأنا سأقوم بعمل ما هو Withdrawing سأمسح ال space الذي هنا Withdrawing 30 مثلاً بالشكل هذا وسأقوم بعمل هنا account.Withdraw سأضعها على ال method وأقوم بعمل Withdraw لـ 30 لو جئت دلوقتي عملت رن للكلام ده شوفوا بيشتغل ولا لا حلاقي كل حاجة تمام خلينا بعد الوقت نروح نعمل تست ونختبر الميثودز اللي جوه الكلاس ده الانشيالايزيشن بيحصل بشكل سليم الدبوزيت بيحصل بشكل سليم ولا لا نفس الكلام بالنسبة للوثدرو فخلينا نروح أعمل فايل جديد للتست أسميه test underscore bank underscore account هنا بختبر الكلاس بتاع bank account فبدي اسم معبر هنعمل طبعا from bank account من الفايل ده عايز أعمل import للكلاس اللي أنا سأختبره في الكلاس يسمى Bank Account ودعونا نختبر هل الانشاليزيشن يحدث بشكل صحيح أم لا سأقوم بعمل مثل هذا سأسميه Def Test Underscore يجب أن تبدأ المثل بـ Test Underscore وأريد تثبيت الانشاليزيشن أريد تثبيت في الأول عندما أرى أن الانشاليزيشن يتضمن بالانشاليزيشن دعونا نأتي هنا نفتح الكوسين ونقوم بعمل colon وعايز اقول مثلا balance equal 100 بعدين هعمل اكيني بعمل object هقول account equal bank account وحديله البالانس ده وبعدين عايز ا assert عايز اختبر هل دلوقتي ال account dot balance بيساوي 100 ولا لا هنا طبعا ممكن اكتب برضو document string اللي بتشرح ده بي test a فممكن هنا اكتب is the initial balance equal to 100 لو عايز أشغل التست ده بقى حعمل ايه؟ هروح طبعاً للشيل وخليني هنا أقول لكم حاجة مهمة أنا هنا عندي أكتر من ملف تست لو كتبت Pytest وخلاص كل التست هتشتغل بمعنى ايه كل التست؟ حلاقي هنا بيقول لي 3 past التست اللي أنا كاتبه في الملف ده والتست اللي كانت موجودة قبل كده اللي أنا كنت أعملها كنت أعمل تستين للname function أنا مش عايز التلاتة يشتغلوا أنا دلوقتي عايز أتست حاجة واحدة بس عايز أركز على الملف بتاع التست underscore bank account الخطوة التي نقوم بها هي الـ class عندما أكتب pi test فهو يعمل كل الـ test files التي في الـ directory التي نحن فيها التي في الـ directory، اتفقنا أنها الـ directory التي نحن فيها هذه الـ directory إذا أردت أن أعمل ملف واحد فقط، دعوني أقوم بعمل clear فأحدد اسم هذا الملف هنا يوجد شيء يقول pi test إذا أردت أن أعمل ملف ما؟ أريد أن أعمل ملف test__balance__account.py هذا هو ما أريدك أن تهتم به في ذلك الوقت سيقول error file or directory not found وهذا صحيح لأنني كتبت اسم الملف خاطئا test__balance__account هو اسمه test__bank__account أنا كتبت balance بدل bank ما فيش مشكلة في حاجة تانية وأكتب boy test و المرة دي هكتبه صح test__bank__account.py بالشكل ده تمام جداً هيقول لي ان فيه one test والتست ده past وكله زي الفلي بقى أنا كده متأكد ان الـ initialization بيحصل بشكل سليم طب عايز أتست دلوقتي موضوع الـ deposit حلو قوي هاجي هنا وهعمل def وهقول test__deposit بالشكل ده وهاجي أخذ الـ 2 دول لأن أنا محتاج أعمل initialization الأول وبعدين أعمل object تاني من الـ class و بعدين عايز أجرب a deposit فحقول account.deposit أنا مش هكتب document strings تاني للسرعة يعني أو عشان ننجز ولكن خليكوا عارفين إن ده practice كويس إن إنتوا تكتبوا document strings في functions عمتاً سواء العادية أو ال test functions عشان نبقى فاهمين بالضبط الفنكشن المفروض يكون بيحاولوا يعملوا إيه المهم حاجة هنا مثلاً أجرب a deposit 50 و عايز أسرت إن ال account.balance دلوقتي بيساوي 150 صح؟ لأن أنا بدأت بbalance 100 لو عملت إداعة 50 يبقى المفروض الbalance دلوقتي يكون 150 ال50 زائد ال100 خليني أعمل run تاني لنفس الكلام وعشان ما أعودش أكتب نفس الcommand أنا أدوس سهم الفوق بيجيب الcommand اللي قابليها على طول بيكتبها هو لوحده بشكل أوتوماتيكي هدوس enter هيقول لي زي الفل 2 passed tests يعني التستين دلوقتي passed يبقى deposit شغالة بشكل سليم طب عايز أعمل الwithdraw حاجي هنا برضو أو عامل إيه def test underscore withdraw بالشكل ده عايز برضو أعمل نفس الحكاية balance equal 100 بالشكل ده وبعدين account equal bank account ودي له البالنس ده بحاكي ان انا بعمل بلنس وبعدين بعمل اوبجيك تاني وبعدين بتست بقى الفانكشناليتي account.withdraw عايزة withdraw مثلا 30 فانا المفروض المية لما اشيل منها 30 يبقى البلنس اللي هيفضل عندي يبقى 70 100 ناقص 30 ب70 يبقى عايزة اعمل assert عايزة افترض كده او اشوف دي هتطلع true ولا false ان البلنس يكون دلوقتي بيساوي 70 بعد ما عملت الwithdraw لو انا عملت clear ثم أضغط على سهم فوق سهم فوق سيأتي لي الـ command التي قبلها pytest test__bank__account.py سأضغط على enter سيقول لي تمام هكذا لديك 3 tests وكلهم passed وكل شيء مثل الـ full لحد الآن سأقول لك شكرا الله يكرمك والله ساعدتني أو بسطتني ما هذا ساعدتني؟ أسعدتني ولكن السعادة لا تدوم أنا الآن أريد تغيير في هذه الـ functionalities أريد أن أضيف شيء أو أضيف feature أقوم بتعديل ولكن من غير أن أضيف الكود الذي كتبته من غير ما الطريقة اللي الكود كان بيشتغل بيها قبل كده أو الإمبليمنتيشن اللي أنا عامله قبل كده يبوز طب إيه الحاجة اللي أنت هتعملها يا إسلام؟ هقولك أنا عايز أجي هنا كده أضيف list اسمها transactions إيه العمليات اللي حصلت؟ تمام؟ transactions بالشكل ده وعايز أنه كل ما يحصل عملية إداع أو سحب العملية دي تضاف للist بتاعت الترانزاكشنز دي بحيث أن أنا لو حبيت بعد كده مثلا أعمل method أشوف من خلالها الترانزاكشنز أو العمليات اللي حصلت على الحساب أقدر أعمل كده وأشوف كل الإداع والـ withdrawal أو السحب اللي حصل قبل كده زي ما بتقدر تشوف في حسابك البنكي طب هتعمل ده إزاي؟ هتعدل إيه هنا؟ حاجة أقولك إن أنا بعد ما هضيف الأمونت في الإداع مثلاً أو في الـ deposit عايز أجي هنا أقول self transactions الليست دي عايز أأبند عليها عايز أضيف عليها string مكتوب فيه deposited بالشكل ده وأكتب الأمونت أو دعت مبلغ كذا نفس الكلام هنا في الـ withdrawal أريد أن أقوم بمسحب ومعاملة وثدروب وأخذ أموالاً ومعاملة أخذ أداء أريد أن أرى هل التغيير الذي قمت به في هذا الميثود سيقوم بمسحب الطريقة القديمة التي كانت تعمل بها أو الفنكشناليتي القديمة التي كانت تعمل بها دعونا نقوم بعمل التحديث مرة أخرى دعونا نرى هل سيحدث خطأ في التحديث أو سيخطئ دعوني أقول ماذا أقول أشغل الـ command بتاعة Pytest هو أشوف حلقي إن ما فيش أي حاجة حصلت في الـ tests القديمة ده معناه إن التغيير بتاعي ما بوصش حاجة هنا أو بمعنى صح ما بوصش حاجة في الـ implementation اللي كان معمول يعني أنا لو جيت على الـ console ومساحة الـ run القديم وجيت أعمل run تاني حلقي كل حاجة لسه تمام ما فيهاش أي مشكلة ودلوقتي أقدر إن أنا كمان أختبر بقى موضوع الـ transaction ده بيتم هو نفسه بشكل صحيح ولا لأ فممكن أروح أزود tests تانية ممكن أقول def مثلاً test underscore deposit deposit underscore transaction عايز اشوف لما بعمل deposit ده بيتضاف كترانزاكشن كعملية ولا لا السطر اللي انا زودته هنا ده هل تمام ولا لا ده unit test بختبر وحدة من الفانكشن وحدة جديدة انا اضفتها في الفانكشن عايز اشوف شغالها ولا لا وطبعا كالعادة محتاج ان انا اروح اعمل لدول copy paste كده وحنلاحز مع بعض اللي لاحز يعني ان دول عملين يتكرروا عمل في كل مرة في كل تست اعرف balance وبعدين اعمل ايه object من الكلاس هل منطقي أنني في البرمجة التي أحاول أن أتفادى فيها لتكرار وما إلى ذلك أنه لا يكون هناك حل للموضوع هذا أنني أضطرر و أكرر هذا الموضوع كل مرة سأقول لك لا، أكيد ليس منطقي ويوجد شيء سنتعلمه الآن وهو الـ fixtures ستعالج هذا الموضوع لكن الأول دعونا نقوم بهذه الـ tests ونتأكد أن كله تمام فأنا هنا أريد أن أقوم بماذا؟ أريد أن أرى كيف يبدأ عندما أقوم بـ account.deposit بـ 50 مثلاً هل كلمة deposit 50 التي أضيفها هنا deposit بعدين الأمونت هتبقى موجودة في الليست دي ولا لا؟ فاللي أنا محتاج أعمله هنا أن أنا أقول assert وأشوف هل ال string deposited 50 هيكون موجود in هيكون موجود جوا ال account.transactions ده النوع ال assertions اللي شوفناه من شوية اللي هو بشوف هل item موجودة جوا collection معين هنا ال transactions دي عبارة عن list صح؟ هاي ال transactions عبارة عن list ودي ال item string معين هل هو موجود جوا ال list دي ولا لا لو حبيت أتأكد من الكلام ده خلينا نعمل clear وخلينا نشغل تاني حلاقي ان كله تمام 4 tests passed يعني كل التست اللي انا عاملها لحد الوقت بتعدي يبقى التست ده كمان شغال عايز اعمل نفس الكلام بالنسبة لإيه؟ بالنسبة للwithdraw ممكن اخد ده copy كده وعمله paste وغير هنا دي بس خليها withdraw دول مش هيتغيروا في حاجة هنا ممكن بس اعمل إيه؟ withdraw واشيل مثلاً أسحب 30 وعايز اتأكد اعمل assert ان كلمة withdraw 30 موجودة في الـ List ولا لا و اروح اشغل تاني خليهن شغل كده حلاقي ان انا دلوقتي عندي مشكلة عايزين اشوف المشكلة دي فين عندي واحد failed و 4 past طب ايه اللي failed حلاقيه موجود هنا واضح ان هو الميثود الجديد اللي انا عملتها ولو فاكرين ده المؤشر اللي بيقول لي ايه السطر اللي failed بالزبط اللي خلى الـ test يفيل فهو السطر ده السطر اللي موجود عندي هنا ده طب ايه نوع الـ error بيقول لي assertion error و حلاقيه هنا بيقول لي ايه وثدرو 30 انت حاولت تأثيرت وثدرو 30 ان وثدرو 30 بس هنا ال W ناقصة حد خد بالهم الحتة دي هنا دي كده ما فيهاش W والأثيرشن اللي انا بعمله بفترض ان هنا فيه W لان دي الطريقة الصحيحة لكتابة الكلمة فاقدر ارجع اشوف المشكلة فين في الكود بتاعي لو رجعت هنا كده للكود حلقيني هنا انسيت ال W شفتوا اهمية التستس؟ نبهتني الحاجة عبيطة جدا spelling mistake مشكلة في الاملاء لكن مشكلة ممكن تعمل مصيبة نعم هنا المصيبة ليست كبيرة جداً لأنها ستكون خطأ في الـM لأنه لن يقوم ببقاء شيء في البرنامج اللوجيكي ولكن عيب أن تكون بنك كبير لا أستطيع أن أكتب مثلاً كلمة ويثدرو أو ويثدرو فالـ test كشف لي هذه الحتة قبل أن أطلق البرنامج لـ users ويستخدموه ويستخدموه ويأخذوا انطباع وحش وكذا فأنا كده عرفت ما هي المشكلة في الـ code فأنا سأذهب وأصلح هذه المشكلة وأزود الـ W هنا فأنا كده كله تمام دعونا نقوم بعمل clear للكلام هذا لو أردت أن أترك الـ tests مرة أخرى لكي أرى ما هي المشكلة حتى أن كل شيء قد تفعيل كل شيء سأقوم بعمله كل الاختبارات تماماً معنى أن الكود يعمل كما أتوقع أنه يجب أن يعمل تعالوا مع بعضنا نضيف بعض التستات أخرى ستقول لي سأقول لك أنني أتبع أن الـ Deposit و الـ Withdraw يعملون بناء على أن المستخدم يلتزم أن يتبع رقم في الـ Deposit أكبر من 0 و هنا في الـ Withdraw أتبع بناء على أن المستخدم يحاول أن يحصل على شيء أقل من أو تساوي القيمة اللي عنده في الحساب طب ماذا لو هو حاول يودع أو يدبوزت حاجة بصفر أو حاجة برقم سالب مثلا هل ده المفروض يشتغل هتقولي المفروض لا ماذا لو حاول مثلا يسحب حاجة أكبر من البالانس بتاعه البالانس بتاعه 100 وحاول يسحب 120 150 أنا مش بعمل تستنج للكلام ده ودي تست مهمة لأن دي حاجة أساسية أو وظائف أساسية في البنك ماينفعش يكون الكود بتاعي بيخلي بيها وده أنا بالفعل عامله هنا أنا هنا بتأكد في الـ deposit هل الـ amount أكبر من وهل هنا الـ amount في الـ withdraw برضو أكبر من 0 لكن أصغر من الـ balance؟ فخلونا نعمل tests للكلام ده ننزل هنا تحت وممكن نعمل test جديد test invalid deposit الـ deposit اللي ما ينفعش طب الـ invalid deposit ده عبارة عن إيه؟ طبعا كالعادة هكرر دول تاني بالشكل ده وأنا قصد إن احنا نقعد نكررهم كده عشان نشوف المأساة خصوصا لو الحاجة على scale كبير مشروع كبير وانا انا بكرر بكرر بكرر في سطور حاجة مش عملية خالص عشان لما نشوف الحل نشوف ازاي الموضوع ده بيساعد المهم دلوقتي انا هجرى بعمل ديبوزيت account.deposit برقم اقل من صفر ديبوزيت بالشكل ده بسالب خمسين مثلا طب عايز اتأكد ان اللوجيك بتاعي شغال انا اصلا مش بقبل ان الرقم يكون ايه اصغر من صفر لازم دايما الامونت تكون اكبر من صفر فلو حاولت احط سالب خمسين اللي هي اصغر من صفر مش هيعمل حاجة مش هيخش اصلا في الاف وحيرجعلي البالنس الbalance اللي هو موجود عندي من الأول أصلاً فده اللي أنا عايز أختبره عايز أشوف لما حاولت أعمل deposit ل-50 هل هو قلل الbalance ده؟ ولا سابه زي ما هو؟ المفروض إن هو بيسيبه زي ما هو فده الافتراض اللي أنا عايز أعمله فعايز أقول account.assert.balance لسه بيساوي 100 لأن إنت حضرتك ما ينفعش توضع سالب 50 فعايز أتأكد إن ده تمام فخلونا نعمل هنا clear وبعدين نشغل تاني حلقين التست الجديد تمام وعندي 6 تست لحد دلوقتي كلهم بيعملوا passing يبقى ده كده زي الفل نفس الكلام عايز أعمله إيه لل Withdraw فحاجي هنا كده هعمل Copy Paste بس وغير دي أخليها Withdraw دول أنا محتاجهم برضو هنا هستخدم الميثود بتاعة Withdraw وأحاول وأنا عندي 100 هحاول أسحب كام؟ هحاول أسحب 150 هل ينفع أسحب 150 وأنا عندي المفروض اللوجيك اللي أنا عامله بيقول لا ما ينفعش تسحب حاجة أكبر من البالنس اللي عندك أو الرصيد اللي عندك فلو حاولت تعمل كده المفروض الرصيد يفضل زي ما هو فحاجة هنا برضو اشوف هل الرصيد لسه زي ما هو ولا بقى بالسالب مثلا ولا ايه اللي حصل فانا بفترض انه هو المفروض يبقى لسه زي ما هو لو الكود بتاعي شغال بشكل سليم لو التست ده عمل pass فحاجة هنا اعمل clear وبعدين اشغل تاني بالشكل ده حلاق ان 7 tests passed يبقى كده كله تمام وكله زي الفل كل اللوجيك بتاعي شغال بشكل صحيح لو جيت برضو هنا في المين عملت run حلاق الدنيا تمام شغالة ما فيش اي مشكلة عندي خلينا بقى نعمل حاجة دلوقتي وهو ان احنا نروح نضيف اصلا method جديدة خالص ونشوف ده حيبوس حاجة في الكود بتاعنا ولا التست هتفضل شغالة بشكل سليم فخليني أجي هنا في البانك أكاونت عايز أعمل ميثود جديدة ووظيفتها أنها تتشك البالنس تقولي أنا عندي رصيد قد إيه لأن أنا ما عنديش ميثود بتعمل الكلام ده لو حبيت أبص بس على البالنس بتاعي مفيش حاجة بتعمل الكلام ده حالياً فحاجي هنا كده في الكلاس وهعمل ميثود اسمها get balance بتاخد self طبعاً كالعادة كل اللي هيبتعمله بترترن self.balance شكراً مش عايز حاجة غير كده أريد أن أتست هذا الموضوع، أعمل بشكل سليم أم لا وأريد أن أقوم بعمل التست الذي لدي أرى هل هذا يقوم ببوض أي شيء من الأمور الموجودة فإذا جئت هنا وقمت بعمل تست سأجد أن كل التست التي لدي بعد الإضافة أو التغيير الذي قمت بعمله في الكلاس شغل بشكل سليم إذا جئت هنا في المنزل وقمت بعمل تست سأجد أيضاً الإمبليمات القديمة شغل بشكل سليم ولم يوجد أي مشكلة لذلك لا يوجد شيء ضربت، جميل جداً أرى أن تست هذه الموضوع الجديد، الإضافة الجديدة التي قمنا بعملها سأقوم بعمل تست test underscore get underscore balance بالشكل ده طبعا كالعادة حاخد السطرين دول اللي معايا في كل حتة بعدين عايز اعمل بقى شوية عمليات اشوف البالنس هيتغير على اساسها ولا لا فخليني كده اعمل assert واقول account.get underscore balance اشوف يا الماثل اصلا بتشتغل في الاول ولا لا المفروض ان هي دلوقتي ترجع 100 انا بادق بbalance 100 ما عملتش اي عمليات فالمفروض ان هي دلوقتي لما عمل get balance ترجع لي المية دي فعايز اتأكد ده بيحصل ولا لا خلي بالكوا الميثود دي حامل فيها اكتر من assertion ودي حاجة عادية مش لازم التست يبقى فيه assertion واحد بس دي حاجة جديدة ولكن حاجة عادية حبيت ان انا اعرفها لكم برضو فخلينا نقول مثلا دلوقتي انا عايز اعمل عملية deposit عايز اعمل اداع ب50 هندع على الassert تاني وعايز اشوف دلوقتي الbalance بتاعي المفروض يكون ب150 لو الميثود شغالها بشكل صحيح كان عندي 100 ضفت عليها 50 المفروض لما اندع على get balance يرجع لي 150 اللي هو الupdated balance او الرصيد الجديد طيب عايز اعمل عملية سحب account وعايز أسحب 30 المفروض دلوقتي لما أنده على getBalance 150 ناقص 30 يرجع لي كام صح 120 فعايز أعمل assertion بالموضوع ده أشوف هيبقى true ولا false هكتب هنا كده 120 لو التست ده passed يبقى getBalance method شغالة بشكل سليم سواء بعرض البالنس في الأول خالص سواء بعرضه بعد مثلاً ما عملت deposit معين سواء بعرضه بعد ما عملت withdraw معين وهكذا فلو جيت هنا في الشل وعملت clear بالشكل ده وبعدين شغلت تاني حلقى ان كله تمام عندي تمانية تيست كلهم past وكله زي الفل يبقى انا متأكد ان الماثل دي شغالة بالطريقة الصحيحة خلينا بعد الوقت نتكلم عن موضوع الفيكسترز اللي قلتلكوا عليه اللي بيعالج فكرة التكرار دي حلقى ان انا عندي تمانية تيست فيهم كلهم بضطر ان انا اعرف البالنس وبعدين اعمل initialization لل object اعرف البالنس وعمل initialization لل object وهكذا وهكذا وهكذا شيء مش المفروض ان انا أبقى بكراره بهذا الشكل أو المفروض يبقى عندي حل more optimized حل بيعالج مشكلة الـ repetition أول تكرار دي عندي concept في البرمجة اسمه dry dry بالشكل ده معناها do not repeat yourself ما تكررش نفسك ما تكررش كود لو انت مش محتاج تكرر الكود ده أو في حل لهذا الموضوع طيب الفيكستر دي عبارة عن ايه عبارة عن ديكوراتر طبعا انا هنا مش هشرح الديكوراترز في درس في القائمة اللي على القناة في بلاي ليست بطاعة بايثون بتشرح الـDecorators الـDecorators برضو موجودة بالتفصيل جداً في الكورس المدفوع جوه درس من احد الدروس فلو انت متعرفش الموضوع روح اتفرج هنا او هنا اين كان انت في المجاني او في المدفوع او روح اعمل بحث عن الموضوع ولكن عشان نستخدم الـDecorators ده بحتاج ان انا اعمل Import للمكتبة بتاعت او الموديول بتاع Pytest لان الـDecorators ده موجود جوه الموديول احنا لحد دلوقتي كنا بنعمل الاختبارات من غير ما نعمل Import للموديول لأنني أشغل الموديول بشكل عملي ويعمل على كل المفاعل التي تبدأ بكلمة test underscore لكن الآن بما أنني سأستخدم ديكوراتور داخل الموديول فأنا أحتاج إلى إمبورت هذا الديكوراتور يكون كيف يتم كتابة الفيكستر يتم كتابة الفيكستر كيف يتم كتابة الفيكستر كما نعلم مهمة الدكوراتور أن يغير السلوك الذي يعمل به فنكشن معينة يغير طبيعة تنفيذ فنكشن معينة وهذا ما سنفعله هنا نريد تحت الدكوراتور نقوم بعمل فنكشن وظيفتها أن تتوفر علي الموضوع الذي أكرره هنا كيف سأفعل هذا؟ سأقوم بعمل فنكشن يسمى bank__account وإذا لا تلاحظون هنا أنني لم أكتب test__bank__account لأن هذا ليس فنكشن تقريباً، إنه فنكشن عادية ستظهر لها مفرد مختلف لتستخدمها بشكل خاص وسنرى هذا الموضوع معاً سأقوم بعمل فنكشن كل مهمة فنكشن هي أن تقوم بإنشياليزة الموضوع أن أقول فيها أن الـ balance يساوي 100 وأقوم بعمل فنكشن يسمى account من الـ class يسمى bank account بالتالي اقدر انا دلوقتي اروح هنا كده في كل التست بتاعتي وبعد كده محتاج هنا اجي اعمل ريتيرن للأوبجيكت دي ريتيرن الاكونت اوبجيكت اللي انا عملتها ودلوقتي اقدر ان انا بقى اروح في كل تست فانكشن من التست فانكشنز اللي عندي واقول له هنا بانك اندرسكور اكونت ادي له الفانكشن ده ساعتها مش هبقى محتاج اكتب الكود ده يعني ممكن هنا دلوقتي امسح السطرين دول ازاي قدرت اعمل كده لان دلوقتي الفانكشن ده التست فانكشن ده لما بياخد الـ Bank Account Function ده كـ Argument أو كـ Parameter والـ Function ده بما أنه عليه Decorator وبيشتغل بطريقة معينة وبيرجع الـ Account Object فخلاص دلوقتي الـ Test Function ده بقى عارف أو بقى شايف الـ Account Object دي مش محتاج أن أنا أعرفها جوا مش محتاج السطرين دول وأقدر أعمل بقى كده في كل بقية الـ Functions يعني أقدر أخد الـ Bank Account دي و أحطها هنا ولكن قبل ما نكمل هلاحظ بس أن الـ Account دلوقتي بقى عليها خط أحمر ليه؟ لأنني مفروض أسميها بانك أكاونت على اسم الفونكشن فهنا سأسميها بانك أكاونت بالشكل هذا وخلاص كما قلنا هذا التست فونكشن يملك مرجع للأبجيكت التي تعملت هنا لا يحتاج أن أعرفها كل مرة نفس الكلام سأفعله هنا الآن أمكن أن أمسح هؤلاء عادي جدا لا أحتاجهم بالشكل هذا وغير هذا وخليها بانك أكاونت هنا أيضا أمسح وأديه بس البانك أكاونت ودقيقة أغيرها وخليها بانك أكاونت سأفعل هذا في نفس الكلام ده كله في نفس الـ functions كلها هنا bank account وهنا bank account وهنا bank account وامسح السطرين اللي انا ما بقيتش محتاجهم اغير دي اخليها bank account اغير دي اخليها bank account احط هنا bank account امسح السطرين اللي انا مش محتاجهم اغير دي اخليها bank account اغير دي اخليها bank account امسح السطرين اللي انا مش محتاجهم حسنا انا عامل روبو حسنا انا بقيت روبوت واغير دي خلاص قربنا نخلص كله تمام لكي نختبر مع بعض ما قمنا به عك أو فل سأمسح هؤلاء لا يحتاجون وأضع هذه الأسعار بـ Bank Account وأضع هذه بـ Bank Account وأضع هذه بـ Bank Account وأضع هذه بـ Bank Account وأضع هذه بـ Bank Account كما يجب أن أقوم بعملها لا يوجد شيء يضرب في وجهي لا يوجد شيء سيضرب لأنني نسيت أن أغير هنا ونسيت أن أغير هنا كما يجب أن أقوم بعملها فعلياً لم أنسى شيئاً لذلك دعني أأتي هنا ونقوم بعمل Clear لحظة Moment of Truth لحظة الحقيقة Enter زي الفول الـ Tests كلها بتباس كله شغال تمام اتعلمت موضوع الفيكستر الـ Decorator اللي بيخليني اعمل Method احط فيها الـ Code اللي كان عمال يتكرر في كل تست من دول فلاقي ان انا اختصرت على نفسي كتير جدا و كده خلاص الـ Function فعليا بتاع الـ Test بقى جوا الحاجات اللي هو م��تاجها بس مش محتاج ان انا كل مرة اعرف Balance و اعرف Object و اعرف Balance و اعرف Object وهكذا طبعاً مش دايماً وإنت بتكتب تيست ممكن تحتاج تستخدم فكسترز خصوصاً لو إنت بتعمل بروجيكت صغيرة ولو حس إن إنت الموضوع معقد أو حاجة ففكك من موضوع الفكستر خالص ابدأ في الأول بإن إنت تكتب تيست عادية حتى لو فيها كود مكرر وبعد ما التيست دي تكتبها ابتدي فكر هل ممكن تأبتميز هل ممكن تحسن الموضوع بشكل ما هل في كود كتير مكرر ممكن تكتب له فكستر أو لا لكن مش لازم تبدأ من الأول عطول إن إنت مفكر إن إنت لازم تعمل فكستر لأنه مش لازم أنا مش عايزك تتعقد من الموضوع بالنسبة لي أفضل لأن أنت تبدأ بس تتعود على فكرة التستينج بشكلها البسيط عن أن أنت ما تكتبش تست خالص وطبعا مش لازم تكتب تست أصلا مش لازم تعمل تستينج لو أنت واحد مبتدئ لسه في الأول بتعمل برامج بسيطة جدا مش محتاجة قوي تست ولكن لما تبدأ تعمل مشاريع أكبر شوية هيبقى حلو أن أنت تتعود على فكرة التستينج وتبتدي تتعود أن ده practice أنت بتعمله دايما وبشكل مستمر لأن دي حاجة هتحتاجها طبعا في الشغل حاجة هتميزك جدا لما تيجي تقدم على شغل لما الراجل اللي بيبص مثلا على CV بتاعك أو بلاش CV بيبص على كود بتاعك على جيت هوب المشاريع اللي انت عاملها لما يلاقي ان انت ايه فاهم التستنج بتستخدم التستنج دي حاجة هتميزك عن بقية الناس لان مش كل المبتدئين في تعلم البرمجة بيتعرضوا للموضوع ده او بيهتموا به او بيعرفوه اصلا طبعا بالنسبة للناس اللي بتتفرج على الدرس ده جوه الكورس بعد الدرس ده كالعادة هيكون فيه تمارين اخرى على امثلة اخرى عشان تتدربوا والمفاهيم تترصخ في دماغكوا ولو فيه اي اسئلة هتسألونا على المجتمع الخاص اما لو انت بتتفرج على اليوتيوب فما تنساش ان انت تبص على الكورس المدفوع بتاعنا الرابط في الوصف وفي اول كومنت وفيه خصم 55% دي كده كانت كل حاجة اتمنى تكونوا استفدتوا واشوفكم ان شاء الله في الدرس الجاي