|
6 | 6 |
|
7 | 7 | ## Зачем нужны тесты? |
8 | 8 |
|
9 | | -При написании функции мы обычно представляем, что она должна делать, какое значение -- на каких аргументах выдавать. |
| 9 | +При написании функции мы обычно представляем, что она должна делать, какое значение на каких аргументах выдавать. |
10 | 10 |
|
11 | | -В процессе разработки мы, время от времени, проверяем, правильно ли работает функция. Самый простой способ проверить -- это запустить её, например, в консоли, и посмотреть результат. |
| 11 | +В процессе разработки мы время от времени проверяем, правильно ли работает функция. Самый простой способ проверить -- это запустить её, например в консоли, и посмотреть результат. |
12 | 12 |
|
13 | | -Если что-то не так -- поправить, опять запустить -- посмотреть результат... И так -- "до победного конца". |
| 13 | +Если что-то не так, поправить, опять запустить -- посмотреть результат... И так "до победного конца". |
14 | 14 |
|
15 | 15 | Но такие ручные запуски -- очень несовершенное средство проверки. |
16 | 16 |
|
17 | 17 | **Когда проверяешь работу кода вручную -- легко его "недотестировать".** |
18 | 18 |
|
19 | | -Например, пишем функцию `f`. Написали, тестируем с разными аргументами. Вызов функции `f(a)` -- работает, а вот `f(b)` -- не работает. Поправили код -- стало работать `f(b)`, вроде закончили. Но при этом забыли заново протестировать `f(a)` -- упс, вот и возможная ошибка в коде. |
| 19 | +Например, пишем функцию `f`. Написали, тестируем с разными аргументами. Вызов функции `f(a)` работает, а вот `f(b)` не работает. Поправили код -- стало работать `f(b)`, вроде закончили. Но при этом забыли заново протестировать `f(a)` -- упс, вот и возможная ошибка в коде. |
20 | 20 |
|
21 | 21 | **Автоматизированное тестирование -- это когда тесты написаны отдельно от кода, и можно в любой момент запустить их и проверить все важные случаи использования.** |
22 | 22 |
|
|
26 | 26 |
|
27 | 27 | BDD -- это не просто тесты. Это гораздо больше. |
28 | 28 |
|
29 | | -**Тесты BDD -- это три в одном: И тесты И документация И примеры использования одновременно.** |
| 29 | +**Тесты BDD -- это три в одном: И тесты, И документация, И примеры использования.** |
30 | 30 |
|
31 | 31 | Впрочем, хватит слов. Рассмотрим примеры. |
32 | 32 |
|
33 | 33 | ## Разработка pow: спецификация |
34 | 34 |
|
35 | 35 | Допустим, мы хотим разработать функцию `pow(x, n)`, которая возводит `x` в целую степень `n`, для простоты `n≥0`. |
36 | 36 |
|
37 | | -Ещё до разработки мы можем представить себе, что эта функция будет делать и описать это по методике BDD. |
| 37 | +Ещё до разработки мы можем представить себе, что эта функция будет делать, и описать это по методике BDD. |
38 | 38 |
|
39 | 39 | Это описание называется *спецификация* (или, как говорят в обиходе, "спека") и выглядит так: |
40 | 40 |
|
@@ -69,11 +69,11 @@ describe("pow", function() { |
69 | 69 |
|
70 | 70 | 1. Пишется спецификация, которая описывает самый базовый функционал. |
71 | 71 | 2. Делается начальная реализация. |
72 | | -3. Для проверки соответствия спецификации мы задействуем одновременно фреймворк, в нашем случае [Mocha](http://mochajs.org/) вместе со спецификацией и реализацией. Фреймворк запускает все тесты `it` и выводит ошибки, если они возникнут. При ошибках вносятся исправления. |
| 72 | +3. Для проверки соответствия спецификации мы задействуем фреймворк (в нашем случае [Mocha](http://mochajs.org/)). Фреймворк запускает все тесты `it` и выводит ошибки, если они возникнут. При ошибках вносятся исправления. |
73 | 73 | 4. Спецификация расширяется, в неё добавляются возможности, которые пока, возможно, не поддерживаются реализацией. |
74 | | -5. Идём на пункт 2, делаем реализацию, и так далее, до победного конца. |
| 74 | +5. Идём на пункт 2, делаем реализацию. И так "до победного конца". |
75 | 75 |
|
76 | | -Разработка ведётся *итеративно*, один проход за другим, пока спецификация и реализация не будут завершены. |
| 76 | +Разработка ведётся *итеративно*: один проход за другим, пока спецификация и реализация не будут завершены. |
77 | 77 |
|
78 | 78 | В нашем случае первый шаг уже завершён, начальная спецификация готова, хорошо бы приступить к реализации. Но перед этим проведём "нулевой" запуск спецификации, просто чтобы увидеть, что уже в таком виде, даже без реализации -- тесты работают. |
79 | 79 |
|
@@ -126,11 +126,11 @@ function pow() { |
126 | 126 |
|
127 | 127 | Функция, конечно, ещё не готова, но тесты проходят. Это ненадолго :) |
128 | 128 |
|
129 | | -Здесь мы видим ситуацию, которая (и не обязательно при ленивом программисте!) бывает на практике -- да, есть тесты, они проходят, но увы, функция работает неправильно. |
| 129 | +Здесь мы видим ситуацию, которая (и не обязательно при ленивом программисте!) бывает на практике -- да, есть тесты, они проходят, но функция (увы!) работает неправильно. |
130 | 130 |
|
131 | 131 | **С точки зрения BDD, ошибка при проходящих тестах -- вина спецификации.** |
132 | 132 |
|
133 | | -В первую очередь не реализация исправляется, а уточняется спецификация, пишется (падающий) тест. |
| 133 | +В первую очередь не реализация исправляется, а уточняется спецификация, пишется падающий тест. |
134 | 134 |
|
135 | 135 | Сейчас мы расширим спецификацию, добавив проверку на `pow(3, 4) = 81`. |
136 | 136 |
|
@@ -166,7 +166,7 @@ function pow() { |
166 | 166 | }); |
167 | 167 | ``` |
168 | 168 |
|
169 | | -Их принципиальное различие в том, что если `assert` обнаруживает ошибку, то он тут же прекращает выполнение блоки `it`. Поэтому в первом варианте, если вдруг первый `assert` "провалился", то про результат второго мы никогда не узнаем. |
| 169 | +Их принципиальное различие в том, что если `assert` обнаруживает ошибку, то он тут же прекращает выполнение блока `it`. Поэтому в первом варианте, если вдруг первый `assert` "провалился", то про результат второго мы никогда не узнаем. |
170 | 170 |
|
171 | 171 | **Таким образом, разделить эти тесты может быть полезно, чтобы мы получили больше информации о происходящем.** |
172 | 172 |
|
@@ -345,7 +345,7 @@ describe("pow", function() { |
345 | 345 |
|
346 | 346 | Однако, между этими вызовами есть отличие в деталях сообщения об ошибке. |
347 | 347 |
|
348 | | -При "упавшем" `assert` в примере выше мы видим `"Unspecified AssertionError"`, то есть просто "что-то пошло не так", а при `assert.equal(value1, value2)` -- будут дополнительные подробности: `expected 8 to equal 81`. |
| 348 | +При "упавшем" `assert` в примере выше мы видим `"Unspecified AssertionError"`, то есть просто "что-то пошло не так", а при `assert.equal(value1, value2)` будут дополнительные подробности: `expected 8 to equal 81`. |
349 | 349 |
|
350 | 350 | **Поэтому рекомендуется использовать именно ту проверку, которая максимально соответствует задаче.** |
351 | 351 |
|
@@ -417,7 +417,7 @@ describe("pow", function() { |
417 | 417 |
|
418 | 418 | **Код, покрытый автотестами, являет собой полную противоположность этому!** |
419 | 419 |
|
420 | | -Даже если какое-то изменение потенциально может порушить всё -- его совершенно не страшно сделать. Ведь есть масса тестов, которые быстро и в автоматическом режиме проверят работу кода и, если что-то падает -- это можно будет легко локализовать и поправить. |
| 420 | +Даже если какое-то изменение потенциально может порушить всё -- его совершенно не страшно сделать. Ведь есть масса тестов, которые быстро и в автоматическом режиме проверят работу кода. И если что-то падает, то это можно будет легко локализовать и поправить. |
421 | 421 |
|
422 | 422 | **Кроме того, код, покрытый тестами, имеет лучшую архитектуру.** |
423 | 423 |
|
|
0 commit comments