mzdhr

Members
  • عدد منشوراتي

    13
  • تاريخ الإنضمام

  • تاريخ اخر زياره

السمعه بالموقع

5 Neutral

1 متابع

عن العضو mzdhr

  • الرتبه
    مبدع مثابر
  • تاريخ الميلاد 02/02/90

معلومات عامة

  • الجنس
    ذكر
  • السكن
    المملكة العربية السعودية
  • هواياتي
    تعلم البرمجة,برمجة تطبيقات اندرويد عربية, جافا, بايثون, قرائه, كتابه, مشي, العاب قديمة, مسلسلات, افلام.
  1. بالنسبة للإحتراق اخي انصحك بـ تقنية البومودورو تساعد كثيراً (ركز على فعل ١٠ بومودورو يومياً, وليس على اتمام المشروع). و انصحك ان تحاول التعلم بالطريقة الصحيحه, هذا الكورس ممتاز جداً تم اعدادة من قبل البرفسور Barbara Oakley. Learning how to Learn: Powerful mental tools to help you master tough subjects https://www.coursera.org/learn/learning-how-to-learn وايضاً لها كتاب يتناول نفس الموضوع (لاتغرك كلمة math بعنوانه, فهو لايناقش الرياضيات) بشكل مفصل وممتاز جداً. A Mind For Numbers: How to Excel at Math and Science (Even If You Flunked Algebra) https://www.amazon.com/Mind-Numbers-Science-Flunked-Algebra-ebook/dp/B00G3L19ZU فهذا الكورس وهذا الكتاب سيناقشون طريقة تفكير عقلك, ولماذا يحدث لك احتراق, وكيفية التغلب عليه, ماهي الطريقة السليمة للمذاكره التي تناسب العقول, وكيف تحسن من اداء مذاكرك (او عملك), وماهي الوسائل والادوات التي تساعدك, وكيفية رؤية الصوره الكبيره, و تركيب القطع الصغيره لترى الصوره الكبيره واضحه الخ... فهي اصبحت من فاشلة تم طردها من الجامعة الى برفسور باستخدام هذه الطرق وهذا الـ mindset التي سوف تشاركه معك في كتابها وكورسها. هذه خرطية ذهنية من عملي لما يتناوله هذا الكورس والكتاب: الجيت هوب https://github.com/mzdhr/Learning-MindMap وفي النهاية ارى التخصص في مجال واحد ثم التوسع الى مجال اخر بعد معرفته بشكل جيد افضل. فالتشعب في المجالات بالبداية هو مايهلك المبرمج. والله اعلم
  2. حاول ايجاد شئ تريد صنعه, واجعله هدفك. في اعتقادي المبرمج الحقيقي هو من يصنع الاشياء. ولصنع هذه الاشياء يتعلم مايحتاجه من لغات برمجة وتقنيات شبكات وحاسوب. اي لاتركز على تعلم لغة البرمجة وتختيمها, بل ركز على الشئ الذي تريد صنعه. مثلاً اذا كنت تريد تعلم لغات البرمجة للفرونت (html, css, javascript), حاول ايجاد شئ يحتاجهم لصنعه, مثل انشاء موقع يخدم شئ محدد. مثال اخر: اذا تريد ان تتعلم الاندرويد يجب عليك ايجاد شئ (فكرة تطبيق) تقوم بالعمل عليها وانت تتعلم ماتحتاجه من جافا وديزاين باترنز واندريود sdk لصنع هذه الفكره, وهكذا... مبرمج عادي: مبرمج حقيقي: وكل ماكثرة هذه الاشياء التي يصنعها المبرمج, يصبح مبرمج حقيقي! هذا اعتقادي, والله اعلم
  3. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذه المقالة سنتعلم كيفية استخدام الـ Parameterized (الدوال متعددة المدخلات) و Theories (النظريات وافتراضاتهم) للتحقق من مزيج للمدخلات المتعددة في دوال الاختبار, حتى لايصادف المشروع اي من الاخطاء المستقبليه بسبب مدخلات عشوائيه او شاذة للدوال. وبما انهم متشابهان في الوظيفة فأرى من الافضل التطرق لهم في مقالة واحدة. المواضيع السابقة (مهمة لفهم هذا المقال) هذه هي المقالات السابقة والتي تعتبر ضروريه لفهم هذا المقال فاذا لم تكن لديك خلفيه مع الـ JUnit انصحك بقرائتها قبل هذا الموضوع والذي يعتبر المقال السادس من اصل ستة مقالات والاخير في هذه السلسلة للإصدار الرابع من JUnit والذي يتوافق مع تطوير تطبيقات الاندرويد, اما بالنسبه للإصدار الخامس من الـ JUnit فهو مشابه للإصدار الرابع هذا مع اضافة بعض من الاشياء الجديده فقط. رابط المشروع https://github.com/mzdhr/KidCalculator-JUnit وتوجد كلاسات هذه المقالة باسم: ParameterizedTest.java و TheoriesTest.java في المشروع. واذا اردت الاطلاع على كلاس الـموديل فهذه هي Calculator.java. ماذا سوف تقرئ في هذه المقالة ماهو المقصود بالمدخلات والمخرجات للدالة؟ ماهي المعضلات التي تقوم الـ Parameterized و Theories بحلهم؟ كيفية استخدامهم؟ وماهي خطوات كتابة كلاساتهم؟ وماهو الفرق بينهم؟ وايضاً ماهي الفروقات بين دالة النظرية ودالة الاختبار. توضيح ماهي المدخلات للدالة؟ هي الـ Parameters للدالة. مثال للدالة public int addition(int firstNumber, int secondNumber) { return firstNumber + secondNumber; } مثال للمدخلات addition(3, 5); تعقيب الرقم ٣ والرقم ٥ يعتبران مدخلات للدالة. والناتج يعتبر المخرج لها. بعض من المعضلات التي تقوم الـ Parameterized و الـ Theories بحلهم هذه بعض من ابرز المشاكل او المعضلات التي تستطيع حلهم باستخدام الـ Parameterized و الـ Theories في الـ JUnit. ماذا لو اردت ان تقوم بكتابة اختبار لدالة الـ addition يحتوي على الكثير من المدخلات؟ هنا نستخدم الـ Parameterized. ماذا لو اردت التحقق من ان الناتج دائماً صحيح كما تريده لداله ما, حتى وان قمنا بشقلبة او مزج او خلط او عكس المدخلات مع بعضها البعض؟ هنا نستخدم الـ Theories. استخدام Parameterized في الـ JUnit نستخدم الـ Parameterized اذا اردنا اجراء اختبارات كثيرة على دالة ما, وهذه الاختبارات تختلف في المدخلات و المخرجات للدالة. معضله تخيل لو ان لديك الدالة التالية: public int addition(int firstNumber, int secondNumber) { return firstNumber + secondNumber; } وانك تريد ان تقوم بكتابة دالة اختبار تقوم بتجربة العديد من المدخلات عليها (ربما stream كامل من المدخلات وليس فقط لسته) لإختبار صحة منطقها. فالحل البدائي هو تكرار كتابة هذه الدالة بعدد المدخلات التي تريد تجربتهم عليها. اما الحل المناسب هو كتابة كلاس Parameterized تقوم بهذا العمل على اكمل وجهه. خطوات كتابة كلاس Parameterized لإختبار المدخلات و المخرجات المتعددة نقوم بعمل كلاس مشغل للـ Parameterized وذلك من خلال النوتيشن RunWith كما في حال المشغلات بالمقالة السابقة. نقوم بكتابة الـ Fields التي سوف نحتاجها في هذه الكلاس مثل عنصر من الموديل Calculator.java وايضاً عناصر ترمز للمدخلات والمخرجات. نكتب دالة setUp ذي النوتيشن Before, لتجهيز عناصرنا المراد اجراء الاختبارات عليهم. ننشئ Construction لربط عناصر الـ Fields بالقيم التي سوف ندخلها لاحقاً. ننشئ دالة data ونجعلها static تقوم بإرجاع المدخلات و المخرجات التي نريد اختبار الدالة بها, ونضع النوتيشن Parameterized.Parameters فوقها. الان نقوم بكتابة دالة الاختبار, والتي سوف تختبر الدالة addition من الموديل Calculator. ونستخدم القيم التي بالـ Fields كمدخلات و مخرجات لدالة الـ addtion. الكود لكلاس مشغل الـ Parameterized package com.company; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Arrays; import java.util.List; import static org.junit.Assert.assertEquals; // This class become a Parameterized Runner @RunWith(Parameterized.class) public class ParameterizedTest { // Fields private Calculator mCalculator; private int mInput01; // uses to store input for the first number. private int mInput02; // uses to store input for the second number. private int mExpect; // uses to store input for the expect test result. @Before public void setUp(){ // Arrange mCalculator = new Calculator("Orange"); } // Class Constructor -> To hook the values to our @Test Method. // It will run for each parameter we have in our Data. public ParameterizedTest(int input01, int input02, int expected){ mInput01 = input01; mInput02 = input02; mExpect = expected; } // This notation provide the input parameters for our @Test Method via the Constructor. @Parameterized.Parameters public static List<Object[]> data(){ return Arrays.asList(new Object[][]{ {2, 4, 6}, // means: 2 + 4 = 6 {4, 4, 8}, // means: 4 + 4 = 8 {-11, 4, -7}, // means: -11 + 4 = -7 {66, 395, 461}, // means: 66 + 395 = 461 {1000, -4, 996}, // means: 1000 + 4 = 996 {99, 1, 100} // means: 99 + 1 = 100 }); } // Our @Test Method @Test public void additions_test(){ // Action int result = mCalculator.addition(mInput01, mInput02); // first number + second number = result. // Assert assertEquals(result, mExpect); } } تعقيب قمنا بجعل هذه الكلاس تعمل كمشغل Parameterized وذلك من خلال استخدام النوتيشن RunWith اعلاها. ثم أنشأنا حقل لعنصر الموديل لدينا Calculator. وايضاً أنشأنا ثلاثة حقول وهي mInput01 و mInput02 و mExpect حتى نخزن فيهم قيمة المدخلات والمخرجات لاحقاً. و جهزنا مانريد في الدالة setUp ذي النوتيشن Before قبل بدء دالة الاختبار. ثم قمنا بانشاء Constructor للكلاس ياخد ثلاثة عناصر ويضع قيمتهم في الحقول الثلاثة السابقه. وبعد ذلك قمنا بكتابة دالة data تقوم بإرجاع لسته وبها جميع المدخلات والمخرجات التي نريد التحقق منهم ووضع النوتيشن Parameterized.Parameters فوقها, حتى تصبح هي المزود للـ Constructor والذي بدوره سوف يضع هذه القيم في الحقول الثلاثة في كل تشغيل له لكل احتمال. واخيراً قمنا بكتابة دالة الاختبار additions_test والتي سوف تختبر الدالة addition من الموديل Calculator بجميع المدخلات و المخرجات بلستة الدالة data. النتيجه تعقيب جميع الاختبارات التالية قد نجحت, اذن الدالة addtion لايوجد بها خلل. 2 + 4 = 6 4 + 4 = 8 -11 + 4 = -7 66 + 395 = 461 1000 + 4 = 996 99 + 1 = 100 وهكذا قمنا باختبار الكثير من المدخلات والمخرجات لدالة بكتابة دالة اختبار واحدة فقط. استخدام Theories في الـ JUnit نستخدم الـ Theories (النظريات) اذا اردنا حصر اي دالة في افتراضات (Assumptions) نحن نحددها, وشرط نجاح الاختبار هو ان تكون النتيجة دائماً صحيحة (اي true). فهي مشابهه جداً للـ Parameterized, ولكن الفرق هنا ان هذه تختلف في المدخلات فقط, وتتشابه في النتيجه وهي true في كل الاحوال. ماهي النظرية التي سوف نكتبها نظرية تقوم باخد مدخلين ثم تقوم بجمع فقط المدخلات الذي يكون الناتج لهم زوجي. خطوات كتابة كلاس Theories لإنشاء نظرية اختبار نقوم بعمل كلاس مشغل للـ Theories وذلك من خلال النوتيشن RunWith كما في حال المشغلات بالمقالة السابقة. نقوم بكتابة الـ Fields التي سوف نحتاجها في هذه الكلاس مثل عنصر من الموديل Calculator.java. نكتب دالة setUp ذي النوتيشن Before, لتجهيز عناصرنا المراد اجراء الاختبارات عليهم. ننشئ دالة data ونجعلها static تقوم بإرجاع المدخلات التي نريد اختبار الدالة بها, ونضع النوتيشن DataPoints فوقها. الان نقوم بكتابة النظرية (بالنوتيشن Theory وليس Test), والتي سوف تختبر ناتج فرضيات وتأكيدات نحن نريدها باستخدام الدالة addition من الموديل Calculator. الكود لكلاس مشغل الـ Theories package com.company; import org.junit.Before; import org.junit.experimental.theories.DataPoints; import org.junit.experimental.theories.Theories; import org.junit.experimental.theories.Theory; import org.junit.runner.RunWith; import static org.junit.Assert.assertTrue; import static org.junit.Assume.*; // This class become Theories.class Runner. @RunWith(Theories.class) public class TheoriesTest { // Fields private Calculator mCalculator; @Before public void setUp(){ // Arrange mCalculator = new Calculator("Purple"); } // Our Data Points (the inputs) @DataPoints public static int[] data() { return new int[]{ 2, 6, 8, 7, 3, 0 }; } // Our @Theory Method, not a @Test @Theory public void addition_even_result_test(int value1, int value2){ // Assumptions -> assumeTrue(), assumeNotNull(), assumeNoException(), assumeThat(), etc... assumeTrue(value1 % 2 == 0); assumeTrue(value2 % 2 == 0); assumeTrue( value1 != 0); assumeTrue( value2 != 0); // Action int sumResult = mCalculator.addition(value1, value2); // Assert assertTrue( sumResult % 2 == 0); // Just for demonstration System.out.println(value1 + " + " + value2 + " = " + sumResult +" is even"); } } تعقيب قمنا بجعل هذه الكلاس تعمل كمشغل Theories وذلك من خلال استخدام النوتيشن RunWith اعلاها. ثم أنشأنا حقل لعنصر الموديل لدينا Calculator. وجهزنا مانريد في الدالة setUp ذي النوتيشن Before قبل بدء دالة النظرية. ثم قمنا بكتابة دالة data تقوم بإرجاع لسته وبها جميع المدخلات التي نريد التحقق منهم ووضع النوتيشن DataPoints فوقها, حتى تصبح هي المزود لدالة النظرية لدينا لاحقاً. واخيراً قمنا بكتابة دالة النظرية addition_even_result_test والتي سوف تختبر الدالة addition من الموديل Calculator لجميع من المدخلات بلستة الدالة data. النظرية تختلف عن الدالة في انها تستخدم النوتيشن Theory. ايضاً تختلف عن الدالة في انها تأخد مدخلات parameters. النظرية تأخد مدخلاتها (parameters) من الدالة data المعلمه بالنوتيشن DataPoints. تستطيع ايضاً استعمال Fields ولكن تعلمها بالنوتيشن DataPoint. النظرية في بدايتها نقوم بكتابة الافتراضيات وهي باستخدام دوال الـ assume التي تأتي مع الـ JUnit. ثم نقوم بكتابة الفعل ومن ثم التأكيد. ناتج تشغيل كلاس النظرية (لاحظ كيف ان النظرية تقوم بتجربة جميع الاحتمالات للمدخلات بمزج وخلط وعكس الـ DataPoints) 2 + 2 = 4 is even 2 + 6 = 8 is even 2 + 8 = 10 is even 6 + 2 = 8 is even 6 + 6 = 12 is even 6 + 8 = 14 is even 8 + 2 = 10 is even 8 + 6 = 14 is even 8 + 8 = 16 is even تعقيب لدينا البيانات التالية : 2, 6, 8, 7, 3, 0 التي سنستخدمهم داخل النظرية. وقمنا بكتابة فرضيات (باستخدام الـ assume) وهي: لنفرض ان المدخل الاول و المدخل الثاني لايساويان صفر, وايضاً لنفرض ان ناتج باقي القسمة للمدخل الاول والثاني يساوي صفر (لماذا؟ حتى نتأكد ان العدد هو رقم زوجي) هكذا: assumeTrue(value1 % 2 == 0); assumeTrue(value2 % 2 == 0); assumeTrue( value1 != 0); assumeTrue( value2 != 0); والان كل ماينطبق عليه هذه الشروط من DataPoints سوف تقوم النظرية باستخدامه في الفعل (addition), وعكس ذلك سوف تقوم بتجاهله. ونلاحظ انها تجاهلة الصفر والاعداد الفردية (كما هو ظاهر في ناتج تشغيلها بالسابق). // Action int sumResult = mCalculator.addition(value1, value2); ثم ستقوم النظرية بالتأكد هل ناتج الجمع هو زوجي. // Assert assertTrue( sumResult % 2 == 0); وهكذا توصلنا الى الاعداد الذي يكون ناتج الجمع لهم زوجي. والحمد لله تم الانتهاء من هذه السلسلة التي تعتبر مدخل مناسب لمن يريد الدخول في عالم الاختبارات في تطوير تطبيقات الاندرويد, والذي سوف اتطرق له ان شاء الله في المستقبل في مقالات اخرى.
  4. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذه المقالة سنتعلم كيفية استخدام الـ Suites و Categories للتحكم في تشغيل الاختبارات حتى يتمكن المبرمج من التحكم بشكل ادق في ادارة و تشغيل اي من الاختبارات كما يتطلب الوضع, وبما انهم متشابهان في الوظيفة فأرى من الافضل التطرق لهم في مقالة واحدة. المواضيع السابقة (مهمة لفهم هذا المقال) هذه هي المقالات السابقة والتي تعتبر ضروريه لفهم هذا المقال فاذا لم تكن لديك خلفيه مع الـ JUnit انصحك بقرائتها قبل هذا الموضوع والذي يعتبر المقال الخامس من اصل ستة مقالات. رابط المشروع https://github.com/mzdhr/KidCalculator-JUnit وتوجد كلاسات هذه المقالة باسم: AdditionTest.class و SubtractionTest.class و MultiplicationTest.class و DivisionTest.class و AllMathematicalTest.java و MathematicalSuiteCategoriesTest في المشروع. واذا اردت الاطلاع على كلاس الـموديل فهذه هي Calculator.java. ماذا سوف تقرئ في هذه المقالة متى تستخدم الـ Suite, وكيفية انشاء مشغل Suites؟ متى تستخدم الـ Category, وطريقة انشاء فئة Category, وكيفية انشاء مشغل Category؟ واخيراً ماهو الفرق بين الـ Suite و Category؟ استخدام Suites في الـ JUnit نستخدم الـ Suite اذا كانت لدينا الكثير من كلاسات الاختبارات ونريد تشغيلهم في اّن واحد. تخيل ان لديك ٥٠ كلاس اختبار (امر محتمل جداً في المشاريع الحقيقه) فتشغيل هذه الكلاسات واحده بعد الاخرى يدوياً متعب جداً. ماذا لو تريد فقط تشغيل ٣٠ كلاس متفرقه منهم في كل مره تعمل تحديث لشفرة مشروعك كإظافة ميزه ما؟ فقرائة اسمائهم والتشغيل اليدوي لهم يعتبر متعب جداً, اذن مالحل؟ الحل هو انشاء Suite يقوم بضم جميع هذه الكلاسات, وحينها تحتاج فقط لتشغيل هذا الـ Suite. انشاء المزيد من كلاسات الاختبارات كلاساتنا السابقه لاتكفي! لذلك سنقوم بكتابة المزيد من الكلاسات حتى نطبق عليهم الـ Suite. والطريقة سهله جداً, فقط نقوم بإنشاء كلاسات جديده بجانب الكلاس الرئيسية (MainTest.java) وكتابة الاختبارات بهم. ماذا سننشئ؟ سننشئ اربعة كلاسات, كل كلاس تقوم بإختبار دالة (الجمع, الطرح, الضرب, القسمة) من الموديل Calculator بشكل اعمق, وهم كالتالي. AdditionTest.class لإختبار والتأكد من عمليات الجمع. SubtractionTest.class لإختبار والتأكد من عمليات الطرح. MultiplicationTest.class لإختبار والتأكد من عمليات الضرب. DivisionTest.class لإختبار والتأكد من عمليات القسمة. ومحتواهم كالتالي: كلاس الـ AdditionTest.class package com.company; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import static org.junit.Assert.assertEquals; public class MathematicalAdditionTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Orange"); } @Test public void addition_a_test(){ // Action int result = calculator.addition(6, 6); // Assert assertEquals(result, 12); // is result actually equal 12? } @Test public void addition_b_test(){ // Action int result = calculator.addition(-1, 8); // Assert assertEquals(result, 7); // is result actually equal 7? } @Test @Category({CategorySlowTest.class}) // Marking this Test as CategorySlowTest, you can add more Categories too. public void addition_c_test(){ // Action int result = calculator.addition(-1, -1); // Assert assertEquals(result, -2); // is result actually equal -2? } } كلاس الـ SubtractionTest.class package com.company; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; public class MathematicalSubtractionTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Yellow"); } @Test public void subtraction_a_test(){ // Action int result = calculator.subtraction(6, 7); // Assert assertEquals(result, -1); // is result actually equal -1? } @Test public void subtraction_b_test(){ // Action int result = calculator.subtraction(-1, -5); // Assert assertEquals(result, 4); // (-1) - (-5) = 4? } @Test public void subtraction_c_test(){ // Action int result = calculator.subtraction(10, 4); // Assert assertEquals(result, 6); // is result actually equal 6? } } كلاس الـ MultiplicationTest.class package com.company; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import static org.junit.Assert.assertEquals; @Category(CategorySlowTest.class) public class MathematicalMultiplicationTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Brown"); } @Test public void multiplication_a_test(){ // Action int result = calculator.multiplication(6, 6); // Assert assertEquals(result, 36); // is result actually equal 36? } @Test public void multiplication_b_test(){ // Action int result = calculator.multiplication(-1, 5); // Assert assertEquals(result, -5); // is result actually equal -5? } @Test public void multiplication_c_test(){ // Action int result = calculator.multiplication(-4, -4); // Assert assertEquals(result, 16); // is result actually equal 16? } } كلاس الـ DivisionTest.class package com.company; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; public class MathematicalDivisionTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Purple"); } @Test public void division_a_test(){ // Action int result = calculator.division(12, 6); // Assert assertEquals(result, 2); // is result actually equal 2? } @Test public void division_c_test(){ // Action int result = calculator.division(10, -2); // Assert assertEquals(result, -5); // is result actually equal -5? } } انشاء مشغل (Runner) اجنحة (Suites) والان سننشئ مشغل لكل هذه الكلاسات, والذي من خلال تشغيله يقوم بتشغيل جميع الاختبارات الموجودة بهذه الكلاسات الاربعه جميعاً. ماهو المشغل؟ المشغل عبارة عن كلاس عادية نقوم باستخدام النوتيشن RunWith فوقها, ثم نحدد نوع المشغل المراد بداخل هذه النوتيشن وهو Suite في حالتنا هذه. ثم نحدد لهذا الـ Suite الكلاسات المراد ضمها. كود كلاس مشغل الـ Suite package com.company; import org.junit.runner.RunWith; import org.junit.runners.Suite; // This is the important part, which is annotations this class. @RunWith(Suite.class) @Suite.SuiteClasses({ // List all test classes you want to run them in one time MathematicalAdditionTest.class, MathematicalSubtractionTest.class, MathematicalMultiplicationTest.class, MathematicalDivisionTest.class }) // Empty class public class MathematicalSuiteAllTest { } تعقيب قمنا بجعل هذه الكلاس AllMathematicalTest.java مشغل (Runner) بدلاً من المشغل الافتراضي الذي يأتي مع الـ JUnit. وذلك بتعليمها بالنوتشن RunWith. ثم بتحديد نوع المشغل الذي نريده وهو Suite.class وهكذا اصحبت مشغل اجنحه Suite. ثم نقوم بكتابة جميع الكلاسات المراد تشغيلها بداخل النوتيشن SuiteClasses. ونستطيع انشاء عناصر منها كمشغلات في اكوادنا لاحقاً اذا دعت الحاجة لذلك. تشغيل مشغل الـ Suite اسرع خيار لتشغيله هو من خلال الضغظ على السهم الدائري بجانب اسم الكلاس, كما بالصوره التالي: نتيجة تشغيل مشغل الـ Suite تعقيب قبل كل شئ لاتهتم للنص ذي الون الاحمر! فهو خطئ يحدث فقط في نظام الماك ولا يؤثر بشئ. الان نرى من تشغيل هذا المشغل انه قام بتشغيل جميع الاختبارات بداخل الكلاسات الاربع, كما هو واضح بالصوره السابقه في جهة اليمين, وجميع اختباراتهم قد نجحوا. وهكذا نستطيع اختصار الوقت بأنشاء مشغل لكلاسات عديده او لكلاسات محدده كما تدعو الحاجة في اختبارات مشاريعنا. فمثلاً عند اضافة ميزة جديده في مشروعك خاصة باستخدام الانترنت, فأنت تريد فقط تشغيل الكلاسات التي تحتوي على اختبارات مرتبطه بالانترنت لترى هل مشروعك صامد ام لا. ولكن ماذا لو اردنا ان نشغل فقط بعض من دوال الاختبارات وليس الكلاسات بأكملها؟ هنا يأتي دور الـ Categories كما سيتضح في القسم التالي. استخدام Categories في الـ JUnit نستخدم الـ Categories اذا كانت لدينا دوال اختبار متفرقه سواء بكلاسات عديدة او بنفس الكلاس ونريد تحديدهم ومن ثم تشغيلهم في وقت واحد وبضغطة زر واحده. فبعض الاحيان لانريد تشغيل كل دوال الاختبار في الكلاس بل فقط البعض منهم. فالـ Categories مشابه جداً لعمل الـ Suite, بل هو في الحقيقه مشغل Suite كالسابق ولكنه يمتاز عليه بانه يستطيع قرائة نوتيشن اسمه Category يوضع فوق دوال الاختبار. انشاء فئات (Categories) خاصة بنا حتى تستطيع استخدام هذا النوع من المشغلات, يجب علينا ان ننشئ فئاتنا الخاصه والتي من خلالهم سوف نقوم بتعليم اي دالة اختبار بما يناسبها حسب احتياجاتنا. في هذا المشروع KidCalculator سنقوم بأنشاء فئتين Categories وهم كالتالي: CategoryFastTest.java, وهي عباره عن انترفيس فارغة, سنحتاجها لتوسيم دوال الاختبار السريعه لدينا. CategorySlowTest.java, وهي عباره عن انترفيس فارغة, سنحتاجها لتوسيم دوال الاختبار البطيئه لدينا. كود الـ CategoryFastTest.java package com.company; public interface CategoryFastTest { } كود الـ CategorySlowTest.java package com.company; public interface CategorySlowTest { } انشاء مشغل (Runner) فئات (Categories) الان سوف ننشئ مشغل الفئات (Categories). العملية مشابهه لإنشاء مشغل Suite ولكن الفرق هنا اننا سنقوم بإضافة نوتيشن مسؤول عن الفئات. كود كلاس المشغل package com.company; import org.junit.experimental.categories.Categories; import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Categories.class) // This Runner runs only @Tests Methods that annotated with CategorySlowTest.java. @Categories.IncludeCategory(CategorySlowTest.class) // If you want to exclude any Category use: // @Categories.ExcludeCategory(CategorySlowTest.class) @Suite.SuiteClasses({ MainTest.class, // Or we can use our last Suite -> MathematicalSuiteAllTest.class ... // ... that contains all these four classes: MathematicalAdditionTest.class, MathematicalSubtractionTest.class, MathematicalMultiplicationTest.class, MathematicalDivisionTest.class }) public class MathematicalSuiteCategoriesTest { } تعقيب قمنا بجعل هذه الكلاس MathematicalSuiteCategoriesTest مشغل (Runner) بدلاً من المشغل الافتراضي الذي يأتي مع الـ JUnit. وذلك بتعليمها بالنوتشن RunWith. ثم قمنا بتحديد نوع المشغل الذي نريده وهو Categories.class وهكذا اصبح مشغل فئات Categories. ومن ثم اضافة النوتيشن IncludeCategory واعطائه الفئه التي نريد منه ان يشغلها (اعطيناه الانترفيس السابقه التي انشئناها CategorySlowTest.java كفئه). ثم نقوم بكتابة جميع كلاسات الاختبار لدينا بداخل النوتيشن suiteClasses. ونستطيع انشاء عناصر منها كمشغلات في اكوادنا لاحقاً اذا دعت الحاجة لذلك. وضع فئات لدوال الاختبارات والان لنعلم بعض من دوال الاختبارات التي لدينا, بأضافة النوتيشن Category فوقها, ثم الاتيان بالفئه المراده (وهي التي انشئناها CategorySlowTest.java حتى نعلم هذه الدالة بانها بطيئه), كما بالكود التالي: @Test // Marking this Test as CategorySlowTest, you can add more Categories too. @Category({CategorySlowTest.class}) public void addition_c_test(){ // Action int result = calculator.addition(-1, -1); // Assert assertEquals(result, -2); // is result actually equal -2? } تعقيب هذه الدالة موجودة بداخل الكلاس MathematicalAdditionTest.java. نحن قمنا بوضع النوتيشن Category فوقها, وتعليمها بانها دالة بطيئه باستخدام الفئه CategorySlowTest.java التي انشئناها سابقاً بداخل هذا النوتيشن. وضع فئات لكلاس اختبارات بأكملها وكذلك نستطيع وضع فئات على الكلاسات وليس فقط على الدوال, كما بالكود التالي: @Category(CategorySlowTest.class) public class MathematicalMultiplicationTest { تعقيب هذه الكلاس هي MathematicalMultiplicationTest.java. قمنا بوضع النوتيشن Category فوقها, وتعليمها بانها كلاس بطيئه باستخدام الفئه CategorySlowTest.java التي انشئناها سابقاً بداخل هذا النوتيشن. تشغيل مشغل الـ Categories اسرع خيار لتشغيله هو من خلال الضغظ على السهم الدائري بجانب اسم كلاسه, كما بالصوره التالي: نتيجة تشغيل المشغل Category تعقيب نلاحظ ان الدالة addition_c_test التي قمنا بتعليمها بالنوتيشن Category ووضعنا فئتها: CategorySlowTest.java قد تم تشغيلها. وايضاً نلاحظ ان جميع دوال الكلاس MathematicalMultiplicationTest.java قد تم تشغيلهم وذلك بسبب وضع النوتيشن Category وتحديد فئة الكلاس بـ CategorySlowTest.java فوق اسم الكلاس. والفائده من هذا هي اذا كان لدينا اي اختبار بطئ فنستطيع وضعه ضمن فئة الاختبارات البطيئه, ومن ثم التعديل على الشفره البرمجيه لمشروعنا ونعيد تشغيل هذه الاختبارات البطيئه لنرى هل اصبحت سريعه ام لا. في النهاية تعلمنا كيفية استخدام مشغلات الـ Suite و Category وكيفية انشائهم, وهذا يعتبر شئ مهم عندما تريد التحكم في تشغيل اي من الاختبارات.
  5. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذه المقالة سنتعلم كيفية استخدام القواعد (Rules) في الـ JUnit والتي تسمح لنا بأضافة سلوك (behavior) جديد او التغيير في بعض السلوكيات على دوال الاختبارات. المواضيع السابقة (مهمة لفهم هذا المقال) هذه هي المقالات السابقة والتي تعتبر ضروريه لفهم هذا المقال فاذا لم تكن لديك خلفيه مع الـ JUnit انصحك بقرائتها قبل هذا الموضوع والذي يعتبر المقال الرابع من اصل ستة مقالات. رابط المشروع https://github.com/mzdhr/KidCalculator-JUnit وتوجد كلاسات هذه المقالة باسم: RuleTest.java و RuleWatchEye.java في المشروع. واذا اردت الاطلاع على كلاس الـموديل فهذه هي Calculator.java. ماذا سوف تقرئ في هذه المقالة ماهي القواعد Rule و كيفية استخدامها؟ ما الفرق بين النوتيشن ClassRule و Rule وكيفية استخدامهم ومتى؟ امثله لإستخدام بعض من القواعد كقاعدة الـ Timeout و الـ TestName و الـ ErrorCollector. واخيراً كيفية انشاء قاعدة خاصة بنا؟ ماهي القواعد (Rule) للـ JUnit هي عبارة عن عناصر منئشه من كلاس قاعدي (اي كلاس يعمل implements للإنترفيس TestRule يعتبر كلاس قاعدي). فأنت تقوم بأنشائها كـ Field في كلاس الاختبارات. كيفية استخدام هذه القواعد Rules في الـ JUnit بعد انشاء عنصر من كلاس قاعدي كـ Field في كلاس الاختبارات, تضع فوقه النوتيشن Rule او ClassRule وبهذا تصبح هذه القاعدة مطبقه على جميع دوال الاختبارات التي بداخل الكلاس او على الكلاس نفسها. قائمة بجميع القواعد الموجوده في الـ JUnit هذه كلاسات قواعد معده مسبقاً, وجاهزه لإنشاء عناصر منها واستخدامها مع النوتيشن Rule و ClassRule في كلاس اختباراتك. TemporaryFolder لإنشاء ملفات ومجلدات وهميه, لإستخدامهم عند الحاجة اثناء كتابة الاختبارات. ExternalResource مثل سابقتها, ولكن هنا تنشئ عناصر وهميه مثل التعامل مع: socket و server و database connection الخ... ErrorCollector تسمح لدوال الاختبار بالاستمرار للنهاية, حتى مع حدوث خطئ لاتتوقف, وتقوم بجمع كل الاخطاء ومن ثم عرضهم. Verifier اذا اردت ان تتحقق من شئ قبل بداية الاختبارات, مثلاً هل شبكة الانترنت متصلة ام لا. TestWatchman/TestWatcher تسمح لك هذه القاعدة بمراقبة دوال الاختبارات و طباعة Log في الكونسول للمراقبة, مثلاً هل بدء الاختبار؟ هل انتهى؟ هل نجح ام فشل؟. TestName اذا اردت الحصول على اسم دالة الاختبار فهذه القاعدة هي المسؤله عن ذلك, مثلاً تستطيع من خلالها طباعة اسم دالة الاختبار من داخلها. Timeout لوضع حد زمني لدوال الاختبارات, على ان تكتمل كل دالة قبل الوصول لذلك الزمن وإلا تفشل. ExpectedException تسمح لك بالحصول على تحكم اكثر في رسالة ونوع الـ exception المرمي في دالة الاختبار. RuleChain لربط القواعد مع بعضها البعض. قائمة بـ نوتيشنات الخاصه للقواعد (annotation) الموجوده في الـ JUnit Rule تستخدم لتطبيق القاعدة على جميع دوال الاختبارات. ClassRule تستخدم لتطبيق القاعدة على كلاس الاختبارات فقط وليس على دوالها. استخدام النوتيشن ClassRule مع القاعدة Timeout أستخدام النوتيشن ClassRule والذي من خلاله نستطيع تطبيق اي قاعده يأتي فوقها على الكلاس نفسها وليس على دوالها. اما القاعدة Timeout فهي تسمح لتحديد وقت (بأجزاء الثانية) حتى ينتهي الاختبار في مدة هذا الوقت والا يعتبر الاختبار فاشل. المثال // Rule for Class @ClassRule public static TestRule timeout = Timeout.millis(5000); تعقيب بانشاء هذا الـ Field من كلاس القاعدة Timeout وتحديد النوتيشن له بـ ClassRule (لاحظ انه static لانه يعود للكلاس نفسها) فهذا يعني: أن كلاس الاختبارات يجب ان تنهي جميع اختباراتها في اقل من ٥ ثواني, والا تعتبر الاختبارات بها فاشله. اذن متى نستخدم النوتيشن الـ ClassRule؟ اذا اردنا ان نطبق قاعدة على الكلاس نفسها, و ايضاً اذا اردنا من القاعدة ان تعمل لمره واحده فقط. مثلاً عندما تريد الاتصال بالانترنت قبل عمل كلاس الاختبارات هذه ثم اطفاء الانترنت عند نهايتها, او اذا كنت تريد تشغيل السيرفر لتجهيزه قبل عمل كلاس الاختبارات هذه ثم اطفائه عند نهايتها, فـ ClassRule مناسبه جداً. استخدام النوتيشن Rule مع القاعدة Timeout هنا سنستخدم نفس القاعدة Timeout لتحديد فتره زمنيه, ولكن ليس على الكلاس! بل على جميع دوال الاختبارات باستخدام النوتيشن Rule كما بالمثال التالي. المثال // Rules for @Test Methods @Rule public final TestRule timeoutForMethods = Timeout.millis(1005); تعقيب بانشاء هذا الـ Field من كلاس القاعدة Timeout وتحديد النوتيشن له بـ Rule فهذا يعني: أن اي دالة اختبار تأتي بالنوتيشن Test عليها ان تنهي عملها قبل تخطي هذا الوقت وهو تقريباً ثانيه, والا سوف تفشل. اذن متى نستخدم النوتيشن الـ Rule؟ اذا اردنا ان نطبق قاعدة على كل الدوال, بمعنى اخر ان هذه القاعده سوف تعمل بعدد كل دوال الاختبارات المعلمه بالنوتيشن Test في كلاس الاختبارات. فاذا قمت باستخدام هذا النوتيشن لقاعدة تقوم بالاتصال بالانترنت وقطعه, فانك سوف تقوم بتكرار هذه العمليه لكل دالة اختبار. استخدام النوتيشن Rule مع القاعدة TestName مثال اخر لإستخدام النوتيشن Rule مع قاعدة اخرى وهي TestName, وكما جاء سابقاً للـ "TestName: اذا اردت الحصول على اسم دالة الاختبار فهذه القاعدة هي المسؤله عن ذلك, مثلاً تستطيع من خلالها طباعة اسم دالة الاختبار من داخلها." المثال لأنشائها @Rule public final TestName testName = new TestName(); تعقيب عباره عن Field بكلاس الاختبارات. المثال لإستخدامها @Test public void method_name_test(){ System.out.println("This message printed from method -> " + testName.getMethodName()); } الناتج This message printed from method -> method_name_test تعقيب قمنا باستخدام الفيلد testName بداخل دالة الاختبار "method_name_test", لطباعة اسمها. استخدام النوتيشن Rule مع القاعدة ErrorCollector مثال اخر لإستخدام النوتيشن Rule مع قاعدة اخرى وهي ErrorCollector , وكما جاء سابقاً للـ "ErrorCollector: تسمح لدوال الاختبار بالاستمرار للنهاية, حتى مع حدوث خطئ لاتتوقف, وتقوم بجمع كل الاخطاء ومن ثم عرضهم." المثال لإنشائها @Rule public final ErrorCollector errorCollector = new ErrorCollector(); تعقيب عباره عن Field بكلاس الاختبارات. المثال لإستخدامها @Test public void error_collector_test(){ // Action int result01 = calculator.addition(2,2); int result02 = calculator.addition(3,3); int result03 = calculator.addition(4,4); // Assertion errorCollector.checkThat(result01, is(3)); // wrong errorCollector.checkThat(result02, is(3)); // wrong errorCollector.checkThat(result03, is(3)); // wrong } النتيجه تعقيب قمنا باستخدام الفيلد errorCollector مع الدالة checkThat واعطيناه ثلاثة احتمالات خاطئه عمداً, لنرى هل يقوم فقط بالتحقق من الاحتمال الاول ثم يفشل ويوقف الاختبار! كما سنرى كيف يحصل مع الداله assertThat لاحقاً! ام يكمل ويأتينا بالاخطاء كلها (نعم اتى بالاخطاء كلها). الاستخدام بدون القاعدة الـ Error Collector @Test public void no_error_collector_test(){ // Action int result01 = calculator.addition(2,2); int result02 = calculator.addition(3,3); int result03 = calculator.addition(4,4); // Assertion assertThat(result01, is(3)); // wrong assertThat(result02, is(3)); // wrong assertThat(result03, is(3)); // wrong } النتيجه تعقيب بدون استخدام القاعدة ErrorCollector فنحن سنحصل فقط على اول خطئ ثم يتوقف عمل دالة الاختبار. انشاء قاعدة خاصة بنا واستخدام النوتيشن Rule معها ماذا لو ان القواعد المدمجه مع الـ JUnit لم تلبي رغبة كتابة اختباراتك لمشروعك! وتحتاج المزيد او غيرها من القواعد؟ اذن في هذه الحاله تستطيع ان تنشئ قاعدتك الخاصة كما سيأتي. ماهي وظيفة القاعدة التي سوف ننشئها؟ سننشئ قاعدة تقوم بإضافة سلوك اضافي لكل دالة اختبار لدينا. وهذا السلوك هو: ان كل دالة اختبار تقوم بطباعة ثلاثة اشياء: اسمها و اسم كلاسها و كم استغرقت من وقت. خطوات انشاء قاعدة خاصة في الـ JUnit انشاء كلاس اختبارات جديدة في مسار مجلد الاختبارات. عمل implements للـ interface التاليه TestRule. عمل Override للدالة apply. انشاء عنصر جديد من كلاس الـ Statement وجعل الدالة apply تقوم بإرجاعه. وهذا العنصر يحتوي على الدالة evaluate والتي بداخلها سوف نقوم بكتابة الكود الذي سيضيف هذا السلوك الجديد لدوال الاختبارات. الكود (كلاس القاعدة الخاصة بنا) package com.company; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; public class RuleWatchEye implements TestRule { @Override public Statement apply(Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { // ---------- Write Behavior ---------- long start = System.currentTimeMillis(); try { // This code will run when each of @Test Methods runs. base.evaluate(); // Trigger for our @Test Methods code's. System.out.println(); System.out.println("Method ---> " + description.getMethodName()); System.out.println("In Class ---> " + description.getTestClass().getName()); } finally { // This code will run when each of @Test Methods is finish running. System.out.println("Takes ---> " + (System.currentTimeMillis() - start) + " Millisecond"); } // ---------- End of Behavior ---------- } }; } } تعقيب العمل كله يحدث داخل الدالة "evaluate" حيث اننا قمنا بأنشاء العنصر start وجعلناه يخزن وقت البدء. ثم بداخل الـ Try قمنا بكتابة ماذا نريد ان يتم عند تشغيل اي دالة اختبارات. وفي الـ finally قمنا بكتابة ماذا نريد ان يتم عند الانتهاء من تشغيل اي دالة اختبارات. ولاتنسى قرائة التعليقات الموجودة بالكود للإيضاح اكثر, وايضاً قرائة خطوات الانشاء السابقه حتى يسهل الفهم. طريقة الاستخدام // Custom Rule @Rule public final RuleWatchEye ruleWatchEye = new RuleWatchEye(); تعقيب فقط نقوم بعمل عنصر كـ Field منها في كلاس اختباراتنا. ونضع فوقه النوتيشن Rule, وعند تشغيل اي دالة اختبار فسوف يتم تفعيل قاعدتنا عليها. الناتج Method ---> time_out_annotation_test In Class ---> com.company.RuleTest Takes ---> 803 Millisecond تعقيب تم تشغيل الدالة time_out_annotation_test في كلاس الاختبارات RuleTest.java بشكل عادي, وتمت طباعة هذه الاسطر الثالثه السابقه, اذن قاعدتنا تعمل بشكل ممتاز. واذا اردت ان تقوم بطباعة جميع المعلومات للدوال الاخرى فقط قم بتشغيل الكلاس بأكملها. ونستطيع ايضاً استخدام هذه القاعد (وذلك فقط بانشاء عنصر منها كـ Field) في كلاسات اختباراتنا الاخرى. الكود الكامل لكلاس الاختبارات للقواعد في هذه المقالة package com.company; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ErrorCollector; import org.junit.rules.TestName; import org.junit.rules.TestRule; import org.junit.rules.Timeout; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; public class RuleTest { // Fields private Calculator calculator; // Rule for Class @ClassRule public static TestRule timeout = Timeout.millis(5000); // Rules for @Test Methods @Rule public final TestRule timeoutForMethods = Timeout.millis(1005); @Rule public final TestName testName = new TestName(); @Rule public final ErrorCollector errorCollector = new ErrorCollector(); // Custom Rule @Rule public final RuleWatchEye ruleWatchEye = new RuleWatchEye(); @Before public void setUp() { // Arrange calculator = new Calculator("Yellow"); } @Test(timeout = 1000) public void time_out_annotation_test() throws InterruptedException { Thread.sleep(800); } @Test public void time_out_global_annotation_test() throws InterruptedException { Thread.sleep(800); } @Test public void error_collector_test(){ // Action int result01 = calculator.addition(2,2); int result02 = calculator.addition(3,3); int result03 = calculator.addition(4,4); // Assertion errorCollector.checkThat(result01, is(3)); // wrong errorCollector.checkThat(result02, is(3)); // wrong errorCollector.checkThat(result03, is(3)); // wrong } @Test public void no_error_collector_test(){ // Action int result01 = calculator.addition(2,2); int result02 = calculator.addition(3,3); int result03 = calculator.addition(4,4); // Assertion assertThat(result01, is(3)); // wrong assertThat(result02, is(3)); // wrong assertThat(result03, is(3)); // wrong } @Test public void method_name_test(){ System.out.println("This message printed from method -> " + testName.getMethodName()); } } في النهاية تعلمنا كيفية استخدام النوتيشن Rule و ClassRule والفرق بينهم. وتطرقنا الى بعض من الامثله للقواعد المدمجة البسيطه (لتسهيل الفهم) مع الـ JUnit كـ ErrorCollector و TestName و Timeout (للإطلاع على المزيد من الامثله لهذه القواعد), وكيفية استخدامهم مع هذه النوتيشنات. وايضاً تعلمنا كيفية انشاء قاعدة خاصة بنا وكيفية استخدامها وتطبيقها في كلاسات اختباراتنا.
  6. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذه المقالة سنتعلم كيفية استخدام الـ JUnitMatchers, لتسهيل كتابة الاختبارات وقرائتها (وخاصة الدالة "assertThat" والتي هي صلب الموضوع). وهو يأتي مع مكتبة الـ JUnit بشكل اساسي, حيث انك لاتحتاج لتثبيت اي ملف jar او اضافة اي اعتمادية لمشروعك. المواضيع السابقة (مهمة لفهم هذا المقال) هذه هي المقالات السابقة والتي تعتبر ضروريه لفهم هذا المقال فاذا لم تكن لديك خلفيه مع الـ JUnit انصحك بقرائتها قبل هذا الموضوع والذي يعتبر المقال الثالث من اصل ستة مقالات. رابط المشروع https://github.com/mzdhr/KidCalculator-JUnit وتوجد كلاس هذه المقالة باسم: MatcherAssertThatTest.java في المشروع. واذا اردت الاطلاع على كلاس الـموديل فهذه هي Calculator.java. ماذا سوف تقرئ في هذه المقالة ماهي انواع الـ Matchers المدعومة في الـ Junit؟ كيفية استخدام الـ JUnitMatchers وبالذات الدالة assertThat؟ كيفية التحقق من كلاس العنصر, وعكس ذلك؟ التحقق من ان العنصر ليس null؟ وايضاً ماهي الطريقة للتحقق من وجود عنصر نصي (string) بداخل عنصر نصي (string) اخر؟ هل هو في البداية ام في النهاية؟ وكيفية التحقق من عناصر الـ boolean؟ واخيراً كيفية التحقق من ان ArrayList تحتوي على عنصر محدد مسبقاً؟ انواع الـ Matchers في الـ JUnit JUnitMatchers والمسمى ايضاً بـ JUnit CoreMatchers وهذا ماسيتم شرحة في هذه المقالة. Hamcrest CoreMatchers لن يتم شرحة, ولكنه مشابه بشكل كبير للسابق, فالاثنين يحتويات على دالة assertThat. وهذا يسبب مشاكل, فاذا قمت بتثبيته ستواجة اختلاط في كتابة الاختبارات, فأنصح كبداية باستخدام النوع الاول اما اذا اردت التعمق فأنصح باستخدام النوع الثاني. ملاحظة: تم بناء النوع الاول وهو JUnitMatchers على النوع الثاني وهو Hamcrest ثم دعمة بشكل رسمي في الـ JUnit. استخدام الـ JUnitMatchers في الـ JUnit في الطريقة التقليدية القديمة تعودنا على كتابة الاختبارات بأستخدام الدالة assertEquals, اما الان فسوف نكتبها بالطريقة الجديدة باستخدام دالة الـ assertThat. مثال: الطريقة القديمة @Test public void assert_old_way(){ // Action int result = calculator.addition(10, 4); // Assert assertEquals(result, 14); } مثال: الطريقة الجديدة @Test public void assert_that_test() { // Action int result = calculator.addition(10, 4); // Assert assertThat(result, is(14)); } تعقيب في الطريقة الجديدة استخدمنا دالة assertThat مع دالة is وهذا يسهل علينا الامر كثيراً. وكأننا نقول هل قيمة الـ result هي 14؟ اذا نعم فالاختبار يعتبر ناجح. وايضاً يمكننا اضافة تعليق لها كما سيأتي. اضافة تعليق للإختبار @Test public void assert_with_message_test(){ // Action int result = calculator.addition(10, 10); // Assert assertThat("This is a message, shows when test failed!", result, is(20)); } تعقيب عند فشل الاختبار فسوف تظهر هذه الرسالة, حيث اننا نستطيع استخدامها لتسهيل علينا تتبع الفشل, كما بالمقال الاول. التحقق من كلاس العنصر @Test public void assert_is_type_x_class_test(){ // Action int result = calculator.addition(10, 5); // Assert assertThat(result, isA(Integer.class)); } تعقيب باستخدام الدالة isA بداخل الدالة assertThat قمنا بالتحقق هل العنصر result هو في الحقيقة من نوع الـ Integer ام لا. وعكس ذلك كما سيأتي لاحقاً. التحقق ان العنصر ليس من كلاس محدده @Test public void assert_not_type_x_class_test(){ // Action int result = calculator.addition(10, 4); // Assert assertThat(result, is(not(instanceOf(Double.class)))); } تعقيب قمنا بالتحقق هل العنصر result ليس من كلاس Double؟ وتم هذا التحقيق باستخدام الدالة is مع دالة النفي not ومن ثم دالة instanceOf التي بدورها تأخد نوع الكلاس المراد التحقق منها. التحقق ان العنصر لايحمل null كقيمة له @Test public void assert_not_null_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, is(notNullValue())); } تعقيب قمنا بالتحقق باستخدام الدالة is والدالة notNullValue, اي كاننا نقول هل العنصر result لا يحمل قيمة null. يوجد عكس هذه الداله وهي nullValue اذا اردت ان تتحقق من ان العنصر يحمل بالفعل قيمة null. التحقق ان عنصر String يحتوي على عنصر String اخر @Test public void assert_contains_string_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, containsString("e")); } تعقيب باستخدام الدالة containsString, قمنا بالتحقق من العنصر color هل يحتوي على حرف الـ e بداخله. طبعاً سينجح الاختبار لإن color يحتوي على قيمة "Red" مسبقاً. التحقق بان العنصر String يحتوي على اي من هذه العناصر الاخرى @Test public void assert_contains_any_with_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, anyOf(containsString("S"), containsString("B"), containsString("d"))); } تعقيب في هذا المثال استخدمنا الدالة anyOf ثم اتينا بسلسه من الدوال containsString للتحقق من اذا كان العنصر color يحتوي على اي منهم. طبعاً سينجح الاختبار لإن اللون color هو عنصر String يحتوي على قيمة "Red" و لإن الاختبار سيرى قيمة "d" بداخله. التحقق ان العنصر String يبدئ بهذه الحروف @Test public void assert_start_with_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, startsWith("R")); // there is also -> endsWith() } تعقيب مشابه للسابقين, ولكن هنا تحققنا ان العنصر color يبدئ بالحرف R باستخدام الدالة startsWith. وايضاً توجد دالة اخرى تقوم بالعكس وهي الدالة endsWith. طبعاً سينجح الاختبار لإن عنصرنا color والذي يحتوي على قيمة "Red" يوجد به حرف "R" في بدايته. التحقق من عنصر boolean هل هو true @Test public void assert_true_test(){ // Action calculator.setOn(); boolean power = calculator.getPower(); // Assert assertThat(power, is(true)); } تعقيب باستخدام كلمة true بداخل الدالة is, قمنا بالتحقق هل ان العنصر power يحمل قيمة true بداخله. والعكس صحيح بالنسبه للتحقق من قيمة الـ false. التحقق من ان ArrayList تحتوي على عنصر محدد @Test public void assert_list_test(){ // Action int number01 = calculator.addition(1, 1); int number02 = calculator.addition(1, 2); int number03 = calculator.addition(1, 3); int number04 = calculator.addition(1, 4); ArrayList<Integer> myList = new ArrayList<>(); myList.add(number01); myList.add(number02); myList.add(number03); myList.add(number04); int itemWanted = 5; // Assert assertThat(myList, hasItem(itemWanted)); } تعقيب قمنا بانشاء اربعة عناصر باستخدام المودل calculator, ثم أضفناهم الى قائمة بأسم myList, وفي النهاية قمنا بانشاء عنصرنا المراد التحقق منه وهو itemWanted. وبأستخدام الدالة hasItem قمنا بهذا التحقق. الكلاس كاملة package com.company; import org.junit.Before; import org.junit.Test; import java.util.ArrayList; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; public class MatcherAssertThatTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Red"); } @Test public void assert_old_way(){ // Action int result = calculator.addition(10, 4); // Assert assertEquals(result, 14); } @Test public void assert_that_test() { // Action int result = calculator.addition(10, 4); // Assert assertThat(result, is(14)); } @Test public void assert_with_message_test(){ // Action int result = calculator.addition(10, 10); // Assert assertThat("This is a message, shows when test failed!", result, is(20)); } @Test public void assert_is_type_x_class_test(){ // Action int result = calculator.addition(10, 5); // Assert assertThat(result, isA(Integer.class)); } @Test public void assert_not_type_x_class_test(){ // Action int result = calculator.addition(10, 4); // Assert assertThat(result, is(not(instanceOf(Double.class)))); } @Test public void assert_not_null_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, is(notNullValue())); } @Test public void assert_contains_string_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, containsString("e")); } @Test public void assert_contains_any_with_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, anyOf(containsString("S"), containsString("B"), containsString("d"))); } @Test public void assert_start_with_test(){ // Action String color = calculator.getColor(); // Assert assertThat(color, startsWith("R")); // there is also -> endsWith() } @Test public void assert_true_test(){ // Action calculator.setOn(); boolean power = calculator.getPower(); // Assert assertThat(power, is(true)); } @Test public void assert_list_test(){ // Action int number01 = calculator.addition(1, 1); int number02 = calculator.addition(1, 2); int number03 = calculator.addition(1, 3); int number04 = calculator.addition(1, 4); ArrayList<Integer> myList = new ArrayList<>(); myList.add(number01); myList.add(number02); myList.add(number03); myList.add(number04); int itemWanted = 5; // Assert assertThat(myList, hasItem(itemWanted)); } } وكانت هذه اغلب الامثلة والدوال المهمة التي سوف تحتاجها في كتابة اختبارات أسهل بأستخدام دالة الـ assertThat بداخل الـ JUnitMatchers في اجراء الاختبارات مع مكتبة الـ JUnit. وللمزيد من المعلومات حول الـ matchers.
  7. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته هذه المقالة لتعلم كيفية كتابة اختبارات JUnit للغة الجافا بشكل مرتب وسلس حتى يشعر القارئ بالراحة وعدم الضياع في كلاس الاختبارات. هذا الموضوع عبارة عن تكملة للموضوع الرئيسي: كتابة اختبارات الـ JUnit بشكل محترف توجد اتفاقية (Conventions) لكتابة الاختبارات بشكل محترف لدى المبرمجين, حتى يسهل عليهم قرائتها والتعامل معها. وهذه الطريقة تسمى اختصاراً بالـ AAA. و ايضاً سأقوم بالتطرق الى بعض الملاحظات والتحذيرات عند كتابة دوال الاختبارات. AAA Style for Tests وتتكون هذه الطريقة من ثلاثة اقسام وهم: الـ Arrange (الترتيب) اي ترتيب وتجهيز العناصر لإجراء الاختبارات عليها. الـ Action (الفعل) اي السلوك للعناصر المراد اختبارها "يعني الدوال للــ Object". الـ Assert (التأكيد او الجزم) في هذه المرحلة نكتب الكود الذي من خلاله نتحقق من صحة المنطق لدينا. مثال @Test public void setting_calculator_color_test(){ // Arrange Calculator calculator = new Calculator("none"); // Action calculator.setColor("blue"); // Assert assertEquals(calculator.getColor(), "blue"); } التعقيب الترتيب: قمنا بانشاء عنصر حاسبة من موديل الـ Calculator. الفعل: قمنا بالنداء على الدالة setColor() لتحويل الحاسبة الى اللون الازرق. التأكيد: قمنا بكتابة شفرة الجزم المطلوبة باستخدام assertEquals, والذي من خلالها سنجزم ان لون حاسبتنا اصبح ازرق حتى ينجح الاختبار, والا فأن الفعل setColor به خلل منطقي. والان حتى لانكرر انشاء العنصر calculator كل مرة نقوم بكتابة دالة اختبار. فالافضل ان نحوله الى Field. ثم نقوم بكتابة الدالة setUp ذي النوتيشن Before والتي فيها ننشئ عناصرنا. لتصبح دالة الاختبار بهذا الشكل: @Test public void setting_calculator_color_test(){ // Action calculator.setColor("blue"); // Assert assertEquals(calculator.getColor(), "blue"); } اما باعلى الكلاس فالوضع اصبح هكذا: public class MainTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Red"); } ... ... ... تحذير: لاتقم باختبار فعلين في دالة واحده مثال @Test public void subtraction_multiplication_tests(){ // Action & Assert assertEquals(calculator.subtraction(10, 6), 4); // is 10 - 6 = 4 ? assertEquals(calculator.multiplication(6, 2), 12); // is 6 * 2 is 12 ? } تعقيب كتابة الاختبارات بهذا الشكل خاطئ جداً! لماذا؟ لاننا قمنا باختبار فعلين مختلفين وهم substraction() و multiplications() في دالة واحدة وهذا غير مستحسن. ففي حالة فشل هذا الاختبار فأننا لاندري اي فعل هو المسبب للفشل, وسيكون الـ debug صعب جداً بل مربك. فمن الافضل ان نقوم باختبار فقط فعل واحد في كل دالة اختبار قدر المستطاع. اذن لنضع على هذه الداله النوتيشن Ignore حتى يتجاهلها الـ JUnit مثال اخر اختبار خوارزمية القسمة العادية و خوارزمية القسمة المطولة في نفس الدالة. @Test public void divisions_test(){ // Action & Assert assertEquals(calculator.division(100, 2), 50); assertEquals(calculator.longDivision(100, 2), 50); } الناتج تعقيب هل تستطيع تحديد اي من الخوارزميات الخاطئة في المنطق؟ هل هي division ام longDivision ؟ هل رأيت صعوبة الامر للقارئ. الحل هو فصل الفعلين الى دالتين اختبار منفصلتين. ولكن الم تلاحظ تقارب بين الفعلين؟ القسمة العادية والقسمة المطولة؟ فهنا نستطيع المحافظة عليهم في نفس دالة الاختبار ونقوم بإظافة رسالة تسهل علينا الأمر في حالة التعطل. الحل هو بأضافة تعليق لكل سطر تأكيد في الداله كما التالي: @Test public void divisions_test(){ // Action & Assert assertEquals("Normal Division", calculator.division(100, 2), 50); assertEquals("Long Division", calculator.longDivision(100, 2), 50); } الناتج تعقيب من الصورة نرى ان الخوارزمية Long Division هي السبب لفشل الاختبار. وهكذا اصبح على القارئ و المبرمج اكتشاف الاخطاء اسهل بكثير. الكلاس كاملة package com.company; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.*; public class MainTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Red"); } @Test public void addition_test() { // Action int result = calculator.addition(2, 2); // Assert assertEquals(result, 4); // is result actually equal 4? } @Test public void subtraction_test() { // Action int result = calculator.subtraction(10, 4); // Assert assertEquals(result, 6); } @Test public void multiplication_test() { // Action int result = calculator.multiplication(5, 5); // Assert assertEquals(result, 25); } @Test public void division_test() { // Action int result = calculator.division(10, 2); // Assert assertEquals(result, 5); } @Test public void check_color_and_change_it_test(){ // Action if (calculator.getColor().equals("Red")){ calculator.setColor("Blue"); } // Assert // Check is color changed? assertEquals(calculator.getColor(), "Blue"); } @Ignore @Test public void check_color_is_still_changed(){ // Assert assertEquals(calculator.getColor(), "Blue"); } // --------------------------- // // --- New Tests - Part 02 --- // // --------------------------- // @Test public void setting_calculator_color_test(){ // Action calculator.setColor("blue"); // Assert assertEquals(calculator.getColor(), "blue"); // is calculator color actually blue? } @Ignore @Test public void subtraction_multiplication_tests(){ // Action & Assert assertEquals(calculator.subtraction(10, 6), 4); // is 10 - 6 = 4 ? assertEquals(calculator.multiplication(6, 2), 12); // is 6 * 2 is 12 ? } @Test public void divisions_test(){ // Action & Assert assertEquals("Normal Division", calculator.division(100, 2), 50); assertEquals("Long Division", calculator.longDivision(100, 2), 50); } @Test public void calculator_is_not_null_test(){ // Assert assertNotNull(calculator); } @Test public void check_calculator_power_test(){ // Assert & Action assertTrue(calculator.checkPower()); // is calculator is powered on? } } وهكذا تصبح قرائة الاختبارات اكثر سهولة وكتابتها ايضاً.
  8. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته هذه المقالة تمهيديه في شرح و كتابة اختبارات الـ Junit للغة الـ Java. والتي من خلالها اصبو الى كتابة المزيد من المقالات في مجال الاختبارات للجافا و للإندرويد في المستقبل ان شاء الله. لإني ارى ان هناك شح كبير جداً في هذا المجال و ان شاء الله اوفق ولو بسد جزء بسيط به, ولا ارى ضرر في كتابة الاخوان في هذا المجال لمن يريد, فالقارئ ربما يفهم من هذا المقال او من ذلك المقال. ماذا سوف تقرئ في هذه المقالة ماهي مكتبة الـ Junit وماهي متطلباتها؟ ماهي الطريقة التي تتم بها كتابة هذا النوع من الاختبارات؟ ماهي اهم الـ Annotations, و الـ Assertions المستخدمة في هذه المكتبة. مع امثلة برمجية وبعض الملاحظات لتقريب المفهوم. وسوف نرى كيفية انشاء مجلد خاص بهذه الاختبارات, وانشاء اول كلاس لكتابة الاختبارات به, ثم كيفية تشغيلها. ماهو الـ JUnit عبارة عن مكتبة لكتابة وتشغيل الاختبارات المتكرره بشكل سهل وسلس. الموقع الرسمي JUnit المتطلبات مكتبة الـ JUnit للإختبارات, الاصدار الرابع (مميزة هذا الاصدار انه مدعوم في الاندرويد كذلك, فجميع هذه الاكواد تعمل في الـ Android Studio بطلاقه). معرفة كيفية استخدام الـ Annotations الخاص بالـ JUnit. طريقة كتابة هذ النوع من الاختبارات يقوم على كتابة دالات اختبار Unit Test في كلاس خاصة بها, ومن خلالهم تقوم باختبار دالاتك الحقيقه في مشروعك. وكل من هذه الدالات الاختبارية يأتي فوقها Annotation خاص بالـ JUnit تحدده انت حسب الغرض. اهم الـ Annotations المستخدمة في اجراء اختبارات الـ JUnit هذا جدول يوضح اهم الـ Annotations التي سوف تحتاجها في كتابة دالات اختباراتك. من الافضل حفظهم عن ظهر قلب. مثال برمجي لتوضيح تسلسل عمل هذه الـ Annotations على دوال الاختبارات package com.company; import org.junit.*; public class MainTest { @BeforeClass public static void preSetup(){ System.out.println("preSetup() Runs!"); System.out.println("-----------------"); } @Before public void setup(){ System.out.println("setup() Runs - Preparing Object"); } @Test public void sum1_test(){ System.out.println("sum1_test() Runs"); } @Test public void sum2_test(){ System.out.println("sum2_test() Runs"); } @Ignore @Test public void sum3_test(){ System.out.println("sum3_test() Runs"); } @After public void clean(){ System.out.println("clean() Runs = Cleaning test environment"); } @AfterClass public static void postClean(){ System.out.println("-----------------"); System.out.println("postClean() Runs!"); } } الناتج preSetup() Runs! ----------------- setup() Runs - Preparing Object sum1_test() Runs clean() Runs = Cleaning test environment setup() Runs - Preparing Object sum2_test() Runs clean() Runs = Cleaning test environment Test ignored. ----------------- postClean() Runs! ملاحظات الدالتين setup و clean تم تشغيلهم اكثر من مره, لكل دالة اختبار, وهذا يعود لتطبيق النوتيشن After و Before اعلاهم. الدالتين preSetup و postClean تم تشغيلهم فقط مره واحده, لهذه الكلاس, وهذا يعود لتطبيق النوتيشن BeforeClass و AfterClass اعلاهم ويجب عندها ان يكونان static. دالة الاختبار المسمية بالـ sum3_test قد تم تجاهلها, وهذا يعود الى استخدام النوتيشن Ignore اعلاها. اما دوال الاختبار لدينا المسماه sum1_test و sum2_test فقد تم تشغيلهم بسلاسة ونجاح. انشاء بيئة الاختبارات الخاصة بالـ JUnit على مشروع جافا الان لنقم بإنشاء بيئة الاختبارات الخاصة بنا, والتي من خلالها سوف نقوم باختبار مشروعنا التجريبي (عباره عن حاسبة اطفال بلغة الجافا). هذه الطريقة تمكنك من انشاء بيئة الاختبار يدوياً Best Practice. قم بتشغيل برنامجك المفضل للجافا (في هذا الشرح IntelliJ IDEA). انشئ مشروع جافا جديد 1.8 ولاتنسى اختيار الـ Command Line App او اختر مشروع سابق. انشئ مجلد جديد في مسار مشروعك وسمه مثلاً test. علم هذا المجلد بانه خاص للإختبارات, حتى يفهم الـ IntelliJ IDEA. اذهب الى اسم كلاسك الرئيسية واضغظ عليها بالزر الايمن للماوس ومن القائمة اختر Go To ثم Test. اضغظ على Create New Test... في النافذة المنبثقة. ستظهر لك نافذة جديده للإختبارات, اختر مكتبة الـ JUnit 4 المتطابقة مع هذا الشرح. انتباه: اذا رأيت الرسالة JUnit4 library not found in the module اضغظ على Fix. ثم استخدم المكتبة الموجودة بمسار الـ IntelliJ او قم بتحميلها وتحديد مسار اخر لها. الخطوات بالصور حتى يسهل الأمر انشاء مجلد الاختبارات تعليم هذا المجلد وجعله خاص للإختبارات انشاء اول اختبار للكلاس الرئيسية ثم انشاء اختبار جديد تعديل الاعدادات واختيار مكتبة الاختبارات كأول مره فقط (لاتنسى اصلاح خلل ايجاد مسار المكتبة) اصلاح Fix خلل ايجاد مسار مكتبة JUnit على جهازك النتيجة, كلاس جاهزة انشئت لكتابة الاختبارات في المجلد التي قمت بتخصيصة الـ Assertions في الـ JUnit يأتي مع الـ JUnit دوال تسمى Assertions من خلالهم تستطيع اجراء الاختبارات, ويجب عليك حفظ وفهم هذه الدوال, كما هو الحال مع الـ Annotations. يمكنك الاطلاع عليهم من خلال هذا الرابط. اهم هذه الدوال هي: شرح المشروع قبل كتابة الاختبارات لنفهم هذا المشروع قليلاً. فأسم المشروع هو KidCalculator. وتستطيع ايجاد نسخة منه على رابط الجيت هوب لدي. يتكون من عدة كلاسات (حالياً) وهي: Main.java وهي الكلاس الرئيسية للمشروع. MainTest.Java وهي كلاس الاختبارات التي انشئناها بالخطوات السابقة. Calculator.Java وهي عبارة عن Model لكلاس الحاسبة لدينا, تحتوي على دوال الحاسبة كالجمع والطرح والقسمة والضرب الخ... والتي من خلالها سيبنى المشروع. BigNumberException كلاس exception خاص بالمشروع, حتى نستخدمها لاحقاً. سيكون عملنا فقط كتابة اكواد داخل كلاس الـ MainTest.Java بما ان الاختبارات هي الهدف من هذه المقالة. كتابة الاختبارات اولاً لنلقي نظرة على كلاس الـ Calculator حتى نفهم هذه الموديل package com.company; public class Calculator { private String mColor; private boolean mPower; public Calculator(String color) { mColor = color; } public String getColor() { return mColor; } public void setColor(String color) { mColor = color; } public boolean checkPower() { return mPower; } public void setOn() { mPower = true; } public void setOff() { mPower= false; } public int addition(int firstNumber, int secondNumber) { return firstNumber + secondNumber; } public int subtraction(int firstNumber, int secondNumber) { return firstNumber - secondNumber; } public int multiplication(int firstNumber, int secondNumber) { return firstNumber * secondNumber; } public int division(int firstNumber, int secondNumber) { return firstNumber / secondNumber; } } والان لنقم بكتابة الاختبارات لهذه الموديل لإختبار المنطق في اجراء العمليات الحسابية حسب ماتم برمجته في الكود السابق. package com.company; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; public class MainTest { private Calculator calculator; @Before public void setUp() { calculator = new Calculator("Red"); } @Test public void addition_test() { int result = calculator.addition(2, 2); assertEquals(result, 4); } @Test public void subtraction_test() { int result = calculator.subtraction(10, 4); assertEquals(result, 6); } @Test public void multiplication_test() { int result = calculator.multiplication(5, 5); assertEquals(result, 25); } @Test public void division_test() { int result = calculator.division(10, 2); assertEquals(result, 5); } } ملاحظات: استخدمنا هنا assertEquals وهي عباره عن دالة JUnit تاخد قيمة متوقعة (result) ثم تقارنها بالقيمة الحقيقة اي الصحيحة. قمنا بأنشاء عنصر من موديل حاسبتنا Calculator في دالة الـ setUp والتي تعمل قبل كل الدوال حتى تنشئ عنصرنا ونتمكن من استخدامه في باقي دوال الاختبارات. وتشغيل هذه الاختبار من خلال الضغظ بالزر الايمن على اسم الكلاس واختيار Run 'MainTest' او من خلال الايقونة الصغيره الخضراء كشكل السهم المستدير بجانب اسم الكلاس, كما بالصورة التالية: نتيجة الاختبار نجاح جميع الاختبارات كما هو متوقع. ملاحظة: لاتعير اهتمام للسطر الاحمر فهو خلل برمجي في الجافا, يحدث للماك وهذه اقتباس من احد العاملين بشركة اوراكل: المزيد من الاختبارات سوف نقوم بانشاء دالة تغير لون حاسبتنا وتتأكد من تغيير اللون. و أيضاً سنقوم بانشاء دالة اخرى تتاكد من هذا اللون, ثم نشغل جميع الدوال. ملاحظات: قمنا بكتابة و تشغيل ٦ اختبارات, ٥ نجحو, وواحد فشل. المهم هو ان الدالة check_color_and_change_it_test قد نجحت في تغيير اللون, ونجحت ايضاً في التأكيد من ان اللون قد تغير الى الازرق. اما الدالة check_color_is_still_changed قد فشلت في التأكيد من ان اللون قد اصبح ازرق؟ لماذا؟ اليست الدالة التي قبلها قد قامت بتغيير هذا اللون؟ وهكذا قمنا بأنشاء مجلد اختبارات + انشاء كلاس اختبارات + كتابة ٦ دوال اختبارات باستخدام بعض من الـ Annotations و Assert واحده وهي assertEquals. واتوقف هنا حتى لايصبح للقارئ overwhelming و burnout, واكمل في المقالات اللاحقة ان شاء الله.
  9. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته هذه المقالة لتعلم كيفية كتابة اختبارات JUnit للغة الجافا بشكل مرتب وسلس حتى يشعر القارئ بالراحة وعدم الضياع في كلاس الاختبارات. هذا الموضوع عبارة عن تكملة للموضوع الرئيسي: كتابة اختبارات الـ JUnit بشكل محترف توجد اتفاقية (Conventions) لكتابة الاختبارات بشكل محترف لدى المبرمجين, حتى يسهل عليهم قرائتها والتعامل معها. وهذه الطريقة تسمى اختصاراً بالـ AAA. و ايضاً سأقوم بالتطرق الى بعض الملاحظات والتحذيرات عند كتابة دوال الاختبارات. AAA Style for Tests وتتكون هذه الطريقة من ثلاثة اقسام وهم: الـ Arrange (الترتيب) اي ترتيب وتجهيز العناصر لإجراء الاختبارات عليها. الـ Action (الفعل) اي السلوك للعناصر المراد اختبارها "يعني الدوال للــ Object". الـ Assert (التأكيد او الجزم) في هذه المرحلة نكتب الكود الذي من خلاله نتحقق من صحة المنطق لدينا. مثال @Test public void setting_calculator_color_test(){ // Arrange Calculator calculator = new Calculator("none"); // Action calculator.setColor("blue"); // Assert assertEquals(calculator.getColor(), "blue"); } التعقيب الترتيب: قمنا بانشاء عنصر حاسبة من موديل الـ Calculator. الفعل: قمنا بالنداء على الدالة setColor() لتحويل الحاسبة الى اللون الازرق. التأكيد: قمنا بكتابة شفرة الجزم المطلوبة باستخدام assertEquals, والذي من خلالها سنجزم ان لون حاسبتنا اصبح ازرق حتى ينجح الاختبار, والا فأن الفعل setColor به خلل منطقي. والان حتى لانكرر انشاء العنصر calculator كل مرة نقوم بكتابة دالة اختبار. فالافضل ان نحوله الى Field. ثم نقوم بكتابة الدالة setUp ذي النوتيشن Before والتي فيها ننشئ عناصرنا. لتصبح دالة الاختبار بهذا الشكل: @Test public void setting_calculator_color_test(){ // Action calculator.setColor("blue"); // Assert assertEquals(calculator.getColor(), "blue"); } اما باعلى الكلاس فالوضع اصبح هكذا: public class MainTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Red"); } ... ... ... تحذير: لاتقم باختبار فعلين في دالة واحده مثال @Test public void subtraction_multiplication_tests(){ // Action & Assert assertEquals(calculator.subtraction(10, 6), 4); // is 10 - 6 = 4 ? assertEquals(calculator.multiplication(6, 2), 12); // is 6 * 2 is 12 ? } تعقيب كتابة الاختبارات بهذا الشكل خاطئ جداً! لماذا؟ لاننا قمنا باختبار فعلين مختلفين وهم substraction() و multiplications() في دالة واحدة وهذا غير مستحسن. ففي حالة فشل هذا الاختبار فأننا لاندري اي فعل هو المسبب للفشل, وسيكون الـ debug صعب جداً بل مربك. فمن الافضل ان نقوم باختبار فقط فعل واحد في كل دالة اختبار قدر المستطاع. اذن لنضع على هذه الداله النوتيشن Ignore حتى يتجاهلها الـ JUnit مثال اخر اختبار خوارزمية القسمة العادية و خوارزمية القسمة المطولة في نفس الدالة. @Test public void divisions_test(){ // Action & Assert assertEquals(calculator.division(100, 2), 50); assertEquals(calculator.longDivision(100, 2), 50); } الناتج تعقيب هل تستطيع تحديد اي من الخوارزميات الخاطئة في المنطق؟ هل هي division ام longDivision ؟ هل رأيت صعوبة الامر للقارئ. الحل هو فصل الفعلين الى دالتين اختبار منفصلتين. ولكن الم تلاحظ تقارب بين الفعلين؟ القسمة العادية والقسمة المطولة؟ فهنا نستطيع المحافظة عليهم في نفس دالة الاختبار ونقوم بإظافة رسالة تسهل علينا الأمر في حالة التعطل. الحل هو بأضافة تعليق لكل سطر تأكيد في الداله كما التالي: @Test public void divisions_test(){ // Action & Assert assertEquals("Normal Division", calculator.division(100, 2), 50); assertEquals("Long Division", calculator.longDivision(100, 2), 50); } الناتج تعقيب من الصورة نرى ان الخوارزمية Long Division هي السبب لفشل الاختبار. وهكذا اصبح على القارئ و المبرمج اكتشاف الاخطاء اسهل بكثير. الكلاس كاملة package com.company; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.*; public class MainTest { // Fields private Calculator calculator; @Before public void setUp() { // Arrange calculator = new Calculator("Red"); } @Test public void addition_test() { // Action int result = calculator.addition(2, 2); // Assert assertEquals(result, 4); // is result actually equal 4? } @Test public void subtraction_test() { // Action int result = calculator.subtraction(10, 4); // Assert assertEquals(result, 6); } @Test public void multiplication_test() { // Action int result = calculator.multiplication(5, 5); // Assert assertEquals(result, 25); } @Test public void division_test() { // Action int result = calculator.division(10, 2); // Assert assertEquals(result, 5); } @Test public void check_color_and_change_it_test(){ // Action if (calculator.getColor().equals("Red")){ calculator.setColor("Blue"); } // Assert // Check is color changed? assertEquals(calculator.getColor(), "Blue"); } @Ignore @Test public void check_color_is_still_changed(){ // Assert assertEquals(calculator.getColor(), "Blue"); } // --------------------------- // // --- New Tests - Part 02 --- // // --------------------------- // @Test public void setting_calculator_color_test(){ // Action calculator.setColor("blue"); // Assert assertEquals(calculator.getColor(), "blue"); // is calculator color actually blue? } @Ignore @Test public void subtraction_multiplication_tests(){ // Action & Assert assertEquals(calculator.subtraction(10, 6), 4); // is 10 - 6 = 4 ? assertEquals(calculator.multiplication(6, 2), 12); // is 6 * 2 is 12 ? } @Test public void divisions_test(){ // Action & Assert assertEquals("Normal Division", calculator.division(100, 2), 50); assertEquals("Long Division", calculator.longDivision(100, 2), 50); } @Test public void calculator_is_not_null_test(){ // Assert assertNotNull(calculator); } @Test public void check_calculator_power_test(){ // Assert & Action assertTrue(calculator.checkPower()); // is calculator is powered on? } } وهكذا تصبح قرائة الاختبارات اكثر سهولة وكتابتها ايضاً.
  10. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته هذه المقالة تمهيديه في شرح و كتابة اختبارات الـ Junit للغة الـ Java. والتي من خلالها اصبو الى كتابة المزيد من المقالات في مجال الاختبارات للجافا و للإندرويد في المستقبل ان شاء الله. لإني ارى ان هناك شح كبير جداً في هذا المجال و ان شاء الله اوفق ولو بسد جزء بسيط به, ولا ارى ضرر في كتابة الاخوان في هذا المجال لمن يريد, فالقارئ ربما يفهم من هذا المقال او من ذلك المقال. ماذا سوف تقرئ في هذه المقالة ماهي مكتبة الـ Junit وماهي متطلباتها؟ ماهي الطريقة التي تتم بها كتابة هذا النوع من الاختبارات؟ ماهي اهم الـ Annotations, و الـ Assertions المستخدمة في هذه المكتبة. مع امثلة برمجية وبعض الملاحظات لتقريب المفهوم. وسوف نرى كيفية انشاء مجلد خاص بهذه الاختبارات, وانشاء اول كلاس لكتابة الاختبارات به, ثم كيفية تشغيلها. ماهو الـ JUnit عبارة عن مكتبة لكتابة وتشغيل الاختبارات المتكرره بشكل سهل وسلس. الموقع الرسمي JUnit المتطلبات مكتبة الـ JUnit للإختبارات, الاصدار الرابع (مميزة هذا الاصدار انه مدعوم في الاندرويد كذلك, فجميع هذه الاكواد تعمل في الـ Android Studio بطلاقه). معرفة كيفية استخدام الـ Annotations الخاص بالـ JUnit. طريقة كتابة هذ النوع من الاختبارات يقوم على كتابة دالات اختبار Unit Test في كلاس خاصة بها, ومن خلالهم تقوم باختبار دالاتك الحقيقه في مشروعك. وكل من هذه الدالات الاختبارية يأتي فوقها Annotation خاص بالـ JUnit تحدده انت حسب الغرض. اهم الـ Annotations المستخدمة في اجراء اختبارات الـ JUnit هذا جدول يوضح اهم الـ Annotations التي سوف تحتاجها في كتابة دالات اختباراتك. من الافضل حفظهم عن ظهر قلب. مثال برمجي لتوضيح تسلسل عمل هذه الـ Annotations على دوال الاختبارات package com.company; import org.junit.*; public class MainTest { @BeforeClass public static void preSetup(){ System.out.println("preSetup() Runs!"); System.out.println("-----------------"); } @Before public void setup(){ System.out.println("setup() Runs - Preparing Object"); } @Test public void sum1_test(){ System.out.println("sum1_test() Runs"); } @Test public void sum2_test(){ System.out.println("sum2_test() Runs"); } @Ignore @Test public void sum3_test(){ System.out.println("sum3_test() Runs"); } @After public void clean(){ System.out.println("clean() Runs = Cleaning test environment"); } @AfterClass public static void postClean(){ System.out.println("-----------------"); System.out.println("postClean() Runs!"); } } الناتج preSetup() Runs! ----------------- setup() Runs - Preparing Object sum1_test() Runs clean() Runs = Cleaning test environment setup() Runs - Preparing Object sum2_test() Runs clean() Runs = Cleaning test environment Test ignored. ----------------- postClean() Runs! ملاحظات الدالتين setup و clean تم تشغيلهم اكثر من مره, لكل دالة اختبار, وهذا يعود لتطبيق النوتيشن After و Before اعلاهم. الدالتين preSetup و postClean تم تشغيلهم فقط مره واحده, لهذه الكلاس, وهذا يعود لتطبيق النوتيشن BeforeClass و AfterClass اعلاهم ويجب عندها ان يكونان static. دالة الاختبار المسمية بالـ sum3_test قد تم تجاهلها, وهذا يعود الى استخدام النوتيشن Ignore اعلاها. اما دوال الاختبار لدينا المسماه sum1_test و sum2_test فقد تم تشغيلهم بسلاسة ونجاح. انشاء بيئة الاختبارات الخاصة بالـ JUnit على مشروع جافا الان لنقم بإنشاء بيئة الاختبارات الخاصة بنا, والتي من خلالها سوف نقوم باختبار مشروعنا التجريبي (عباره عن حاسبة اطفال بلغة الجافا). هذه الطريقة تمكنك من انشاء بيئة الاختبار يدوياً Best Practice. قم بتشغيل برنامجك المفضل للجافا (في هذا الشرح IntelliJ IDEA). انشئ مشروع جافا جديد 1.8 ولاتنسى اختيار الـ Command Line App او اختر مشروع سابق. انشئ مجلد جديد في مسار مشروعك وسمه مثلاً test. علم هذا المجلد بانه خاص للإختبارات, حتى يفهم الـ IntelliJ IDEA. اذهب الى اسم كلاسك الرئيسية واضغظ عليها بالزر الايمن للماوس ومن القائمة اختر Go To ثم Test. اضغظ على Create New Test... في النافذة المنبثقة. ستظهر لك نافذة جديده للإختبارات, اختر مكتبة الـ JUnit 4 المتطابقة مع هذا الشرح. انتباه: اذا رأيت الرسالة JUnit4 library not found in the module اضغظ على Fix. ثم استخدم المكتبة الموجودة بمسار الـ IntelliJ او قم بتحميلها وتحديد مسار اخر لها. الخطوات بالصور حتى يسهل الأمر انشاء مجلد الاختبارات تعليم هذا المجلد وجعله خاص للإختبارات انشاء اول اختبار للكلاس الرئيسية ثم انشاء اختبار جديد تعديل الاعدادات واختيار مكتبة الاختبارات كأول مره فقط (لاتنسى اصلاح خلل ايجاد مسار المكتبة) اصلاح Fix خلل ايجاد مسار مكتبة JUnit على جهازك النتيجة, كلاس جاهزة انشئت لكتابة الاختبارات في المجلد التي قمت بتخصيصة الـ Assertions في الـ JUnit يأتي مع الـ JUnit دوال تسمى Assertions من خلالهم تستطيع اجراء الاختبارات, ويجب عليك حفظ وفهم هذه الدوال, كما هو الحال مع الـ Annotations. يمكنك الاطلاع عليهم من خلال هذا الرابط. اهم هذه الدوال هي: شرح المشروع قبل كتابة الاختبارات لنفهم هذا المشروع قليلاً. فأسم المشروع هو KidCalculator. وتستطيع ايجاد نسخة منه على رابط الجيت هوب لدي. يتكون من عدة كلاسات (حالياً) وهي: Main.java وهي الكلاس الرئيسية للمشروع. MainTest.Java وهي كلاس الاختبارات التي انشئناها بالخطوات السابقة. Calculator.Java وهي عبارة عن Model لكلاس الحاسبة لدينا, تحتوي على دوال الحاسبة كالجمع والطرح والقسمة والضرب الخ... والتي من خلالها سيبنى المشروع. BigNumberException كلاس exception خاص بالمشروع, حتى نستخدمها لاحقاً. سيكون عملنا فقط كتابة اكواد داخل كلاس الـ MainTest.Java بما ان الاختبارات هي الهدف من هذه المقالة. كتابة الاختبارات اولاً لنلقي نظرة على كلاس الـ Calculator حتى نفهم هذه الموديل package com.company; public class Calculator { private String mColor; private boolean mPower; public Calculator(String color) { mColor = color; } public String getColor() { return mColor; } public void setColor(String color) { mColor = color; } public boolean checkPower() { return mPower; } public void setOn() { mPower = true; } public void setOff() { mPower= false; } public int addition(int firstNumber, int secondNumber) { return firstNumber + secondNumber; } public int subtraction(int firstNumber, int secondNumber) { return firstNumber - secondNumber; } public int multiplication(int firstNumber, int secondNumber) { return firstNumber * secondNumber; } public int division(int firstNumber, int secondNumber) { return firstNumber / secondNumber; } } والان لنقم بكتابة الاختبارات لهذه الموديل لإختبار المنطق في اجراء العمليات الحسابية حسب ماتم برمجته في الكود السابق. package com.company; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; public class MainTest { private Calculator calculator; @Before public void setUp() { calculator = new Calculator("Red"); } @Test public void addition_test() { int result = calculator.addition(2, 2); assertEquals(result, 4); } @Test public void subtraction_test() { int result = calculator.subtraction(10, 4); assertEquals(result, 6); } @Test public void multiplication_test() { int result = calculator.multiplication(5, 5); assertEquals(result, 25); } @Test public void division_test() { int result = calculator.division(10, 2); assertEquals(result, 5); } } ملاحظات: استخدمنا هنا assertEquals وهي عباره عن دالة JUnit تاخد قيمة متوقعة (result) ثم تقارنها بالقيمة الحقيقة اي الصحيحة. قمنا بأنشاء عنصر من موديل حاسبتنا Calculator في دالة الـ setUp والتي تعمل قبل كل الدوال حتى تنشئ عنصرنا ونتمكن من استخدامه في باقي دوال الاختبارات. وتشغيل هذه الاختبار من خلال الضغظ بالزر الايمن على اسم الكلاس واختيار Run 'MainTest' او من خلال الايقونة الصغيره الخضراء كشكل السهم المستدير بجانب اسم الكلاس, كما بالصورة التالية: نتيجة الاختبار نجاح جميع الاختبارات كما هو متوقع. ملاحظة: لاتعير اهتمام للسطر الاحمر فهو خلل برمجي في الجافا, يحدث للماك وهذه اقتباس من احد العاملين بشركة اوراكل: المزيد من الاختبارات سوف نقوم بانشاء دالة تغير لون حاسبتنا وتتأكد من تغيير اللون. و أيضاً سنقوم بانشاء دالة اخرى تتاكد من هذا اللون, ثم نشغل جميع الدوال. ملاحظات: قمنا بكتابة و تشغيل ٦ اختبارات, ٥ نجحو, وواحد فشل. المهم هو ان الدالة check_color_and_change_it_test قد نجحت في تغيير اللون, ونجحت ايضاً في التأكيد من ان اللون قد تغير الى الازرق. اما الدالة check_color_is_still_changed قد فشلت في التأكيد من ان اللون قد اصبح ازرق؟ لماذا؟ اليست الدالة التي قبلها قد قامت بتغيير هذا اللون؟ وهكذا قمنا بأنشاء مجلد اختبارات + انشاء كلاس اختبارات + كتابة ٦ دوال اختبارات باستخدام بعض من الـ Annotations و Assert واحده وهي assertEquals. واتوقف هنا حتى لايصبح للقارئ overwhelming و burnout, واكمل في المقالات اللاحقة ان شاء الله.
  11. السلام عليكم ورحمة الله وبركاتة. اللهم صلى على محمد وعلى اله وصحبه وسلم, والحمد لله رب العالمين. هذه مراجعة لي وسرد تجربتي لدراسة درجة النانو ديجري في اساسيات تطوير الاندرويد من خلال يوداستي كونكت, حتى يستفيد الكل ممن يريد الخوض في هذه التجربه. بدايتاً اتقدم بالشكر لمؤسسة مسك الخيرية ومؤسسها الامير محمد بن سلمان بن عبدالعزيز, لإتاحة هذه الفرصة لي و لكل الراغبين في الالتحاق بها. ماذا سوف تقرئ في هذه المقاله معلومات الدورة اسمها: Android Basics Nanodegree by Google هذه الدورة خاصة بتعلم اساسيات البرمجة والتطوير للإندرويد في شكل مرئي و نصي وتفاعلي, اي انك تشاهد محاضرات قد اعدت سابقاً و ايضاً القرائة الكثيره من صفحات الـ Documentation و مقالات الويب المتعلقة في مجال تطوير الاندرويد (مثلا المقالات الموجوده في هذا الموقع مفيده جداً). ويأتي الدور التفاعلي في الكونكت بشكل مباشر مع المشرفين والطلاب اسبوعياً ٣ ساعات. ثم تطبق ماتعلمته لإنجاز المشاريع المطلوبة منك حتى تتخرج. رابطها: من يوداستي. رابطها: من مسك. سبب التحاقي بها الحصول على شهادة معتمده في تطوير الاندرويد والهدف الكبير هو تأهيلي للدورة المتقدمة في تطوير الاندرويد, ثم الاختبار المقدم من شركة جوجل. مدة هذه الدورة مدتها مكثفه جداً (مضغوطة) و تمدت الى ثلاثة اشهر في حالة الدراسة لـ ١٥ ساعة اسبوعياً. وتستطيع سباق هذه المدة والتخرج في وقت اقصر اذا كثفت ساعات الدراسة, ولكن لاتستطيع التأخر عن ٣ اشهر والا سوف تستبعد منها. في حالتي احتجت الى اقل من شهر واحد (٢٥ يوماً) لإتمامها, وذلك بتكثيف الدراسة بشكل كبير واستخدام تقنية الطماطم للدراسة! نصائح مني لمن يرغب بالدخول في هذه الدورة في رأيي قبل الدخول في هذه الدورة يجب ان تكون لديك معرفه بسيطة الى متوسطة في الامور التاليه: لغة الجافا. اللغة الانجليزية. وجود وقت متفرغ للدراسة (١٥ ساعه اسبوعياً او اكثر اذا تريد التخرج سريعاً). لغة الـ SQLite او SQL لإدارة قواعد البيانات (ان امكن). التعامل مع الـ JSON و الـ Network في الاندرويد وكيفية التعامل مع الـ APIs لإستقبال البيانات من الانترنت (ان امكن). اذا وجد لديك معرفة في اغلب هذه الامور السابقه فانك حتماً ستنهي هذه الدوره في شهر تقريباً. اما اذا لا فلا تقلق فسوف تدرسها معهم, ولكن في اعتقادي ستحتاج الى ٣ اشهر وهو مقدار وقت هذه الدوره وكافي لها. تحذيرات قبل الدخول في هذه الدورة الغش Plagiarism ممنوع منعاً باتاً, عقابه الحرمان من الدراسه في Udacity نهائياً و الحرمان من المنح المقدمه من مسك ايضاً. جعل شخص اخر يعمل مشاريعك يعتبر غش. نسخ الاكواد من المواقع الشهيره كـ Stackoverflow واستخدامها في اتمام مشاريع هذه الدوره يعتبر غش. نسخ الاكواد و الكلاسات من مشاريع زملاء سابقين قد انهو هذه الدوره يعتبر غش. استخدام مكاتب تسهل عليك اتمام المطلوبات الاساسيه يعتبر غش, مثلا استخدام مكاتب تسهل التعامل مع قواعد البيانات او الـ Networking ممنوع. المطلوب هو كتابة Java Raw Code في التعامل مع المطلوبات الاساسية. تستطيع استخدام مكاتب تسهل عليك بعض الاشياء الغير اساسيه كمثلاً مكتبة السكين Butter Knife. بالنسبه لإكتشاف الغش, الذي لاحظته من تجربتي معهم أنهم يستخدمون تطبيقات كالـ Falcon و مبرمجين خبراء, و ايضاً Machine Learning للتصحيح و الاحصائيات واكتشاف الغش, لذلك لاتفكر في الغش بشكل مطلق حتى لاتستبعد. ماذا سوف تتعلم في هذه الدورة كل شئ اساسي بالاندرويد! ابتدائاً من تصميم الواجهات والتعامل مع ادخال البيانات من قبل المستخدم وانشاء Activities مختلفه و Fragments و التعامل مع HTTP Networking و JSON Parsing و Threads وتختمها مع قواعد البيانات بالاندرويد. طريقة عمل هذه الدورة كانك داخل Loop تبدء بمشاهدة المحاضرات المسجله سابقاً في الاقسام التي سوف تدرسها بموقع Udacity باللغة الانجليزية طبعاً, وتقوم بحل الاسئله ان وجدت. ثم في نهاية كل قسم يوجد مشروع تعمل على اتمامه في الوقت المحدد لك. ثم تقوم برفع هذه المشروع على موقع GitHub او من خلال رفعه كملف zip وهم يقومون بتصحيحه والتدقيق وتأكد خلوه من الغش. وايضاً اسبوعياً تقوم بعمل كونكت من خلال موقع زوم مع المشرفين (نصيبي كان مع الاستاذ Abdulaziz Alawshan والاستاذه Shorouq Basnawi الرائعين) انت وبقية الطلاب (نص و صوت, ولكن اذا توفرت الكاميرا فهو افضل) حتى يوضحون لك الكثير من الامور الهامه ومساعدتك ان كنت تواجه صعوبات ومشاكل. وايضاً يوجد مجتمع خاص على موقع الـ Slack لطلب المساعده و الشات في امور تتعلق بالمشاريع والدروس. وايضاً منتدى خاص بالطلاب كذلك على موقع Udacity. وفي النهاية عند اتمام جميع المشاريع تتخرج. التخرج التخرج سلس جداً, ففي حال انتهائك من جميع المشاريع, كل ماعليك هو اثبات هويتك وانت التي قمت بالدراسة وليس غيرك. وذلك يأتي من خلال الاثبات الالكتروني للهوية وهو مبني على هذه الخدمة, ومن ثم تخريجك في اقل من ١٠ دقائق! الفرق بين هذه الدوره المدفوعه و دراسة الكورسات مجاناً طبعاً تستطيع دراسة محتوى هذه الدوره مجاناً على موقع يوداستي, حتى قبل خوضك فيها لتمهيد نفسك, ولكن تمتاز هذه الدوره المدفوعه بمميزات كثيره تكسبك خبرات اعمق مثلاً: وجود مجتمع حي وتفاعلي, على الكونكت و Slack و المنتدى الخاص بطلاب الدوره المدفوعه. التتبع معك من قبل المشرفين و فريق عمل يوداستي. تصحيح واجباتك ومشاريعك واعطائك feedback واقتراحات لطريقة برمجتك واتمامك للمشاريع من قبل خبراء في برمجة الاندرويد. الشهاده المدعومه عالمياً. ماهو الفرق بين Udacity و TeamTreeHouse و Udemy و Pluralsight ربما يتسائل البعض عن هذا الفرق, بما ان لدي خبره في تجربة جميع هذه المنصات للتعلم الذاتي (في مجال الاندرويد). استطيع ان اقول ان Udacity اعمق في التعليم واتقان برمجة الاندرويد. والفرق الشاسع في رأيي هو ان Udacity تسلك منهج مختلف عنهم وهو ان يجب على الطالب البحث والتجربه والعمل بالطرق الخاطئه ثم العمل بالطرق الصحيحه والفشل والتعلم من الفشل حتى يكمل مشاريعه وواجباته. اما باقي الشركات فمنهجهم هو مشاهده المحاضرات وبعض الاسئله مما يخلق جو سهل وممل. ولكن لإنصاف شركة الـ TeamTreeHouse فهي تعتبر منافس قوي لـ Udacity في تعليم الاندرويد وارخص وتعليمها ذو جودة يقارب Udacity نوعاً ما ولكن ليس بها ذلك العمق. الطرق التي تستطيع استخدامها للمذاكرة والتخرج بشكل سريع (في اقل من شهر) هذه بعض من الطرق التي استخدمتها حتى تسهل المذاكرة و التركيز وتزيد من الكفائه في عمل المشاريع مما ينتج عنها الجوده والتخرج السريع. تقنية الطماطم. تكثيف الدراسة شبه يومياً. قرائة متطلبات المشروع و تحديد المهم من النقاط قبل الخوض في دروس القسم (حتى تتكون لديك الـ Big Picture للمشروع تلقائياً). تحديد كل ماهو مهم في الـ Documentation ومقالات الويب عند قرائته, لانك حتماً سترجع لهم. تسريع المحاضرات في الدروس لضعف 1.5 و 2.0 بعض الاحيان (كما هو موجود باليوتيوب). العمل على المشروع في نفس وقت مشاهدة الدروس! لكني لا انصح بهذا الشئ لمن يواجه صعوبه. قلم التحديد المستخدم في هذا الرابط. تقنية الطماطم - لزيادة الكفائه بما ان هذه التقنيه هي من افضل الاشياء المساعده في المذاكره والحفاظ على قوة التركيز وزيادة الكفائه فمن الافضل التعلم عليها وجعلها عادة قبل الخوض في هذه الدوره ان امكن. تستطيع مشاهده فيديو تعريفي لها من هذا الرابط (تقنية الطماطم). بالنسبة لي استخدمت برنامج خاص بالماك وهو Be Focused Pro برنامج جداً بسيط وعملي, توجد منه نسخة مجانيه. اما اذا لم تكن من مستخدمي الماك فهناك الكثير من البرامج التي تطبق تقنية الطماطم في باقي المنصات فقط قم بالبحث في جوجل عنها تحت مسمى الـ Pomodoro Technique Apps. هذه الصوره توضح مسار عملي على المشاريع باستخدام تقنية الطماطم. حيث كان الهدف ١٠ بندورات كل يوم. (ملاحظة تقريباً لم احسب وقت مشاهدة المحاضرات و الدروس. فقط قمت بحساب الوقت الذي استغرقته في عمل المشاريع كالبرمجه و التصميم والبحث, والتجربه, وحل المشاكل, والاطلاع على مصادر متنوعه, الخ...). الفتره المستغرقة لإتمام مشاريع هذه الدورة والتخرج كانت تقريباً اقل من شهر, من 11/11/2017 الى 12/06/2017. وذلك باستخدام هذه التقنية و التكثيف الدراسي. عدد الطماطم هو: ١٦٧, والوقت الكلي المستغرق: ٦٩:٣٥ ساعة. كل طماطم مدتها ٢٥ دقيقه. واخيراً صور للإيضاح حتى يتقرب المعنى لك اخي\اختي القارئ هذه بعض الصور من الدوره للتوضيح صوره للصف الخاص Class بك وتحتوي على الاقسام, وفي كل قسم دروس ومشروعات تعملها (بالعاده مشروع او مشروعين للقسم الواحد فقط). مثال: متطلبات المشروع الختامي للقسم الثالث المسمى بالـ User Input * تستطيع تكبير الصوره بالضغظ عليها ثم الضغظ على زر "الحجم الكامل" بالزاوية السفلى, لمشاهدتها بشكل واضح جداً. بعد تصحيح المشروع من قبل Udacity ونجاحه في كل المهام المطلوبه * تستطيع تكبير الصوره بالضغظ عليها ثم الضغظ على زر "الحجم الكامل" بالزاوية السفلى, لمشاهدتها بشكل واضح جداً. بعض الـ Feedback و الاقتراحات لتحسين برمجتك من قبل المصححين * تستطيع تكبير الصوره بالضغظ عليها ثم الضغظ على زر "الحجم الكامل" بالزاوية السفلى, لمشاهدتها بشكل واضح جداً. الناتج النهائي, اي حل المشروع المطلوب بعض من امثله لمشاريعي الاخرى في هذه الدوره تطبيق للتعامل مع قواعد البيانات بالاندرويد (المشروع النهائي) باستخدام Raw Java Code وبدون مكاتب. وذلك بكتابة كلاسات للتعامل مع قواعد البيانات كالـ Provider و Helper و Contract خاصين بقاعدة البيانات لديك. تطبيق للتعامل مع الـ JSON و HTTP Netorking و Threads و قرائة الناتج من الـ APIs كـ 0 و 1 ثم تحويله الى عناصر , باستخدام Raw Code Java اي بدون مكاتب. يجلب الاخبار المتعلقه بالذكاء الاصطناعي من احدى الصحف البريطانيه المشهوره (الجاردين). تطبيق سياحي لإحدى المدن, في حالتي اخترت المدينة المنورة. والهدف من هذا التطبيق هو التصميم و التعامل مع الـ Fragments و غيرها من اشياء. تطبيق مشغل موسيقى (ولكن في حالتي اخترت ان اعمل تطبيق مشغل للكتب الصوتيه). الهدف منه ممارسه التصميم و الاشياء البداية كالـ intent وليس تشغيل الموسيقى. اخيراً مع ابسط مشروعان بالدوره. تطبيق لدكان يبيع الايس كريم! اما الثاني فهو لحساب وتسجيل نتائج احدى الرياضات. وهذا هو اول واجب لي معهم, وكان عباره عن عمل تطبيق كشكل بطاقه مع الرسم اليدوي. في حالتي استخدمت هذه الصوره التي التقطها مسبقاً, وقمت بعمل illustrator لها باستخدام برنامج Pixelmator بالماك واظافة مقوله رائعه لها " البحر الهادئ لايصنع القبطان الجيد ". في النهاية انصح الجميع باخد هذه الدوره حتى وان كانت سهله لديك, لانك ستحصل على شهادة معترف بها عالمياً من شركة جوجل. اي تزكيه بانك مبرمج اندرويد حقيقي. اما اذا كنت مبتدء فهي دورة ممتازه لك ايضاً وسوف تجد الكثير من المساعده معهم لإتمامها فلا تقلق. والحمد لله رب العالمين اولاً واخراً ودمتم في رعاية الرحمن.
  12. شكراً لك على مشاركة تجربتك. انا افكر في اختباره ولكن ليس الان, في المستقبل القريب ان شاء الله.
  13. السلام عليكم ورحمة الله وبركاتة هذا المقال يسهل لك ايها القارئ ايضاح مفهوم الـ Abstraction (اي التجريد) بالبرمجه من خلال ربطه بالحياه الواقعيه. مناسب لكل من هو مبتدئ او اي شخص يواجه صعوبه في فهم هذا المفهوم. فأنا في فتره من الفترات كنت لا اعرف ماهو هذا مطلقاً, ومن خلال بحثي وقرائتي عنه تكونت لدي صوره واضحه عنه واحببت ان انقل هذه الصوره لك اختي | اخي القارئ. والذي يعتبر التجريد بدوره عامل كبير جداً في البرمجة. وايضاً يعتبر المكون الاساسي لمفهوم الـ Object-oriented programming - OOP. المعنى الحرفي العربي لكلمة Abstraction التجريد. اصل ومعنى كلمة Abstraction الاصل مأخود من الكلمة اللاتينية abs, والتي تأتي بمعنى away from (اي: بعيداً عن). مثال: لنفرض ان لديك مقلمه بها العديد من الاقلام وقمت بعمل abs للقلم ذي اللون البرتقالي, هنا نستطيع القول انك اخدت هذا القلم بعيداً عن المقلمه. وكصورة عامة نستطيع القول انك قمت بعمل عملية الـ abstraction للمقلمه. اي عندما تعمل لشئ abs من بين عدة اشياء, هو فقط ان تاخده بعيداً عن تلك الاشياء. الان كرر عملية الـ abstraction واستمر في عمل abs لكل الاقلام ذوي الالوان الغير اساسيه, حتى يتبقى لديك مقلمه تحتوي فقط على ٣ اقلام وهي الالوان الاساسية الاحمر والاصفر والازرق وهنا نستطيع القول انك اقتربت من انهاء عملية التجريد للمقلمه. اكمل التجريد وأتي بمقلمه اخرى وضع بها الالوان الذي استخرجتهم من الاولى. وهنا اصبحت لديك مقلمتين واحده للإلوان الاساسيه والاخرى للإلوان الغير اساسيه ونستطيع القول ان التجريد قد اكتمل للمقلمه. الفائدة من تجريد المقلمه حتى يسهل على الطفل استخدامها! فوجود اقلام كثيره يجعل الطفل في حيره من امره. ولكن بوجود فقط ٣ اقلام اساسيه يصبح الشئ اكثر سهوله في الاختيار والفهم والحفظ والترتيب الخ... واذا احتاج الطفل اي من الاقلام الغير اساسية فيستطيع الاستعانه بالمقلمه الاخرى. اذن نستطيع القول من مثال المقلمه ان فائدة الـ abstraction هي تبسيط الاشياء المعقده الى اشياء سهله, عن طريق ابعادها وفصل الاشياء الجانبيه بحيث في النهاية يتبقى لدينا الاساسيات فقط في الواجهه. الفائدة من خلال القيام بعملية الـ Abstraction خلال القيام بعملية التجريد لشئ ما, يكتسب الدماغ فهم اكثر واعمق لهذا الشئ. فمثلاً الطفل عندما يقوم بتجريد لعبه مكونه من مكعبات اللوجو (اي يعمل abs لكل قطعه في شكل النمر) يكتسب خلال هذه العملية معرفة اعمق للقطع المكونه لهذه اللعبه وكيفية اتحادها مع بعضها البعض لتكوين هذا الشكل. ليصبح لديه في النهاية درايه وقدره اكبر لتكوين نفس الشكل او القدره في الابداع لتكوين اشكال اخرى من مكعبات اللوجو. فعند الاتيان بقطع متناثره من اللوجو (المكعبات) لطفل لم يعمل تجريد لاي لعبة من قبل, نرى ان لديه صعوبه في تكوين الاشكال. بعكس الطفل الذي قام بالكثير من عمليات الـ abstraction لـ ألعاب اللوجو من قبل, فهو على درايه كبيره في كيفية عمل كل قطعة صغيره وطرق التحامها بالاخرى, وايضاً تتكون لديه درايه اكبر في فهم الصوره العامه (big picture). معنى الـ Abstraction في البرمجة للاسف يوجد الكثر من مفاهيم ومعاني التجريد, فهي كلمه فلسفيه بحته. وسترى معاني غريبه لها في بادئ الامر. ولكن الان لنركز على الهدف من هذا المقال وهو مفهوم وتطبيق التجريد في البرمجه. لفهم التعريف تخيل ان مشروعك هو مقلمة الطفل. وان اسطرك البرمجية هي الاقلام بتلك المقلمه. وتذكر كيف جعلنا الامر اسهل على الطفل من خلال التجريد الى مقلمات اخرى. وتذكر ماذا اكتسب الطفل الاخر من خلال قيامه بتجريد قطع اللوجو. مثال: مشروع به ٥٠ مليون سطر برمجي تخيل لو ان فريق من المبرمجين يعملون على مشروع مكون من class واحده فقط (تسمى God Class من اسوء الاخطاء في البرمجة) فكم سطر برمجي ستكون هذه الكلاس؟ لنفرض انها ٥٠ مليون سطر! كما هو الحال في الشفره المصدريه لـ ويندوز فيزتا الرائع جداً! في هذه الحاله يجب على كل مبرمج ان يفهم هذه الكلاس كامله حتى يتعامل معها ويبرمج داخلها! وهذا يخلق صعوبه عاليه بل مستحيله جداً فلا يوجد مبرمج يستطيع ان يحشر ٥٠ مليون سطر في دماغه. ماذا لو احدث احد المبرمجين (مبرمج يريد اضافة ميزة جماليه للاشعارات) تغيير في السطر رقم ٣٣٤٢٣٣٣؟ وسطر ٥٤٣٢٣٤٥٦ قد احدث خطئ وهنق الويندوز! من هو الخارق الذي سيقرئ او يعمل تحليل لـ ٥٠ مليون سطر ليحل المشكله؟ هل سيقوم هذا المبرمج بالتنطط بين الـ ٥٠ مليون سطر بمطرقته الـ Debug! الا توجد طريقه لعمل هذا المشروع حتى يصبح تطويره واصلاحه من قبل المبرمجين في الفريق اسهل بكثير؟ نعم وهو بتطبيق مبدء التجريد! الحل هو تطبيق الـ Abstraction الهدف المراد تحقيقه: هو معرفة القليل من الكود الاساسي في هذه الكلاس العملاقه حتى يسهل حفظه من قبل كل مبرمج في الفريق, ويخلق لديهم المزيد من الكفائه للتعامل مع الكود والاضافه والاصلاحات. لنجرد كبدايه بعض الاسطر بهذه الكلاس العملاقه: لنفرض ان هنالك في هذه الكلاس كود مكون من ١٠٠٠ سطر وظيفته هي اظهار اشعار للمستخدم, فلماذا على كل مبرمج ان يحفظ هذا الكود الكبير! اليس من الاسهل ان نقوم بتغليف هذا الكود داخل ميثود ونسميها بفعلها كـ showNotification ونطلب من كل مبرمج فقط ان يحفظ اسم هذه الميثود و ماذا تخرج (return) و ماذا تريد ان يدخل بها (parameters). ويقوم باستدعائها فقط عند الحاجه! اذاً بهذا العمل قد قمنا باخفاء التعقيدات (اخفاء كيفية عمل كود الاشعارات ذي الـ ١٠٠٠ سطر). فأنت عندما ترى مشغل موسيقى امامك كل ماتراه هو واجهه (interface) فقط. ولا ترى مابداخل هذا المسجل من قطع الكترونيه. وتعرف ان هذا المسجل يدخل فيه شريط كاسيت و يخرج صوت وذلك عن طريق الضغظ على زر التشغيل. فرؤيتك الى interface او تعاملك مع interface يسهل لك حياتك في استخدام الاشياء ولا داعي للتعقيد ومعرفة كيفية سير كل الامور بداخل هذه المسجل. تطبيق المزيد من الـ Abstraction على الكلاس العملاقه ذي الـ ٥٠ مليون سطر الان لنرجع الى الكلاس العملاقه مره اخرى. اليس من الافضل ان نغلف هذا الكود الى العديد من الميثودات (كما قمنا في تغليف كود الاشعارات سابقاً) ونقوم بحفظ فقط اسمائها و مداخلها و مخارجها. ايضاً اليس من الافضل ان نقسم هذه الكلاس الكبيره الى عدة كلاسات اخرى. ونجرد اسطرها البرمجيه الى ميثودات بالكلاسات الاخرى. وان نجعل كل كلاس جديده تحتوي فقط على الميثودات المتقاربه (كالطفل والمقلمات). توقف هنا وتمعن! (هنا في هذه النقطة صنعنا شئ اسمه API في البرمجه). واخيراً لنعطي كل مبرمج من الفريق كلاس خاص به, فارغ تماماً, ونجلب له الـ Documentation ليتعلم او ليبحث عن اسماء تلك الميثودات ويعرف مخرجاتها ومدخلاتها, ويستدعي مايحتاجه لكتابه واكمال كلاسه للقيام بدوره في الفريق وانجاز المشروع. كلاس مبرمج الاشعارات الان كيف ستكون؟ تخيل كلاس المبرمج الذي يعمل على تجميل الاشعارات, هو الان يحتاج فقط ان ينادي على ميثود الـ showNotification ويقوم بكتابة بعض الاسطر القليله التي تنشئ جماليات لإضافتها الى الاشعارات. والذي من المؤكد انه سوف يبدع في دوره كثيراً لان مجمل تركيزه في الاشعارات, وليس كما كان في البداية مشغول في حفظ و التنطط بين الـ ٥٠ مليون سطر برمجي ومحاولة اصلاح ماقد تسبب به من اخطاء. فنحن بعملنا هذا قمنا بتجريد الكلاس العملاقه هذه وانتزاع منها اسطر برمجيه بالملايين, وتغليفهم في كلاسات خاصة بهم داخل ميثودات باسماء افعالهم, وجعلنا فقط بها الاسطر الاساسية وكأنها اصبحت interface يسهل على المبرمج التعامل معها (كمشغل الموسيقى والمستخدم العادي له!!!). مطبقين مبدء التجريد الـ abstraction وبالاستعانه ايضاً بمبدء التغليف الـ encabsulating والذي يعتبر بدوره جزء كبير من تحقيق عملية التجريد في البرمجه. واخيراً قمنا بتحويل المشروع كلياً الى شئ يسمى API حتى يسهل على المبرمج ندائه واستخدامه وتطويره. نصائح لاتتعمق في التجريد, والا سوف تصنع مشروع معقد على نفسك. لفهم الاشياء التي تراها في صوره كامله, حاول تجريدها قطعه قطعه (عملية التجريد). كتجريد مكونات الـ API للاندرويد. لتركيب صوره كامله لشئ تريد تعلمه, حاول تركيبها قطعه قطعه (عملية التجريد). اي شئ صعب فهمه حاول تجريده, وفهم القطع الصغيره منه وكيفية التحامها مع الاخره. التجريد وجد للتسهيل, لذلك لاتتفاجأ عندما ترى مكتبه او مشروع او api يحتوي على مئات الكلاسات والميثودات. فقط خد نفس عميق وابدء بفهمه قطعه قطعه (جرده) او قم بنداء مايلزم لاتمام شغلك فقط. عند تصميم مشروع في البدايه قم بالتفكير في التجريد, انظر الى الصوره الكبيره كما يفعل الطفل ذي الخبره في اللوجو, قم بعمل اللازم من كلاسات وميثودات, وفي النهايه استخدمها كما تحب في الـ mainActivity.class كانك تركب تطبيقك بالاندرويد في هذه الكلاس, ليس كتابة جميع الاكواد بها وجعلها (God Glass) وهذا شئ خاطئ جداً. نقاط واسئله للتأمل في التجريد هل تستطيع الربط بين مفهوم الـ Abstraction و مفهوم كلاس الـ Abstract Class في مخيلتك! هل ترى الفلسفه في فكرة الربط بين واجهة المستخدم الرسوميه لتسهيل حياته, وواجهة المبرمج والتي هي ملف الـ interface لتسهيل عمله كمبرمج! هل تستطيع التنقل بسهوله بين طبقات التجريد؟ هل تستطيع عكس التجريد؟ هل مر عليك مصطلح: برمج الى انترفيس وليس الى كلاس؟ امثله برمجيه تجريد مشروع لتطبيق اندرويد الى كلاسات وبكجات كثيره: فبدلاً ان يكون البرمجه محشوره كلها في كلاس الـ mainActivity قمت بانشاء العديد من الكلاسات والبكجات لترتيب اسطري البرمجه. ثم ندائهم في الـ mainActivity لأصنع التطبيق. والان مثال للتجريد بالكود سأستخدم لغة البايثون فهي اسهل للفهم واقل كتابة من الجافا. وهذا فقط مثال للتوضيح وليس Abstraction محض. لدينا مبرمجان يعملون على انجاز برنامج, وظيفة هذا البرنامج هي: يطلب من المستخدم ادخال اسمه. ثم المبرمج الاول يقوم بكتابة كود يطبع حرف حرف للمستخدم مع مكان وجود الحرف في اسمه. اما المبرمج الثاني فيقوم باخد اسم المتسخدم وحساب عدد الحروف المكرره ثم يطبعها ايضاً حرف حرف مع عدد تكرارها. الكلاس قبل عمل الـ Abstraction لها: star = (chr(10029)) user_name = input("Enter your name:") user_name_total_char = 0 for i in range(len(user_name)): print(user_name[i] + " --> " + str(i + 1)) for i in range(len(user_name)): total = 0 for j in user_name: if j == user_name[i]: total += 1 print(user_name[i], "--->", total, "repeated") الكلاس بعد عمل الـ Abstraction لها اخرجنا جميع الاكواد الى كلاسات فرعيه. واصبحت الكلاس هكذا: initialize() ask_user_for_name() calculate_user_characters() calculate_user_characters_counts() print_user_chars() print_user_char_counts() ويستطيع اي مبرمج اخر استخدام هذه الميثودات كما يشاء اذا احتاجها في تطوير شئ جديد كميزه بالبرنامج (تذكر هذا فقط مثال بسيط لتسهيل فهم التجريد والذي هو كافي تماماً في اغلب الحالات). الـ Abstraction وتمثله في الطبيعه (خلق الرحمن) في النهاية انظر الى الصوره (نبتة الماء) وتمعن في جمال صنيع الخالق وعظمته في الخلق. انظر الى قوة التجريد الذي من خلاله يخلق نبته جميله جداً. تمعن في كل قطعة بالنبته (جردها بعينك, اي اعمل لها abs بخيالك) وكيفية التحامها وتركيبها Composite وتناسقها مع القطع الاخرى لتكون في النهايه نبتة الماء كالصوه النهائيه لعملية التجريد. انظر الى درجة اعمق من التجريد, فكر في طريقة غدائها, وغداء كل قطعه منها على حدى الخ... تأمل! هل توجد هناك مقارنه بين ابداع الخالق في عملية التجريد, وعفسة المبرمج في عملية التجريد عندما ترى مشروعه من الوهله الاولى! فسبحان الله على بديع خلقه.
  14. السلام عليكم ورحمة الله وبركاتة هذه مقالة مبسطة لشرح مفهوم الـ Class بلغة البرمجة الـ Java لكل من يعاني من صعوبة في فهمها. فمن مدة قمت بكتابة مقاله مشابهه لها لتقريب مفهوم الكلاس بالبايثون في احدى المواقع الانجليزيه وقد نالت على الاعجاب, فأحببت ان اكتب مقاله تخدم نفس الهدف ولكن باللغة العربية وبلغة البرمجة الاكثر عمقاً وهي الجافا. الشرح مناسب لكل الاعمار, يستخدم الطريقة المشهورة في تبسيط الامور وهي: explain like I'm five, اي اشرحها لي كأني طفل او مبتدئ. فأرى ان كل شخص يريد تعلم شئ جديد يفوق مستواه الحالي في الفهم, في البداية يجب عليه ان يتواضع ويحاول فهمها كانه يملك دماغ طفل! بعيداً عن الغطرسة والمصطلحات المعقدة والتي بدورها تصعب الامور. هذه الصوره لـ ام وابنتها ونرى مدى تشابههم مع بعضهم البعض, وكأنهم يمثلون Class و Object. شرح مفهوم الكلاس بشكل تقريبي للحياة الطبيعية سيكون الشرح على شكل نقاط حتى يسهل الفهم, وستكون الامثله تقريبيه للحياه الطبيعيه لتسهيل الفهم فقط لاغير. وتستطيع قرائة هذه المقاله اكثر من مره والرجوع لها اذا واجهت مصطلح غامض اثناء تعلمك البرمجة بلغة الجافا. وان شاء الله سوف تنير لك طريقك. الـ Class تمثل في الحقيقة امك. الـ Object هو انت. و Object اخر يعتبر اختك او اخاك. ونستطيع تسميتكم بـ Instances of the class. اي اولاد ملكيتكم ترجع الى امكم. الـ Class Constructor تستطيع القول انه الرحم الذي سوف تتكون بداخله انت وجيناتك. الـ Declaration وهي عملية تحديد الـ Variables قبل استخدامها, اي تصريح الام بقيمها التي تتدخل في جيناتك و عملية ولادتك. الـ Class Fields تمثل قيم الام, والتي تتدخل في عملية ولادتك دائماً بشكل فريد عن باقي اخوتك واخواتك. كأسمك, لون بشرتك, وتسمى نسبتاً لك بالعادة Object Attributes. وفي بعض الاحيان يكون بعضها قيم خاصة للإم نفسها كأسم امك (ملاحظة بالنسبة لإسم الام: راح يكون static و public اي ثابت وعام وتستطيع السؤال عنه بدون اوجكتات. اما باقي الاشياء فمن المفضل جعلها private اي خاصة). الـ Instantiation هنا يبدئ التمهيد لعملية الولادة لك. الـ Initialization هنا قامت بولادتك الام. طبعاً باستخدام كلمة new والنداء على الـ Constructor اي الرحم. الـ Initialization Block عباره عن قطعه من الكود تعمل في كل مره تم انشاء اوبجكت من الكلاس, وتعمل مره واحده للكلاس نفسها. مثلاً كانها صرخة الولادة لكل طفل, او تحول المرأه الى ام, فالتحول هذا يصبح مره واحده في حياة المرأه. ألـ Class Methods or Functions تعتبر الافعال التي سوف تعلمك اياها امك وتختمها عن ظهر قلب بعد ولادتك. ككيفية ترتيب سريرك, كيفية الاكل, فرك اسنانك بالفرشاه والمعجون, نطق اسمك الخ.... وايضاً بعض من هذه الافعال راح تكون static اي امك التي تقوم بها, ونستطيع استخدامها من خلال امك بدون اوبجكتات (بدون حاجتك), كفعل نطق امك لاسمها متى شائت. الـ Getter and Setter نتدرج من الافعال (الميثودز) التي تعلمك اياه امك. الـ Inheritance اي كلمة extends تاتي بمعنى الوراثة, مثال: لو وضعنا هذه الكلمة بعد اسم امك ثم اتينا باسم جدتك, سوف ترث امك جميع تعاليم جدتك وافعالها وقيمها وطريقة تربيتها لإولادها وتطبقها عليك (الاوبجكت). الـ Super تاتي هذه الكلمة في حالة الوراثة, اذا احتجت مساعده من الجده, تطلبها من خلال كتابة هذه الكلمة. في حالة الوراثة تسمى امك بكلاس الـ Child Class وجدتك باسم الـ Parent Class او Super Class. وانت تصبح ملكيتك الى امك, والى كلاس جدتك ايضاً. وايضاً (في حالة الورثاة) اذا اردت ان تتعامل مع امك حالياً تستخدم كلمة this واذا اردت ان تتعامل مع جدتك تستخدم كلمة super. الـ Overriding او كلمة @Override الموجوده فوق بعض افعال (ميثودات) الام التي ورثتها. هذه الكلمة تضعها الام في حالة تريد تغيير في فعل ورثته من جدتك. اي اذا ورثة وصفة طبخ ما وتريد تغيير بعض من مقاديرها, هنا تستخدم هذه الكلمة. لغة الجافا لاتحب الوراثة في كلاساتها! عكس لغة السي شارب! فالجافا لاتسمح للوراثة الا من شخص واحد او بالاحرى من جهه وحده. فإما ترث انت من جهت امك او من جهت ابوك! فقط لاغير. لتفتادي مشاكل التعقيد كمشكلة الالماسة القاتلة في البرمجة قدر المستطاع! الـ implements تستخدم هذه الكلمة لتحقيق رغبة الوراثه المتعدده واشياء اخرى كثيره. فهي تأتي بعد اسم الكلاس تلحقها باسماء كثيره من الـ interface. وهكذا تصبح للكلاس خصائص متعدده كثيره بدون الوراثه, نستطيع القول هنا انها مشابهه بالتقليد! اي ان امك قامت باخد وتقليد طرق وقيم وافعال كل من عماتك, خالاتك, جاراتك الخ... في تربيتك, بدون الحاجه منها ان ترثهم. الـ interface ليس معناتها واجهت المستخدم, بل المقصود هنا بالبرمجة هي الواجهه التي تكون بينك وبين اي طرف اخر تريده بالبرمجة. نستخدمها في البرمجة لإجبار الكلاس (امك) على اضافة افعال وقيم لها, بدون الحاجة الى الوراثة. وعلى امك ان تكتب هذه القيم والافعال كما تريد. دائماً فضل استخدام الـ interface على الكلاس. اي دائماً فضل الـ implements على الـ extends. ملاحظة: في حالة الوراثة لاتحتاج الى كتابة جميع افعال (ميثودز) تلك الكلاس. ولكن في حالة الـ implemention من interface تحتاج بشكل ضروري الى كتابة جميع تلك الافعال (ميثودز) كـ @Override والا ستتعطل الكلاس. ملاحظة: للـ interface استخدامات متعدده وكثيره جداً. الـ abstract كلمة تستخدم قبل اسم الكلاس, لجعها كلاس مجرده! اي جدة قابلة للوراثة فقط ولا تستطيع ولادة اي كائن لا امك ولا انت! اي كانها جدة قامت بتبني امك ثم قامت امك بوراثتها! يقوم عملها كـتعامل امك مع الـ interface تقريباً. شرح بعض من كلمات لغة الجافا التي تتداخل مع مفهوم الكلاس بشكل تقريبي للحياة الطبيعية كلمة الـ private اي خاص, تستخدمها للاشياء الخاصة فقط, كمثلا لون ملابسك الداخلية. كلمة الـ public اي عام, تستخدمها للاشياء التي تريدها ان تكون عامه ومنظوره من قبل الجميع كوجهك. كلمة الـ protected اي خاصة بعض الشئ, تستخدمها للاشياء التي تريدها فقط ان تكون معروفة بين افراد اسرتك واقربائهم, ومخفيه على العالم. كاسرار عائلتك مثلا. بدون كلمة! خاصة فقط لك و لعائلتك التي في منزلك فقط لا اقرباء. وهذا هي القيمة الافتراضية بلغة الجافا, اي انك اذا لم تختر اي من احد الكلمات الثلاث السابقة. كلمة الـ final تستخدم للاشياء التي نريدها ان تكون غير قابله للتغير. كنسبك الى امك, لاتستطيع تغييره ابداً. مثال برمجي للكلاس: هذا مثال برمجي يحاكي ماتم تناولة في النقاط السابقة. كلاس الام: حاول ان تتمعن بالكلاس وارجع الى النقاط بالشرح لتوضيح الفهم لديك وتقريب المعنى. /** * Created by mohammad on 10/13/17. */ public class Mother extends GrandMother implements Aunt, Uncle{ // Class Fields public static final String TAG = "Mother Class Tag"; // <--- filed can not be changed private String mName; private String mSkinColor; public static String mYourMotherName; private static int mTotalChild = 0; // Initialization Block - running just one time // Static one static { Log.d("TAG", "static initializer: Woman Become Mother"); } // Initialization Block - running each time an object created // instance one { Log.d(TAG, "instance initializer: Mother Cry of pain"); mTotalChild = mTotalChild + 1; } // Class Constructor public Mother(String childName){ mName = childName; } // getters and setters (same as methods/functions) public static int getChildNumber(){ return mTotalChild; } public static void setYourMotherName(String yourMotherName){ mYourMotherName = yourMotherName; } // methods / functions public void eat(){ Log.d(TAG, this.mName + " eat: I'm eating ..."); // <-- this, refer to who is eating here Log.d(TAG, mName + " eat: I'm eating ..."); // <-- or by using m principle better } public void speak(){ Log.d(TAG, "speak: My name is: " + mName); } // method from GrandMother class // Okay to remove it if you don't need it @Override public void cookingPizza() { super.cookingPizza(); // <-- making the pizza with grandMother recipe. // <-- if you want yours recipe remove super.cookingPizza(); // <-- and write your recipe. } // method from you Aunt interface // you must implemented it (have it) or your program gonna crash (you can't remove it) // and it's okay to leave its body empty. @Override public void drawing() { } } استخدامها: // Instantiation Initialization Mother firstChild = new Mother("Noah"); Mother secondChild = new Mother("Emily"); // setting a name for your mother by using the setter Mother.setYourMotherName("Emma"); // calling your mother name from her static fields Log.d(TAG, "Your MotherName is : " + Mother.mYourMotherName); // making you and your sister doing what your *mother* teach you firstChild.cookingPizza(); // <-- *her* inherited cooking pizza from her grand mother and teach it to you. secondChild.eat(); // <-- *her* teach your sister how to eat. // asking your mother how many child she give birth to Log.d(TAG, "Total Children: " + Mother.getChildNumber()); النتيجة: Woman Become Mother initializer: Mother Cry of pain initializer: Mother Cry of pain Your MotherName is : Emma Class: cookingPizza: Pizza is cooking Class Tag: Emily eat: I'm eating ... Class Tag: Emily eat: I'm eating ... Total Children: 2 اخيراً اتمنى ان المعلومة وصلت بسهوله لك اختي \ اخي القارئ. فهذه كانت فقط لايضاح وتقريب معنى مفهوم الكلاس. وليس شرح كامل للكلاس او طرق انشائها. واكرر اتمنى ان المعنى قد اتضح لديك عزيزي القارئ.
  15. مقال رائع وشرح ممتاز, تتشكر عليه. دائماً كان التعامل مع التاريخ برمجياً اصعب من التعامل مع ورقة امتحان الرياضات بالنسبه لي 😄. فالحمد لله على هذه المكتبه الرائعه.

عالم البرمجة

عالم البرمجة مقالات برمجة و دورات مجانية لإحتراف البرمجة هدفنا تبسيط البرمجة ونشرها بيد الكل بشكل ممتع ومتطور ومحدث بإستمرار لمواكبة جديد تطورات البرمجة الحديثة و المتقدمة بدون مقابل