edit
This commit is contained in:
parent
e78e527866
commit
05a93ced80
212 changed files with 3213 additions and 3968 deletions
|
@ -1,12 +1,14 @@
|
|||
# Сделать pow по спецификации
|
||||
importance: 5
|
||||
|
||||
[importance 5]
|
||||
---
|
||||
|
||||
# Сделать pow по спецификации
|
||||
|
||||
Исправьте код функции `pow`, чтобы тесты проходили.
|
||||
|
||||
Для этого ниже в задаче вы найдёте ссылку на песочницу.
|
||||
|
||||
Она содержит HTML с тестами. Обратите внимание, что HTML-страница в ней короче той, что обсуждалась в статье [](/testing). Это потому что библиотеки Chai, Mocha и Sinon объединены в один файл:
|
||||
Она содержит HTML с тестами. Обратите внимание, что HTML-страница в ней короче той, что обсуждалась в статье <info:testing>. Это потому что библиотеки Chai, Mocha и Sinon объединены в один файл:
|
||||
|
||||
```html
|
||||
<script src="https://js.cx/test/libs.js"></script>
|
||||
|
|
|
@ -6,7 +6,7 @@ it("любое число в степени 0 равно 1", function() {
|
|||
});
|
||||
```
|
||||
|
||||
Конечно, желательно проверить на нескольких числах.
|
||||
Конечно, желательно проверить на нескольких числах.
|
||||
|
||||
Поэтому лучше будет создать блок `describe`, аналогичный тому, что мы делали для произвольных чисел:
|
||||
|
||||
|
@ -28,8 +28,7 @@ describe("любое число, кроме нуля, в степени 0 рав
|
|||
|
||||
И не забудем добавить отдельный тест для нуля:
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
```js no-beautify
|
||||
...
|
||||
it("ноль в нулевой степени даёт NaN", function() {
|
||||
assert( isNaN(pow(0, 0)), "0 в степени 0 не NaN");
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Добавьте тест к задаче
|
||||
importance: 5
|
||||
|
||||
[importance 5]
|
||||
---
|
||||
|
||||
# Добавьте тест к задаче
|
||||
|
||||
Добавьте к [предыдущей задаче](/task/pow-nan-spec) тесты, которые будут проверять, что любое число, кроме нуля, в нулевой степени равно `1`, а ноль в нулевой степени даёт `NaN` (это математически корректно, результат 0<sup>0</sup> не определён).
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Этот тест демонстрирует один из соблазнов, которые ожидают начинающего автора тестов.
|
||||
|
||||
Вместо того, чтобы написать три различных теста, он изложил их в виде одного потока вычислений, с несколькими `assert`.
|
||||
Вместо того, чтобы написать три различных теста, он изложил их в виде одного потока вычислений, с несколькими `assert`.
|
||||
|
||||
Иногда так написать легче и проще, однако при ошибке в тесте гораздо менее очевидно, что же пошло не так.
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Что не так в тесте?
|
||||
importance: 5
|
||||
|
||||
[importance 5]
|
||||
---
|
||||
|
||||
# Что не так в тесте?
|
||||
|
||||
Что не так в этом тесте функции `pow`?
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
При написании функции мы обычно представляем, что она должна делать, какое значение -- на каких аргументах выдавать.
|
||||
|
||||
В процессе разработки мы, время от времени, проверяем, правильно ли работает функция. Самый простой способ проверить -- это запустить её, например, в консоли, и посмотреть результат.
|
||||
В процессе разработки мы, время от времени, проверяем, правильно ли работает функция. Самый простой способ проверить -- это запустить её, например, в консоли, и посмотреть результат.
|
||||
|
||||
Если что-то не так -- поправить, опять запустить -- посмотреть результат... И так -- "до победного конца".
|
||||
Если что-то не так -- поправить, опять запустить -- посмотреть результат... И так -- "до победного конца".
|
||||
|
||||
Но такие ручные запуски -- очень несовершенное средство проверки.
|
||||
|
||||
|
@ -22,19 +22,18 @@
|
|||
|
||||
## BDD -- поведенческие тесты кода
|
||||
|
||||
Мы рассмотрим методику тестирования, которая входит в [BDD](http://en.wikipedia.org/wiki/Behavior-driven_development) -- Behavior Driven Development. Подход BDD давно и с успехом используется во многих проектах.
|
||||
Мы рассмотрим методику тестирования, которая входит в [BDD](http://en.wikipedia.org/wiki/Behavior-driven_development) -- Behavior Driven Development. Подход BDD давно и с успехом используется во многих проектах.
|
||||
|
||||
BDD -- это не просто тесты. Это гораздо больше.
|
||||
BDD -- это не просто тесты. Это гораздо больше.
|
||||
|
||||
**Тесты BDD -- это три в одном: И тесты И документация И примеры использования одновременно.**
|
||||
|
||||
Впрочем, хватит слов. Рассмотрим примеры.
|
||||
|
||||
## Разработка pow: спецификация
|
||||
## Разработка pow: спецификация
|
||||
|
||||
Допустим, мы хотим разработать функцию `pow(x, n)`, которая возводит `x` в целую степень `n`, для простоты `n≥0`.
|
||||
|
||||
|
||||
Ещё до разработки мы можем представить себе, что эта функция будет делать и описать это по методике BDD.
|
||||
|
||||
Это описание называется *спецификация* (или, как говорят в обиходе, "спека") и выглядит так:
|
||||
|
@ -50,31 +49,29 @@ describe("pow", function() {
|
|||
```
|
||||
|
||||
У спецификации есть три основных строительных блока, которые вы видите в примере выше:
|
||||
<dl>
|
||||
<dt>`describe(название, function() { ... })`</dt>
|
||||
<dd>Задаёт, что именно мы описываем, используется для группировки "рабочих лошадок" -- блоков `it`. В данном случае мы описываем функцию `pow`.</dd>
|
||||
<dt>`it(название, function() { ... })`</dt>
|
||||
<dd>В названии блока `it` *человеческим языком* описывается, что должна делать функция, далее следует *тест*, который проверяет это.</dd>
|
||||
<dt>`assert.equal(value1, value2)`</dt>
|
||||
<dd>Код внутри `it`, если реализация верна, должен выполняться без ошибок.
|
||||
|
||||
Различные функции вида `assert.*` используются, чтобы проверить, делает ли `pow` то, что задумано. Пока что нас интересует только одна из них -- `assert.equal`, она сравнивает свой первый аргумент со вторым и выдаёт ошибку в случае, когда они не равны. В данном случае она проверяет, что результат `pow(2, 3)` равен `8`.
|
||||
`describe(название, function() { ... })`
|
||||
: Задаёт, что именно мы описываем, используется для группировки "рабочих лошадок" -- блоков `it`. В данном случае мы описываем функцию `pow`.
|
||||
|
||||
`it(название, function() { ... })`
|
||||
: В названии блока `it` *человеческим языком* описывается, что должна делать функция, далее следует *тест*, который проверяет это.
|
||||
|
||||
Есть и другие виды сравнений и проверок, которые мы увидим далее.</dd>
|
||||
</dl>
|
||||
`assert.equal(value1, value2)`
|
||||
: Код внутри `it`, если реализация верна, должен выполняться без ошибок.
|
||||
|
||||
Различные функции вида `assert.*` используются, чтобы проверить, делает ли `pow` то, что задумано. Пока что нас интересует только одна из них -- `assert.equal`, она сравнивает свой первый аргумент со вторым и выдаёт ошибку в случае, когда они не равны. В данном случае она проверяет, что результат `pow(2, 3)` равен `8`.
|
||||
|
||||
Есть и другие виды сравнений и проверок, которые мы увидим далее.
|
||||
|
||||
## Поток разработки
|
||||
|
||||
Как правило, поток разработки таков:
|
||||
<ol>
|
||||
<li>Пишется спецификация, которая описывает самый базовый функционал.</li>
|
||||
<li>Делается начальная реализация.</li>
|
||||
<li>Для проверки соответствия спецификации мы задействуем одновременно фреймворк, в нашем случае [Mocha](http://mochajs.org/) вместе со спецификацией и реализацией. Фреймворк запускает все тесты `it` и выводит ошибки, если они возникнут. При ошибках вносятся исправления.</li>
|
||||
<li>Спецификация расширяется, в неё добавляются возможности, которые пока, возможно, не поддерживаются реализацией.</li>
|
||||
<li>Идём на пункт 3, делаем реализацию, и так далее, до победного конца.</li>
|
||||
</ol>
|
||||
|
||||
1. Пишется спецификация, которая описывает самый базовый функционал.
|
||||
2. Делается начальная реализация.
|
||||
3. Для проверки соответствия спецификации мы задействуем одновременно фреймворк, в нашем случае [Mocha](http://mochajs.org/) вместе со спецификацией и реализацией. Фреймворк запускает все тесты `it` и выводит ошибки, если они возникнут. При ошибках вносятся исправления.
|
||||
4. Спецификация расширяется, в неё добавляются возможности, которые пока, возможно, не поддерживаются реализацией.
|
||||
5. Идём на пункт 3, делаем реализацию, и так далее, до победного конца.
|
||||
|
||||
Разработка ведётся *итеративно*, один проход за другим, пока спецификация и реализация не будут завершены.
|
||||
|
||||
|
@ -82,34 +79,30 @@ describe("pow", function() {
|
|||
|
||||
## Пример в действии
|
||||
|
||||
Для запуска тестов нужны соответствующие JavaScript-библиотеки.
|
||||
Для запуска тестов нужны соответствующие JavaScript-библиотеки.
|
||||
|
||||
Мы будем использовать:
|
||||
<ul>
|
||||
<li>[Mocha](http://mochajs.org/) -- эта библиотека содержит общие функции для тестирования, включая `describe` и `it`.</li>
|
||||
<li>[Chai](http://chaijs.com) -- библиотека поддерживает разнообразные функции для проверок. Есть разные "стили" проверки результатов, с которыми мы познакомимся позже, на текущий момент мы будем использовать лишь `assert.equal`.</li>
|
||||
<li>[Sinon](http://sinonjs.org/) -- для эмуляции и хитрой подмены функций "заглушками", понадобится позднее.</li>
|
||||
</ul>
|
||||
|
||||
- [Mocha](http://mochajs.org/) -- эта библиотека содержит общие функции для тестирования, включая `describe` и `it`.
|
||||
- [Chai](http://chaijs.com) -- библиотека поддерживает разнообразные функции для проверок. Есть разные "стили" проверки результатов, с которыми мы познакомимся позже, на текущий момент мы будем использовать лишь `assert.equal`.
|
||||
- [Sinon](http://sinonjs.org/) -- для эмуляции и хитрой подмены функций "заглушками", понадобится позднее.
|
||||
|
||||
Эти библиотеки позволяют тестировать JS не только в браузере, но и на сервере Node.JS. Здесь мы рассмотрим браузерный вариант, серверный использует те же функции.
|
||||
|
||||
Пример HTML-страницы для тестов:
|
||||
|
||||
```html
|
||||
<!--+ src="index.html" -->
|
||||
```
|
||||
[html src="index.html"]
|
||||
|
||||
Эту страницу можно условно разделить на четыре части:
|
||||
<ol>
|
||||
<li>Блок `<head>` -- в нём мы подключаем библиотеки и стили для тестирования, нашего кода там нет.</li>
|
||||
<li>Блок `<script>` с реализацией спецификации, в нашем случае -- с кодом для `pow`.</li>
|
||||
<li>Далее подключаются тесты, файл `test.js` содержит `describe("pow", ...)`, который был описан выше. Методы `describe` и `it` принадлежат библиотеке Mocha, так что важно, что она была подключена выше.</li>
|
||||
<li>Элемент `<div id="mocha">` будет использоваться библиотекой Mocha для вывода результатов. Запуск тестов инициируется командой `mocha.run()`.</li>
|
||||
</ol>
|
||||
|
||||
1. Блок `<head>` -- в нём мы подключаем библиотеки и стили для тестирования, нашего кода там нет.
|
||||
2. Блок `<script>` с реализацией спецификации, в нашем случае -- с кодом для `pow`.
|
||||
3. Далее подключаются тесты, файл `test.js` содержит `describe("pow", ...)`, который был описан выше. Методы `describe` и `it` принадлежат библиотеке Mocha, так что важно, что она была подключена выше.
|
||||
4. Элемент `<div id="mocha">` будет использоваться библиотекой Mocha для вывода результатов. Запуск тестов инициируется командой `mocha.run()`.
|
||||
|
||||
Результат срабатывания:
|
||||
|
||||
[iframe height=250 src="pow-1" border=1 edit]
|
||||
[iframe height=250 src="pow-1" border=1 edit]
|
||||
|
||||
Пока что тесты не проходят, но это логично -- вместо функции стоит "заглушка", пустой код.
|
||||
|
||||
|
@ -127,11 +120,11 @@ function pow() {
|
|||
|
||||
О, вот теперь работает:
|
||||
|
||||
[iframe height=250 src="pow-min" border=1 edit]
|
||||
[iframe height=250 src="pow-min" border=1 edit]
|
||||
|
||||
## Исправление спецификации
|
||||
|
||||
Функция, конечно, ещё не готова, но тесты проходят. Это ненадолго :)
|
||||
Функция, конечно, ещё не готова, но тесты проходят. Это ненадолго :)
|
||||
|
||||
Здесь мы видим ситуацию, которая (и не обязательно при ленивом программисте!) бывает на практике -- да, есть тесты, они проходят, но увы, функция работает неправильно.
|
||||
|
||||
|
@ -139,45 +132,39 @@ function pow() {
|
|||
|
||||
В первую очередь не реализация исправляется, а уточняется спецификация, пишется (падающий) тест.
|
||||
|
||||
Сейчас мы расширим спецификацию, добавив проверку на `pow(3, 4) = 81`.
|
||||
Сейчас мы расширим спецификацию, добавив проверку на `pow(3, 4) = 81`.
|
||||
|
||||
Здесь есть два варианта организации кода:
|
||||
|
||||
<ol>
|
||||
<li>Первый вариант -- добавить `assert` в тот же `it`:
|
||||
1. Первый вариант -- добавить `assert` в тот же `it`:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
it("возводит в n-ю степень", function() {
|
||||
assert.equal(pow(2, 3), 8);
|
||||
*!*
|
||||
assert.equal(pow(3, 4), 81);
|
||||
*/!*
|
||||
});
|
||||
it("возводит в n-ю степень", function() {
|
||||
assert.equal(pow(2, 3), 8);
|
||||
*!*
|
||||
assert.equal(pow(3, 4), 81);
|
||||
*/!*
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
});
|
||||
```
|
||||
2. Второй вариант -- сделать два теста:
|
||||
|
||||
</li>
|
||||
<li>Второй вариант -- сделать два теста:
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
it("при возведении 2 в 3ю степень результат 8", function() {
|
||||
assert.equal(pow(2, 3), 8);
|
||||
});
|
||||
|
||||
it("при возведении 2 в 3ю степень результат 8", function() {
|
||||
assert.equal(pow(2, 3), 8);
|
||||
});
|
||||
it("при возведении 3 в 4ю степень равен 81", function() {
|
||||
assert.equal(pow(3, 4), 81);
|
||||
});
|
||||
|
||||
it("при возведении 3 в 4ю степень равен 81", function() {
|
||||
assert.equal(pow(3, 4), 81);
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
</li>
|
||||
</ol>
|
||||
});
|
||||
```
|
||||
|
||||
Их принципиальное различие в том, что если `assert` обнаруживает ошибку, то он тут же прекращает выполнение блоки `it`. Поэтому в первом варианте, если вдруг первый `assert` "провалился", то про результат второго мы никогда не узнаем.
|
||||
|
||||
|
@ -187,11 +174,12 @@ describe("pow", function() {
|
|||
|
||||
**Один тест тестирует ровно одну вещь.**
|
||||
|
||||
Если мы явно видим, что тест включает в себя совершенно независимые проверки -- лучше разбить его на два более простых и наглядных.
|
||||
Если мы явно видим, что тест включает в себя совершенно независимые проверки -- лучше разбить его на два более простых и наглядных.
|
||||
|
||||
По этим причинам второй вариант здесь предпочтительнее.
|
||||
По этим причинам второй вариант здесь предпочтительнее.
|
||||
|
||||
Результат:
|
||||
|
||||
[iframe height=250 src="pow-2" edit border="1"]
|
||||
|
||||
Как и следовало ожидать, второй тест не проходит. Ещё бы, ведь функция всё время возвращает `8`.
|
||||
|
@ -232,8 +220,8 @@ describe("pow", function() {
|
|||
```
|
||||
|
||||
Результат:
|
||||
[iframe height=250 src="pow-3" edit border="1"]
|
||||
|
||||
[iframe height=250 src="pow-3" edit border="1"]
|
||||
|
||||
## Вложенный describe
|
||||
|
||||
|
@ -273,13 +261,12 @@ describe("pow", function() {
|
|||
|
||||
В будущем мы сможем в добавить другие тесты `it` и блоки `describe` со своими вспомогательными функциями.
|
||||
|
||||
[smart header="before/after и beforeEach/afterEach"]
|
||||
В каждом блоке `describe` можно также задать функции `before/after`, которые будут выполнены до/после запуска тестов, а также `beforeEach/afterEach`, которые выполняются до/после каждого `it`.
|
||||
````smart header="before/after и beforeEach/afterEach"
|
||||
В каждом блоке `describe` можно также задать функции `before/after`, которые будут выполнены до/после запуска тестов, а также `beforeEach/afterEach`, которые выполняются до/после каждого `it`.
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
```js no-beautify
|
||||
describe("Тест", function() {
|
||||
|
||||
before(function() { alert("Начало тестов"); });
|
||||
|
@ -290,7 +277,7 @@ describe("Тест", function() {
|
|||
|
||||
it('тест 1', function() { alert('1'); });
|
||||
it('тест 2', function() { alert('2'); });
|
||||
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
|
@ -300,17 +287,17 @@ describe("Тест", function() {
|
|||
Начало тестов
|
||||
Вход в тест
|
||||
1
|
||||
Выход из теста
|
||||
Выход из теста
|
||||
Вход в тест
|
||||
2
|
||||
2
|
||||
Выход из теста
|
||||
Конец тестов
|
||||
```
|
||||
|
||||
[edit src="beforeafter"]Открыть пример с тестами в песочнице[/edit]
|
||||
[edit src="beforeafter" title="Открыть пример с тестами в песочнице"]
|
||||
|
||||
Как правило, `beforeEach/afterEach` (`before/each`) используют, если необходимо произвести инициализацию, обнулить счётчики или сделать что-то ещё в таком духе между тестами (или их группами).
|
||||
[/smart]
|
||||
Как правило, `beforeEach/afterEach` (`before/each`) используют, если необходимо произвести инициализацию, обнулить счётчики или сделать что-то ещё в таком духе между тестами (или их группами).
|
||||
````
|
||||
|
||||
## Расширение спецификации
|
||||
|
||||
|
@ -343,6 +330,7 @@ describe("pow", function() {
|
|||
```
|
||||
|
||||
Результат с новыми тестами:
|
||||
|
||||
[iframe height=450 src="pow-nan" edit border="1"]
|
||||
|
||||
Конечно, новые тесты не проходят, так как наша реализация ещё не поддерживает их. Так и задумано: сначала написали заведомо не работающие тесты, а затем пишем реализацию под них.
|
||||
|
@ -353,9 +341,9 @@ describe("pow", function() {
|
|||
|
||||
Она потребовалась, потому что сравнивать с `NaN` обычным способом нельзя: `NaN` не равно никакому значению, даже самому себе, поэтому `assert.equal(NaN, x)` не подойдёт.
|
||||
|
||||
Кстати, мы и ранее могли бы использовать `assert(value1 == value2)` вместо `assert.equal(value1, value2)`. Оба этих `assert` проверяют одно и тоже.
|
||||
Кстати, мы и ранее могли бы использовать `assert(value1 == value2)` вместо `assert.equal(value1, value2)`. Оба этих `assert` проверяют одно и тоже.
|
||||
|
||||
Однако, между этими вызовами есть отличие в деталях сообщения об ошибке.
|
||||
Однако, между этими вызовами есть отличие в деталях сообщения об ошибке.
|
||||
|
||||
При "упавшем" `assert` в примере выше мы видим `"Unspecified AssertionError"`, то есть просто "что-то пошло не так", а при `assert.equal(value1, value2)` -- будут дополнительные подробности: `expected 8 to equal 81`.
|
||||
|
||||
|
@ -363,15 +351,13 @@ describe("pow", function() {
|
|||
|
||||
Вот самые востребованные `assert`-проверки, встроенные в Chai:
|
||||
|
||||
<ul>
|
||||
<li>`assert(value)` -- проверяет что `value` является `true` в логическом контексте.</li>
|
||||
<li>`assert.equal(value1, value2)` -- проверяет равенство `value1 == value2`.</li>
|
||||
<li>`assert.strictEqual(value1, value2)` -- проверяет строгое равенство `value1 === value2`.</li>
|
||||
<li>`assert.notEqual`, `assert.notStrictEqual` -- проверки, обратные двум предыдущим.</li>
|
||||
<li>`assert.isTrue(value)` -- проверяет, что `value === true`</li>
|
||||
<li>`assert.isFalse(value)` -- проверяет, что `value === false`</li>
|
||||
<li>...более полный список -- в [документации](http://chaijs.com/api/assert/)</li>
|
||||
</ul>
|
||||
- `assert(value)` -- проверяет что `value` является `true` в логическом контексте.
|
||||
- `assert.equal(value1, value2)` -- проверяет равенство `value1 == value2`.
|
||||
- `assert.strictEqual(value1, value2)` -- проверяет строгое равенство `value1 === value2`.
|
||||
- `assert.notEqual`, `assert.notStrictEqual` -- проверки, обратные двум предыдущим.
|
||||
- `assert.isTrue(value)` -- проверяет, что `value === true`
|
||||
- `assert.isFalse(value)` -- проверяет, что `value === false`
|
||||
- ...более полный список -- в [документации](http://chaijs.com/api/assert/)
|
||||
|
||||
В нашем случае хорошо бы иметь проверку `assert.isNaN`, но, увы, такого метода нет, поэтому приходится использовать самый общий `assert(...)`. В этом случае для того, чтобы сделать сообщение об ошибке понятнее, желательно добавить к `assert` описание.
|
||||
|
||||
|
@ -405,29 +391,25 @@ describe("pow", function() {
|
|||
|
||||
В коде тестов выше можно было бы добавить описание и к `assert.equal`, указав в конце: `assert.equal(value1, value2, "описание")`, но с равенством обычно и так всё понятно, поэтому мы так делать не будем.
|
||||
|
||||
|
||||
## Итого
|
||||
|
||||
Итак, разработка завершена, мы получили полноценную спецификацию и код, который её реализует.
|
||||
|
||||
Задачи выше позволяют дополнить её, и в результате может получиться что-то в таком духе:
|
||||
|
||||
```js
|
||||
//+ src="pow-full/test.js"
|
||||
```
|
||||
[js src="pow-full/test.js"]
|
||||
|
||||
[edit src="pow-full"]Открыть полный пример с реализацией в песочнице[/edit]
|
||||
[edit src="pow-full" title="Открыть полный пример с реализацией в песочнице"]
|
||||
|
||||
Эту спецификацию можно использовать как:
|
||||
<ol>
|
||||
<li>**Тесты**, которые гарантируют правильность работы кода.</li>
|
||||
<li>**Документацию** по функции, что она конкретно делает.</li>
|
||||
<li>**Примеры** использования функции, которые демонстрируют её работу внутри `it`.</li>
|
||||
</ol>
|
||||
|
||||
1. **Тесты**, которые гарантируют правильность работы кода.
|
||||
2. **Документацию** по функции, что она конкретно делает.
|
||||
3. **Примеры** использования функции, которые демонстрируют её работу внутри `it`.
|
||||
|
||||
Имея спецификацию, мы можем улучшать, менять, переписывать функцию и легко контролировать её работу, просматривая тесты.
|
||||
|
||||
Особенно важно это в больших проектах.
|
||||
Особенно важно это в больших проектах.
|
||||
|
||||
Бывает так, что изменение в одной части кода может повлечь за собой "падение" другой части, которая её использует. Так как всё-всё в большом проекте руками не перепроверишь, то такие ошибки имеют большой шанс остаться в продукте и вылезти позже, когда проект увидит посетитель или заказчик.
|
||||
|
||||
|
@ -447,6 +429,6 @@ describe("pow", function() {
|
|||
|
||||
## Что дальше?
|
||||
|
||||
В дальнейшем условия ряда задач будут уже содержать в себе тесты. На них вы познакомитесь с дополнительными примерами.
|
||||
В дальнейшем условия ряда задач будут уже содержать в себе тесты. На них вы познакомитесь с дополнительными примерами.
|
||||
|
||||
Как правило, они будут вполне понятны, даже если немного выходят за пределы этой главы.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue