You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/03-code-quality/05-testing-mocha/article.md
+20-20Lines changed: 20 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,11 +18,11 @@
18
18
19
19
Це дуже типово. Коли ми щось розробляємо, ми пам’ятаємо про багато можливих випадків використання. Але не треба очікувати, що програміст перевірятиме їх усі вручну після кожної зміни. Так стає легко виправити щось одне і зламати інше.
20
20
21
-
**Автоматизоване тестування означає, що тести пишуться окремо від основного коду, доповнюючи його. Вони запускають наші функції різними способами і порівнюють результати з очікуваними.**
21
+
**Автоматизоване тестування означає, що тести пишуться окремо від основного коду, доповнюючи його. Вони запускають наші функції різними способами та порівнюють результати з очікуваними.**
22
22
23
23
## Керована поведінкою розробка (BDD)
24
24
25
-
Давайте розпочнемо з техніки під назвою [Керована поведінкою розробка](https://uk.wikipedia.org/wiki/Керована_поведінкою_розробка) або коротко, BDD (від англ. behavior-driven development).
25
+
Розпочнімо з техніки під назвою [Керована поведінкою розробка](https://uk.wikipedia.org/wiki/Керована_поведінкою_розробка) або коротко, BDD (від англ. behavior-driven development).
26
26
27
27
**BDD це три в одному: і тести, і документація, і приклади використання.**
28
28
@@ -32,7 +32,7 @@
32
32
33
33
Припустимо, ми хочемо зробити функцію `pow(x, n)`, яка піднесе `x` до степеня `n`. Ми припускаємо, що `n≥0`.
34
34
35
-
Це завдання є просто прикладом - в JavaScript є оператор `**`, що підносить до степеня, але в цьому прикладі ми зосередимось на процесі розробки, який потім можна також застосовувати і для більш складних завдань.
35
+
Це завдання є просто прикладом - в JavaScript є оператор `**`, що підносить до степеня, але в цьому прикладі ми зосередимось на процесі розробки, який потім можна також застосовувати й для складніших завдань.
36
36
37
37
Перш ніж створити код для функції `pow ', ми можемо уявити, що вона повинна виконувати, і описати її.
38
38
@@ -57,11 +57,11 @@ describe("pow", function() {
57
57
: У першому аргументі (назві) `it` ми описуємо *людською мовою* конкретний спосіб використання функції, а у другому аргументі пишемо функцію, яка тестуватиме цей спосіб.
58
58
59
59
`assert.equal(value1, value2)`
60
-
: Код, всереді блоку `it`, якщо реалізація правильна, повинен виконуватись без помилок.
60
+
: Код, всередині блоку `it`, якщо реалізація правильна, повинен виконуватись без помилок.
61
61
62
62
Функції `assert.*` використовуються для перевірки того, що функція `pow` працює, як ми очікуємо. В нашому випадку, ми використовуємо одну з них -- `assert.equal`, вона порівнює аргументи і сповіщає про помилку, якщо вони відрізняються. Тут вона перевіряє, що результат `pow(2, 3)` дорівнює `8`. Є також інші способи порівняння та перевірки, які ми розглянемо пізніше.
63
63
64
-
Специфікацію можна виконати, і вона у свою чергу виконає тести вказані у блоках `it`. Ми розглянемо це далі.
64
+
Специфікацію можна виконати, і вона автоматично виконає тести вказані у блоках `it`. Ми розглянемо це далі.
65
65
66
66
## Процес розробки
67
67
@@ -71,15 +71,15 @@ describe("pow", function() {
71
71
2. Створюється початкова реалізація.
72
72
3. Щоб перевірити, чи вона працює, ми використовуємо тестовий фреймворк [Mocha](https://mochajs.org/) (більш детально нижче), який виконує специфікацію. Якщо функціонал не завершено -- виводяться повідомлення про помилки. Ми робимо виправлення до тих пір, поки не матимемо повністю робочий код.
73
73
4. Тепер ми маємо початкову реалізацію з тестами.
74
-
5. Ми додаємо більше способів використання до специфікації, навіть таких, що поки що не підтримуються реалізацією. Виконання тестів знову завершиться невдачою.
74
+
5. Ми додаємо більше способів використання до специфікації, навіть таких, що поки що не підтримуються реалізацією. Виконання тестів знову завершиться невдачею.
75
75
6. Переходимо на 3-й пункт, змінюємо реалізацію, щоб вона відповідала тестам і вони не повертали повідомлення про помилку.
76
76
7. Повторюємо процес, описаний у пунктах з 3-го по 6-ий, поки функціонал не буде повністю готовий.
77
77
78
78
Тобто, процес розробки є *ітеративним*. Ми пишемо специфікацію, реалізуємо її, переконуємось, що тести проходять, потім пишемо ще тести, переконуємось, що вони також проходять і т.д. Завершивши цей процес, ми маємо реалізований робочий функціонал і тести до нього.
79
79
80
-
Давайте розглянемо цей процес розробки на нашому прикладі.
80
+
Розгляньмо цей процес розробки на нашому прикладі.
81
81
82
-
Перший пункт вже виконано -- ми маємо первинну специфікацію для функції `pow`. Тепер, перед початком написання коду, давайте використаємо декілька бібліотек JavaScript для запуску тестів, щоб перевірити, що вони працюють (звичайно, без коду функції, вони всі завершаться невдачою).
82
+
Перший пункт вже виконано -- ми маємо первинну специфікацію для функції `pow`. Тепер, перед початком написання коду, використаймо декілька бібліотек JavaScript для запуску тестів, щоб перевірити, що вони працюють (звичайно, без коду функції, вони всі завершаться невдачею).
Поки що тест провалюється, є помилка. Це логічно - код функції `pow` пустий, тобто `pow(2,3)`поверає`undefined` замість `8`.
111
+
Поки що тест провалюється, є помилка. Це логічно - код функції `pow` пустий, тобто `pow(2,3)`повертає`undefined` замість `8`.
112
112
113
113
На майбутнє зазначимо, що є більш високорівневі засоби для запуску тестів, наприклад [karma](https://karma-runner.github.io/) та інші, які полегшують автоматичний запуск різних тестів.
114
114
115
115
## Первинна реалізація
116
116
117
-
Давайте розробимо первинну реалізацію функції `pow`, щоб тести проходили:
117
+
Розробімо первинну реалізацію функції `pow`, щоб тести проходили:
118
118
119
119
```js
120
120
functionpow(x, n) {
@@ -166,7 +166,7 @@ function pow(x, n) {
166
166
});
167
167
```
168
168
169
-
Принципова відмінність полягає в тому, що коли `assert` повертає помилку, блок `it` негайно припиняється. Отже, у першому варіанті, якщо перший `assert` не вдасться, ми ніколи не отримаємо результат другого`assert`.
169
+
Принципова відмінність полягає в тому, що коли `assert` повертає помилку, блок `it` негайно припиняється. Отже, у першому варіанті, якщо перший `assert` не вдасться, ми ніколи не отримаємо результат другого`assert`.
170
170
171
171
Створення тестів окремо корисно, щоб отримати більше інформації про те, що відбувається, так що другий варіант краще.
172
172
@@ -186,7 +186,7 @@ function pow(x, n) {
186
186
187
187
## Вдосконалення реалізації
188
188
189
-
Давайте напишемо щось більш реальне для проходження тестів:
189
+
Напишімо щось більш реальне для проходження тестів:
190
190
191
191
```js
192
192
function pow(x, n) {
@@ -200,7 +200,7 @@ function pow(x, n) {
200
200
}
201
201
```
202
202
203
-
Щоб переконатися, що функція працює правильно, давайте перевіримо більше значень. Замість того, щоб писати блоки `it` вручну, ми можемо генерувати їх в циклі `for`:
203
+
Щоб переконатися, що функція працює правильно, перевірмо більше значень. Замість того, щоб писати блоки `it` вручну, ми можемо генерувати їх в циклі `for`:
204
204
205
205
```js
206
206
describe("pow", function() {
@@ -225,7 +225,7 @@ describe("pow", function() {
225
225
226
226
## Вкладені інструкції "describe"
227
227
228
-
Ми додамо ще більше тестів. Але перед цим зазначимо, що дпоміжна функція `makeTest` та цикл `for` повинні бути згруповані разом. Нам не знадобиться `makeTest` в інших тестах - вона потрібна лише для циклу `for`- їх спільне завдання перевіряти `pow`, звівши число до заданого степеня.
228
+
Ми додамо ще більше тестів. Але перед цим зазначимо, що допоміжна функція `makeTest` та цикл `for` повинні бути згруповані разом. Нам не знадобиться `makeTest` в інших тестах - вона потрібна лише для циклу `for`- їх спільне завдання перевіряти `pow`, звівши число до заданого степеня.
229
229
230
230
Групування проводиться за допомогою вкладеної інструкції `describe`:
[edit src="beforeafter" title="Відкрити приклад в пісочниці."]
298
298
299
-
Як правило, `beforeEach/afterEach` і `before/after` використовуються для виконання ініціалізації, обнулення лічильників або ще для чогось між тестами (або групами тестів).
299
+
Як правило, `beforeEach/afterEach` і `before/after` використовуються для виконання ініціалізації, скидання лічильників або ще для чогось між тестами (або групами тестів).
300
300
````
301
301
302
302
## Розширення специфікації
303
303
304
-
Основна функціональність `pow` завершена. Перша ітерація розробки завершена. Відсвяткувавши та випивши шампанське, давайте продовжемо вдосконалювати її.
304
+
Основна функціональність `pow` завершена. Перша ітерація розробки завершена. Відсвяткувавши та випивши шампанське, продовжмо вдосконалювати її.
305
305
306
306
Як було сказано, функція `pow(x, n)` має працювати з додатними цілими значеннями `n`.
307
307
@@ -387,23 +387,23 @@ function pow(x, n) {
387
387
388
388
Це особливо важливо для великих проєктів, коли функція використовується в багатьох місцях. Коли ми змінюємо таку функцію, просто неможливо вручну перевірити, чи кожне місце, яке її використовує, все ще працює правильно.
389
389
390
-
Без тестів люди мають два варіанта:
390
+
Без тестів люди мають два варіанти:
391
391
392
392
1. Здійснити зміну, незважаючи ні на що. І тоді наші користувачі зустрічаються з помилками, оскільки ми, мабуть, не перевірили щось вручну.
393
393
2. Або, якщо покарання за помилки суворе, оскільки немає тестів, люди бояться змінювати такі функції, і тоді код застаріває, ніхто не хоче його правити. Це не добре для розробки.
394
394
395
395
**Автоматичне тестування допомагає уникнути цих проблем!**
396
396
397
-
Якщо проєкт покритий тестами, такої проблеми просто немає. Після будь-яких змін ми можемо запустити тести і побачити безліч перевірок, зроблених за лічені секунди.
397
+
Якщо проєкт покритий тестами, такої проблеми просто немає. Після будь-яких змін ми можемо запустити тести й побачити безліч перевірок, зроблених за лічені секунди.
398
398
399
399
**Крім того, добре перевірений код має кращу архітектуру.**
400
400
401
401
Звісно, це тому, що автоматично перевірений код легше змінювати та вдосконалювати. Але є й інша причина.
402
402
403
403
Для написання тестів код повинен бути організований таким чином, щоб кожна функція мала чітко описане завдання, чітко визначені вхідні дані та вихідний результат. Це означає хорошу архітектуру з самого початку.
404
404
405
-
У реальному житті це часом не так просто. Іноді складно написати специфікацію перед фактичним кодом, тому що ще не зрозуміло, як вона повинна вести себе. Але в цілому написання тестів робить розробку швидшою і стабільнішою.
405
+
У реальному житті це часом не так просто. Іноді складно написати специфікацію перед фактичним кодом, тому що ще не зрозуміло, як він повинен поводитись. Але в цілому написання тестів робить розробку швидшою і стабільнішою.
406
406
407
407
Пізніше в підручнику ви зустрінете багато завдань з тестами. Тож ви побачите більше практичних прикладів.
408
408
409
-
Написання тестів вимагає хороших знань JavaScript. Але ми тільки починаємо це вивчати. Отже, не хвилюйтесь, поки що вам не потрібно писати тести, але ви вже маєте можливість їх прочитати, навіть якщо вони будут трохи складніші, ніж ті, що навдені у цій главі.
409
+
Написання тестів вимагає хороших знань JavaScript. Але ми тільки починаємо це вивчати. Отже, не хвилюйтесь, поки що вам не потрібно писати тести, але ви вже маєте можливість їх прочитати, навіть якщо вони будуть трохи складніші, ніж ті, що наведені у цій главі.
0 commit comments