From cb499eb007d0f5a3de53462276154f2b44614c20 Mon Sep 17 00:00:00 2001 From: Abd-Elrahman Maged Sherwida Date: Fri, 3 Jul 2020 13:27:26 +0200 Subject: [PATCH] Automated testing with Mocha --- .../05-testing-mocha/article.md | 322 +++++++++--------- 1 file changed, 157 insertions(+), 165 deletions(-) diff --git a/1-js/03-code-quality/05-testing-mocha/article.md b/1-js/03-code-quality/05-testing-mocha/article.md index 68ffcae4d..a65978476 100644 --- a/1-js/03-code-quality/05-testing-mocha/article.md +++ b/1-js/03-code-quality/05-testing-mocha/article.md @@ -1,120 +1,105 @@ -# Automated testing with Mocha +# الاختبار الآلي لشيفرات جافاسكربت باستخدام mocha -Automated testing will be used in further tasks, and it's also widely used in real projects. +يُستخدَم الاختبار الآلي في الكثير من المهام، كما يستخدم بكثرة في المشاريع الحقيقية. -## Why we need tests? +## لم نحتاج الاختبارات؟ -When we write a function, we can usually imagine what it should do: which parameters give which results. +عند كتابة دالة، يمكننا تخيل ما يجب أن تقوم به: ما هي المعاملات التي تعطي نتائج معينة. يمكننا فحص الدالة أثناء التطوير من خلال تشغيلها وموازنة مخرجاتها مع ما هو متوقع. مثلا يمكننا القيام بذلك في الطرفية. -During development, we can check the function by running it and comparing the outcome with the expected one. For instance, we can do it in the console. +إن كان هناك خطأ، فإننا نُصلِح الشيفرة البرمجية، ونُعيد تشغيلها، ونفحص النتائج. وهكذا حتى تصبح صحيحة. لكن هذه الطريقة «إعادة التشغيل» غير مثالية. -If something is wrong -- then we fix the code, run again, check the result -- and so on till it works. +**عند اختبار شيفرة برمجية عن طريق إعادة التشغيل اليدوية، فمن السهل نسيان شيئٍ ما.** -But such manual "re-runs" are imperfect. +على سبيل المثال، عند إنشاء الدالة f. نكتب فيها بعض الشيفرات البرمجية، ثم نَفحصها: "f(1)‎" تعمل لكن "f(2)‎" لا تعمل. صلِح الشيفرة حتى تعمل "f(2)‎". ثم تبدو الدالة كأنها مكتملة، لكننا ننسى إعادة اختبار "f(1)‎" مما قد يؤدي إلى خطأ. -**When testing a code by manual re-runs, it's easy to miss something.** +هذا الأمر وارد بكثرة. فعند تطوير أي شيء، نُبقِي العديد من الاحتمالات في الحسبان. لكنه من الصعب توقع أن يختبر المبرمج جميع هذه الحالات يدويا بعد كل تغيير، فيصبح من السهل إصلاح شيء ما وإفساد شيء آخر. -For instance, we're creating a function `f`. Wrote some code, testing: `f(1)` works, but `f(2)` doesn't work. We fix the code and now `f(2)` works. Looks complete? But we forgot to re-test `f(1)`. That may lead to an error. +**يعني الاختبار الآلي أن الاختبارات تُكتب مستقلة، بالإضافة إلى الشيفرة البرمجية. تشغِّل هذه الاختبارات الدوال بعدة طرق وتوازنها مع النتائج المتوقعة.** -That's very typical. When we develop something, we keep a lot of possible use cases in mind. But it's hard to expect a programmer to check all of them manually after every change. So it becomes easy to fix one thing and break another one. +## التطوير المستند إلى السلوك (BDD) -**Automated testing means that tests are written separately, in addition to the code. They run our functions in various ways and compare results with the expected.** +لنبدأ بتقنية تسمى التطوير المستند إلى السلوك [Behavior Driven Development](http://en.wikipedia.org/wiki/Behavior-driven_development) أو كاختصار BDD. -## Behavior Driven Development (BDD) +**هذه التقنية BDD هي 3 في 1: اختبارات وتوثيق وامثلة.** -Let's start with a technique named [Behavior Driven Development](http://en.wikipedia.org/wiki/Behavior-driven_development) or, in short, BDD. +سنجرب حالة تطوير عملية لفهم BDD. -**BDD is three things in one: tests AND documentation AND examples.** +## تطوير الدالة "pow": الوصف -To understand BDD, we'll examine a practical case of development. +Lلنفترض أننا نريد إنشاء الدالة pow(x, n)‎ التي ترفع الأساس x إلى القوة n. مع الأخذ بالحسبان أن n≥0. هذه المهمة هي مجرد مثال: المعامل \*\* يقوم بهذه العملية في JavaScript، لكننا نركز هنا على تدفق التطوير الذي يمكن تطبيقه على مهام أكثر تعقيدا. -## Development of "pow": the spec - -Let's say we want to make a function `pow(x, n)` that raises `x` to an integer power `n`. We assume that `n≥0`. - -That task is just an example: there's the `**` operator in JavaScript that can do that, but here we concentrate on the development flow that can be applied to more complex tasks as well. - -Before creating the code of `pow`, we can imagine what the function should do and describe it. - -Such description is called a *specification* or, in short, a spec, and contains descriptions of use cases together with tests for them, like this: +يمكننا تخيل ووصف ما يجب أن تقوم به الدالة pow قبل إنشاء شيفرتِها البرمجية. هذا الوصف يُسمى "specification" أو باختصار "spec" ويحتوي على وصف حالات الاستخدام بالإضافة إلى اختبارات لهذه الحالات كالتالي: ```js describe("pow", function() { - it("raises to n-th power", function() { assert.equal(pow(2, 3), 8); }); - }); ``` -A spec has three main building blocks that you can see above: +تحتوي المواصفات على 3 أجزاء رئيسية كما ترى في الأعلى: `describe("title", function() { ... })` -: What functionality we're describing. In our case we're describing the function `pow`. Used to group "workers" -- the `it` blocks. +: ماهي الوظيفة التي نصفها، في هذه الحالة، نحن نصف الدالة pow. تستخدم بواسطة العاملين- أجزاء it. `it("use case description", function() { ... })` -: In the title of `it` we *in a human-readable way* describe the particular use case, and the second argument is a function that tests it. +: نصف (نحن بطريقة مقروءة للبشر) حالة الاستخدام المخصصة في عنوان it، والمعامل الآخر عبارة عن دالة تفحص هذه الدالة. `assert.equal(value1, value2)` -: The code inside `it` block, if the implementation is correct, should execute without errors. - - Functions `assert.*` are used to check whether `pow` works as expected. Right here we're using one of them -- `assert.equal`, it compares arguments and yields an error if they are not equal. Here it checks that the result of `pow(2, 3)` equals `8`. There are other types of comparisons and checks, that we'll add later. +: الشيفرة البرمجية بداخل it يجب أن تُنَفَّذ بدون أخطاء في حال كان التنفيذ صحيحًا. -The specification can be executed, and it will run the test specified in `it` block. We'll see that later. +تستخدم الدوال assert.\* لِفحص ما إن كانت الدالة pow تعمل بالشكل المتوقع أم لا. تستخدم إحدى هذه الدوال في هذا المثال - assert.equal، والتي توازن معاملَين وتُرجِع خطأ في حال عدم تساويهما. في المثال تفحص هذه الدالة إن كانت نتيجة تنفيذ الدالة pow(2, 3)‎ تساوي 8. كما يوجد العديد من أنواع التحقق والمقارنة والتي سنُضيفها لاحقا. -## The development flow +يمكن تنفيذ الوصف، وسينفِّذ الفحص الموجود بداخل it كما سنرى لاحقا. -The flow of development usually looks like this: +## تدفق التطوير -1. An initial spec is written, with tests for the most basic functionality. -2. An initial implementation is created. -3. To check whether it works, we run the testing framework [Mocha](http://mochajs.org/) (more details soon) that runs the spec. While the functionality is not complete, errors are displayed. We make corrections until everything works. -4. Now we have a working initial implementation with tests. -5. We add more use cases to the spec, probably not yet supported by the implementations. Tests start to fail. -6. Go to 3, update the implementation till tests give no errors. -7. Repeat steps 3-6 till the functionality is ready. +يبدو تدفق التطوير غالبا كما يلي: -So, the development is *iterative*. We write the spec, implement it, make sure tests pass, then write more tests, make sure they work etc. At the end we have both a working implementation and tests for it. +1. يُكتب الوصف الأولي مع فحص للوظيفة الرئيسية. +2. يُنشَئ تنفيذ أولي. +3. لتأكد من صحة عمل التنفيذ، نُشَغِّل إطار التقييم [Mocha](http://mochajs.org/) الذي يُشَغِّل الوصف. ستظهر أخطاء في حال عدم اكتمال الوظائف. نُصحح الأخطاء حتى يصبح كل شيء صحيحًا. +4. هكذا أصبح لدينا تنفيذ مبدئي يعمل كالمطلوب بالإضافة إلى فحصه. +5. نضيف المزيد من حالات الاستخدام للوصف، ربما بعض هذه الميزات ليس مضمنا في التنفيذ بعد. حينها يبدأ الاختبار بالفشل. +6. عُد للخطوة 3 وحدِّث التنفيذ إلى أن تختفي كل الأخطاء. +7. كرر الخطوات 3-6 حتى تجهز كل الوظائف. -Let's see this development flow in our practical case. +إذا، تُعد عملية التطوير تكرارية. نكتب الوصف، ننفذه، نتأكد من اجتياز التنفيذ للفحص، ثم نكتب المزيد من الاختبارات، نتأكد من صحة عملها. حتى نحصل على تنفيذ صحيح مع اختباراته في الأخير. -The first step is already complete: we have an initial spec for `pow`. Now, before making the implementation, let's use few JavaScript libraries to run the tests, just to see that they are working (they will all fail). +لنُجرب تدفق التطوير هذا على حالتنا العملية. -## The spec in action +الخطوة 1 أصبحت جاهزة: لدينا وصفًا مبدئيًّا للدالة `pow`. الآن وقبل التنفيذ، لِنستخدم بعض مكاتب جافاسكربت لتشغيل الاختبار حتى نتأكد من إن كانت تعمل (لن تعمل). -Here in the tutorial we'll be using the following JavaScript libraries for tests: +## المواصفات أثناء التنفيذ -- [Mocha](http://mochajs.org/) -- the core framework: it provides common testing functions including `describe` and `it` and the main function that runs tests. -- [Chai](http://chaijs.com) -- the library with many assertions. It allows to use a lot of different assertions, for now we need only `assert.equal`. -- [Sinon](http://sinonjs.org/) -- a library to spy over functions, emulate built-in functions and more, we'll need it much later. +سنستخدم في هذا الشرح مكاتب جافاسكربت التالية للاختبار: -These libraries are suitable for both in-browser and server-side testing. Here we'll consider the browser variant. +- [Mocha](http://mochajs.org/) -- لإطار الرئيسي: يوفر دوال الفحص الأكثر استخدامًا ما يشمل describe و it بالإضافة إلى الدوال الرئيسية التي تُشَغِّل الاختبار. +- [Chai](http://chaijs.com) -- لمكتبة المحتوية على دوال تأكيدية. تتيح لنا استخدام العديد من هذه الدوال، نحتاج الآن `assert.equal` فقط. . +- [Sinon](http://sinonjs.org/) -- a مكتبة للتجسس على الدوال، ومحاكاة الدوال المدمجة، والمزيد؛ سنحتاج هذه المكتبة لاحقا. -The full HTML page with these frameworks and `pow` spec: +تُعد هذه المكاتب مفيدة للاختبار في كل من المتصفح والخادم. سنأخذ بعين الاعتبار هنا جهة المتصفح. صفحة HTML كاملة مع هذه المكاتب ووصف الدالة pow: -```html src="index.html" -``` - -The page can be divided into five parts: +يمكن تقسيم الصفحة إلى 5 أجزاء: -1. The `` -- add third-party libraries and styles for tests. -2. The `