init
This commit is contained in:
parent
06f61d8ce8
commit
f301cb744d
2271 changed files with 103162 additions and 0 deletions
17
01-js/03-writing-js/04-testing/01-pow-nan-spec/solution.md
Normal file
17
01-js/03-writing-js/04-testing/01-pow-nan-spec/solution.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
|
||||
```js
|
||||
function pow(x, n) {
|
||||
*!*
|
||||
if (n < 0) return NaN;
|
||||
if (Math.round(n) != n) return NaN;
|
||||
*/!*
|
||||
|
||||
var result = 1;
|
||||
for(var i=0; i<n; i++) {
|
||||
result *= x;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
17
01-js/03-writing-js/04-testing/01-pow-nan-spec/task.md
Normal file
17
01-js/03-writing-js/04-testing/01-pow-nan-spec/task.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Сделать pow по спецификации
|
||||
|
||||
[importance 5]
|
||||
|
||||
Исправьте код функции `pow`, чтобы тесты проходили.
|
||||
|
||||
Для этого ниже в задаче вы найдёте ссылку на песочницу.
|
||||
|
||||
Она содержит HTML с тестами. Обратите внимание, что HTML-страница в ней короче той, что обсуждалась в статье [](/testing). Это потому что библиотеки Chai, Mocha и Sinon объединены в один файл:
|
||||
|
||||
```html
|
||||
<script src="http://js.cx/test/libs.js"></script>
|
||||
```
|
||||
|
||||
Этот файл содержит код библиотек, стили, настройки для них и запуск `mocha.run` по окончании загрузки страницы. Если нет элемента с `id="mocha"`, то результаты выводятся в `<body>`.
|
||||
|
||||
Сборка сделана исключительно для более компактного представления задач, без рекомендаций использовать именно её в проектах.
|
38
01-js/03-writing-js/04-testing/02-pow-test-0/solution.md
Normal file
38
01-js/03-writing-js/04-testing/02-pow-test-0/solution.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
Новый тест может быть, к примеру, таким:
|
||||
|
||||
```js
|
||||
it("любое число в степени 0 равно 1", function() {
|
||||
assert.equal( pow(123, 0), 1);
|
||||
});
|
||||
```
|
||||
|
||||
Конечно, желательно проверить на нескольких числах.
|
||||
|
||||
Поэтому лучше будет создать блок `describe`, аналогичный тому, что мы делали для произвольных чисел:
|
||||
|
||||
```js
|
||||
describe("любое число, кроме нуля, в степени 0 равно 1", function() {
|
||||
|
||||
function makeTest(x) {
|
||||
it("при возведении " + x + " в степень 0 результат: 1", function() {
|
||||
assert.equal( pow(x, 0), 1);
|
||||
});
|
||||
}
|
||||
|
||||
for(var x = -5; x <= 5; x+=2) {
|
||||
makeTest(x);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
И не забудем добавить отдельный тест для нуля:
|
||||
|
||||
```js
|
||||
...
|
||||
it("ноль в нулевой степени даёт NaN", function() {
|
||||
assert( isNaN(pow(0,0), "0 в степени 0 не NaN");
|
||||
});
|
||||
...
|
||||
```
|
||||
|
7
01-js/03-writing-js/04-testing/02-pow-test-0/task.md
Normal file
7
01-js/03-writing-js/04-testing/02-pow-test-0/task.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Добавьте тест к задаче
|
||||
|
||||
[importance 5]
|
||||
|
||||
Добавьте к [предыдущей задаче](/task/pow-nan-spec) тесты, которые будет проверять, что любое число, кроме нуля, в нулевой степени равно `1`, а ноль в нулевой степени даёт `NaN` (это математически корректно, результат 0<sup>0</sup> не определён).
|
||||
|
||||
При необходимости, исправьте реализацию, чтобы тесты проходили без ошибок.
|
27
01-js/03-writing-js/04-testing/03-pow-test-wrong/solution.md
Normal file
27
01-js/03-writing-js/04-testing/03-pow-test-wrong/solution.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
Этот тест демонстрирует один из соблазнов, которые ожидают начинающего автора тестов.
|
||||
|
||||
Вместо того, чтобы написать три различных теста, он изложил их в виде одного потока вычислений, с несколькими `assert`.
|
||||
|
||||
Иногда так написать легче и проще, однако при ошибке в тесте гораздо менее очевидно, что же пошло не так.
|
||||
|
||||
Если в сложном тесте произошла ошибка где-то посередине потока вычислений, то придётся выяснять, какие конкретно были входные и выходные данные на этот момент, то есть по сути -- отлаживать код самого теста.
|
||||
|
||||
Гораздо лучше будет разбить тест на несколько блоков `it`, с чётко прописанными входными и выходными данными.
|
||||
|
||||
```js
|
||||
describe("Возводит x в степень n", function() {
|
||||
it("5 в степени 1 равно 5", function() {
|
||||
assert.equal( pow(5, 1), 5 );
|
||||
});
|
||||
|
||||
it("5 в степени 2 равно 25", function() {
|
||||
assert.equal( pow(5, 2), 25 );
|
||||
});
|
||||
|
||||
it("5 в степени 3 равно 125", function() {
|
||||
assert.equal( pow(5, 3), 25 );
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Можно использовать цикл для генерации блоков `it`, в этом случае важно, чтобы сам код такого цикла был достаточно простым. Иногда проще записать несколько блоков `it` вручную, как сделано выше, чем "городить огород" из синтаксических конструкций.
|
22
01-js/03-writing-js/04-testing/03-pow-test-wrong/task.md
Normal file
22
01-js/03-writing-js/04-testing/03-pow-test-wrong/task.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Что не так в тесте?
|
||||
|
||||
[importance 5]
|
||||
|
||||
Что не так в этом тесте функции `pow`?
|
||||
|
||||
```js
|
||||
it("Возводит x в степень n", function() {
|
||||
var x = 5;
|
||||
|
||||
var result = x;
|
||||
assert.equal( pow(x, 1), result );
|
||||
|
||||
var result *= x;
|
||||
assert.equal( pow(x, 2), result );
|
||||
|
||||
var result *= x;
|
||||
assert.equal( pow(x, 3), result );
|
||||
});
|
||||
```
|
||||
|
||||
P.S. Синтаксически он верен и работает, но спроектирован неправильно.
|
447
01-js/03-writing-js/04-testing/article.md
Normal file
447
01-js/03-writing-js/04-testing/article.md
Normal file
|
@ -0,0 +1,447 @@
|
|||
# Автоматические тесты при помощи chai и mocha
|
||||
|
||||
В этой главе мы разберём основы автоматического тестирования. Оно будет применяться далее в задачах, и вообще, входит в "образовательный минимум" программиста.
|
||||
|
||||
[cut]
|
||||
|
||||
## Зачем нужны тесты?
|
||||
|
||||
При написании функции мы обычно представляем, что она должна делать, какое значение -- на каких аргументах выдавать.
|
||||
|
||||
В процессе разработки мы, время от времени, проверяем функцию. Самый простой способ проверки -- это запустить функцию и посмотреть результат.
|
||||
|
||||
Потом написать ещё код, попробовать запустить -- опять посмотреть результат.
|
||||
|
||||
И так -- "до победного конца".
|
||||
|
||||
К сожалению, такие ручные запуски -- очень несовершенное средство проверки.
|
||||
|
||||
**Когда проверяешь работу кода вручную -- легко его "недотестировать".**
|
||||
|
||||
Например, пишем функцию `f`. Написали, тестируем с разными аргументами. Вызов функции `f(a)` -- работает, а вот `f(b)` -- не работает. Поправили код -- стало работать `f(b)`, вроде закончили. Но при этом забыли заново протестировать `f(a)` -- упс, вот и возможная ошибка в коде.
|
||||
|
||||
**Автоматизированное тестирование -- это когда тесты написаны отдельно от кода, и можно в любой момент запустить их и проверить все важные случаи использования.**
|
||||
|
||||
## BDD -- поведенческие тесты кода
|
||||
|
||||
Мы рассмотрим методику тестирования, которая входит в [BDD](http://en.wikipedia.org/wiki/Behavior-driven_development) -- Behavior Driven Development. Подход BDD давно и с успехом используется во многих проектах.
|
||||
|
||||
BDD -- это не просто тесты. Это гораздо больше.
|
||||
|
||||
**Тесты BDD -- это три в одном: это И тесты И документация И примеры использования одновременно.**
|
||||
|
||||
Впрочем, хватит слов. Рассмотрим примеры.
|
||||
|
||||
## Разработка pow
|
||||
|
||||
Допустим, мы хотим разработать функцию `pow(x, n)`, которая возводит `x` в целую степень `n`, для простоты `n≥0`.
|
||||
|
||||
### Спецификация
|
||||
|
||||
Ещё до разработки мы можем представить себе, что эта функция будет делать и описать это по методике BDD.
|
||||
|
||||
Это описание называется *спецификация* (или, как говорят в обиходе, "спека") и выглядит так:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
it("возводит в n-ю степень", function() {
|
||||
assert.equal( pow(2, 3), 8);
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
У спецификации есть три основных строительных блока, которые вы видите в примере выше:
|
||||
<dl>
|
||||
<dt>`describe(название, function() { ... })`</dt>
|
||||
<dd>Задаёт, что именно мы описываем, используется для группировки "рабочих лошадок" -- блоков `it`. В данном случае мы описываем функцию `pow`.</dd>
|
||||
<dt>`it(название, function() { ... })`</dt>
|
||||
<dd>В названии блока `it` *человеческим языком* описывается, что должна делать функция, далее следует *тест*, который проверяет это.</dd>
|
||||
<dt>`assert.equal(value1, value2)`</dt>
|
||||
<dd>Код внутри `it`, если реализация верна, должен выполняться без ошибок.
|
||||
|
||||
Для того, чтобы проверить, делает ли `pow` то, что задумано, используются функции вида `assert.*`. Пока что нас интересует только одна из них -- `assert.equal`, она сравнивает свой первый аргумент со вторым и выдаёт ошибку в случае, когда они не равны. Есть и другие виды сравнений и проверок, которые мы увидим далее.</dd>
|
||||
</dl>
|
||||
|
||||
Как правило, поток разработки таков:
|
||||
<ol>
|
||||
<li>Пишется спецификация, которая описывает самый базовый функционал.</li>
|
||||
<li>Делается начальная реализация.</li>
|
||||
<li>Для проверки соответствия спецификации мы задействуем одновременно фреймворк, в нашем случае [Mocha](http://visionmedia.github.io/mocha/) вместе со спецификацией и реализацией. Фреймворк запускает все тесты `it` и выводит ошибки, если они возникнут. При ошибках вносятся исправления.</li>
|
||||
<li>Спецификация расширяется, в неё добавляются возможности, которые пока, возможно, не поддерживаются реализацией.</li>
|
||||
<li>Идём на пункт 3, делаем реализацию, и так далее, до победного конца.</li>
|
||||
</ol>
|
||||
|
||||
Разработка ведётся *итеративно*, один проход за другим, пока спецификация и реализация не будут завершены.
|
||||
|
||||
В нашем случае первый шаг уже завершён, начальная спецификация готова, хорошо бы приступить к реализации. Но перед этим проведём "нулевой" запуск спецификации, просто чтобы увидеть, что уже в таком виде, даже без реализации -- тесты работают.
|
||||
|
||||
### Проверка спецификации
|
||||
|
||||
Для запуска тестов нужны соответствующие JavaScript-библиотеки.
|
||||
|
||||
Мы будем использовать:
|
||||
<ul>
|
||||
<li>[Mocha](http://visionmedia.github.io/mocha/) -- эта библиотека содержит общие функции для тестирования, включая `describe` и `it`.</li>
|
||||
<li>[Chai](http://chaijs.com) -- библиотека поддерживает разнообразные функции для проверок. Есть разные "стили" проверки результатов, с которыми мы познакомимся позже, на текущий момент мы будем использовать лишь `assert.equal`.</li>
|
||||
<li>[Sinon](http://sinonjs.org/) -- для эмуляции и хитрой подмены функций "заглушками", понадобится позднее.</li>
|
||||
</ul>
|
||||
|
||||
Эти библиотеки позволяют тестировать JS не только в браузере, но и на сервере Node.JS. Здесь мы рассмотрим браузерный вариант, серверный использует те же функции.
|
||||
|
||||
Пример HTML-страницы для тестов:
|
||||
|
||||
```html
|
||||
<!--+ src="index.html" -->
|
||||
```
|
||||
|
||||
Эту страницу можно условно разделить на три части:
|
||||
<ol>
|
||||
<li>В `<head>` подключаем библиотеки и стили.</li>
|
||||
<li>Подключаем `<script>` с реализацией, в нашем случае -- с кодом для `pow`. Пока что функции нет, мы лишь готовимся её написать.</li>
|
||||
<li>Далее подключаются тесты, файл `test.js` содержит `describe("pow", ...)`, который был описан выше. Методы `describe` и `it` принадлежат библиотеке Mocha, так что важно, что она была подключена выше. Их вызов добавляет тесты, для запуска которых используется команда `mocha.run()`. Она выведет результат тестов в элемент с `id="mocha"`.</li>
|
||||
</ol>
|
||||
|
||||
Результат срабатывания:
|
||||
|
||||
[iframe height=250 src="pow-1" border=1 edit]
|
||||
|
||||
Пока что у нас одна функция и одна спецификация, но на будущее заметим, что если различных функций и тестов много -- это не проблема, можно их все подключить на одной странице. Конфликта не будет, так как каждый функционал имеет свой блок `describe("что тестируем"...)`. Сами же тесты обычно пишутся так, чтобы не влиять друг на друга, не делать лишних глобальных переменных.
|
||||
|
||||
Посмотрели, попробовали запустить у себя что-то подобное? Если да -- идём дальше.
|
||||
|
||||
### Начальная реализация
|
||||
|
||||
Пока что, как видно, тесты не проходят, ошибка сразу же. Давайте сделаем минимальную реализацию `pow`, которая бы работала нормально:
|
||||
|
||||
```js
|
||||
function pow() {
|
||||
return 8; // :) мы - мошенники!
|
||||
}
|
||||
```
|
||||
|
||||
О, вот теперь работает:
|
||||
|
||||
[iframe height=250 src="pow-min" border=1 edit]
|
||||
|
||||
### Расширение спецификации
|
||||
|
||||
Функция, конечно, ещё не готова, но тесты проходят. Это ненадолго :)
|
||||
|
||||
Здесь мы видим ситуацию, которая (и не обязательно при ленивом программисте!) бывает на практике -- да, есть тесты, они проходят, но увы, функция работает неправильно.
|
||||
|
||||
**С точки зрения BDD, ошибка при проходящих тестах -- вина спецификации.**
|
||||
|
||||
В первую очередь не реализация исправляется, а уточняется спецификация, пишется (падающий) тест.
|
||||
|
||||
Сейчас мы расширим спецификацию, добавив проверку на `pow(3, 4) = 81`.
|
||||
|
||||
Здесь есть два варианта организации кода:
|
||||
|
||||
<ol>
|
||||
<li>Первый вариант -- добавить `assert` в тот же `it`:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
it("возводит в n-ю степень", function() {
|
||||
assert.equal( pow(2, 3), 8);
|
||||
*!*
|
||||
assert.equal( pow(3, 4), 81);
|
||||
*/!*
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
</li>
|
||||
<li>Второй вариант -- сделать два теста:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
it("при возведении 2 в 3ю степень результат 8", function() {
|
||||
assert.equal( pow(2, 3), 8);
|
||||
});
|
||||
|
||||
it("при возведении 3 в 4ю степень равен 81", function() {
|
||||
assert.equal( pow(3, 4), 81);
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
Их принципиальное различие в том, что если `assert` обнаруживает ошибку, то он тут же прекращает выполнение блоки `it`. Поэтому в первом варианте, если вдруг первый `assert` "провалился", то про результат второго мы никогда не узнаем.
|
||||
|
||||
**Таким образом, разделить эти тесты может быть полезно, чтобы мы получили больше информации о происходящем.**
|
||||
|
||||
Кроме того, есть ещё одно правило, которое желательно соблюдать.
|
||||
|
||||
**Один тест тестирует ровно одну вещь.**
|
||||
|
||||
Если мы явно видим, что тест включает в себя совершенно независимые проверки -- лучше разбить его на два более простых и наглядных.
|
||||
|
||||
По этим причинам второй вариант здесь предпочтительнее.
|
||||
|
||||
Результат:
|
||||
[iframe height=250 src="pow-2" edit border="1"]
|
||||
|
||||
Как и следовало ожидать, второй тест не проходит. Ещё бы, ведь функция всё время возвращает `8`.
|
||||
|
||||
### Уточнение реализации
|
||||
|
||||
Придётся написать нечто более реальное:
|
||||
|
||||
```js
|
||||
function pow(x, n) {
|
||||
var result = 1;
|
||||
|
||||
for(var i = 0; i < n; i++) {
|
||||
result *= x;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
Чтобы быть уверенными, что функция работает верно, желательно протестировать её на большем количестве значений. Вместо того, чтобы писать блоки `it` вручную, мы можем сгенерировать тесты в цикле `for`:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
function makeTest(x) {
|
||||
var expected = x*x*x;
|
||||
it("при возведении " + x + " в степень 3 результат: " + expected, function() {
|
||||
assert.equal( pow(x, 3), expected);
|
||||
});
|
||||
}
|
||||
|
||||
for(var x = 1; x <= 5; x++) {
|
||||
makeTest(x);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
Результат:
|
||||
[iframe height=250 src="pow-3" edit border="1"]
|
||||
|
||||
|
||||
### Вложенный describe
|
||||
|
||||
Функция `makeTest` и цикл `for`, очевидно, нужны друг другу, но не нужны для других тестов, которые мы добавим в дальнейшем. Они образуют единую группу, задача которой -- проверить возведение в `n`-ю степень.
|
||||
|
||||
Будет правильно выделить их, при помощи вложенного блока `describe`:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
*!*
|
||||
describe("возводит x в степень n", function() {
|
||||
*/!*
|
||||
|
||||
function makeTest(x) {
|
||||
var expected = x*x*x;
|
||||
it("при возведении " + x + " в степень 3 результат: " + expected, function() {
|
||||
assert.equal( pow(x, 3), expected);
|
||||
});
|
||||
}
|
||||
|
||||
for(var x = 1; x <= 5; x++) {
|
||||
makeTest(x);
|
||||
}
|
||||
|
||||
*!*
|
||||
});
|
||||
*/!*
|
||||
|
||||
// ... дальнейшие тесты it и подблоки describe ...
|
||||
});
|
||||
```
|
||||
|
||||
Вложенный `describe` объявит новую "подгруппу" тестов, блоки `it` которой запускаются так же, как и обычно, но выводятся с подзаголовком, вот так:
|
||||
|
||||
[iframe height=300 src="pow-4" edit border="1"]
|
||||
|
||||
В будущем мы сможем в добавить другие тесты `it` и блоки `describe` со своими вспомогательными функциями.
|
||||
|
||||
[smart header="before/after и beforeEach/afterEach"]
|
||||
В каждом блоке `describe` можно также задать функции `before/after`, которые будут выполнены до/после запуска тестов, а также `beforeEach/afterEach`, которые выполняются до/после каждого `it`.
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
describe("Тест", function() {
|
||||
|
||||
before(function() { alert("Начало тестов"); });
|
||||
after(function() { alert("Конец тестов"); });
|
||||
|
||||
beforeEach(function() { alert("Вход в тест"); });
|
||||
afterEach(function() { alert("Выход из теста"); });
|
||||
|
||||
it('тест 1', function() { alert('1'); });
|
||||
it('тест 2', function() { alert('2'); });
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
Последовательность будет такой:
|
||||
|
||||
```
|
||||
Начало тестов
|
||||
Вход в тест
|
||||
1
|
||||
Выход из теста
|
||||
Вход в тест
|
||||
2
|
||||
Выход из теста
|
||||
Конец тестов
|
||||
```
|
||||
|
||||
[edit src="beforeafter"]Открыть пример с тестами в песочнице[/edit]
|
||||
|
||||
Как правило, `beforeEach/afterEach` (`before/each`) используют, если необходимо произвести инициализацию, обнулить счётчики или сделать что-то ещё в таком духе между тестами (или их группами).
|
||||
[/smart]
|
||||
|
||||
### Расширение спецификации
|
||||
|
||||
**Базовый функционал описан и реализован, первая итерация разработки завершена. Теперь расширим и уточним его.**
|
||||
|
||||
Как говорилось ранее, функция `pow(x, n)` предназначена для работы с целыми неотрицательными `n`.
|
||||
|
||||
В JavaScript для ошибки вычислений служит специальное значение `NaN`, которое функция будет возвращать при некорректных `n`.
|
||||
|
||||
Добавим это поведение в спецификацию:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
// ...
|
||||
|
||||
it("при возведении в отрицательную степень результат NaN", function() {
|
||||
*!*
|
||||
assert( isNaN( pow(2, -1) ) );
|
||||
*/!*
|
||||
});
|
||||
|
||||
it("при возведении в дробную степень результат NaN", function() {
|
||||
*!*
|
||||
assert( isNaN( pow(2, 1.5) ) );
|
||||
*/!*
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
Результат с новыми тестами:
|
||||
[iframe height=450 src="pow-nan" edit border="1"]
|
||||
|
||||
Конечно, новые тесты не проходят, так как наша реализация ещё не поддерживает их. Так и задумано: сначала написали заведомо не работающие тесты, а затем пишем реализацию под них.
|
||||
|
||||
### Другие assert
|
||||
|
||||
**Обратим внимание, в спецификации выше использована проверка не `assert.equal`, как раньше, а `assert(выражение)`. Такая проверка выдаёт ошибку, если значение выражения при приведении к логическому типу не `true`.**
|
||||
|
||||
Она потребовалась, потому что сравнивать с `NaN` обычным способом нельзя: `NaN` не равно никакому значению, даже самому себе, поэтому `assert.equal(NaN, x)` не подойдёт.
|
||||
|
||||
Кстати, мы и ранее могли бы использовать `assert(value1 == value2)` вместо `assert.equal(value1, value2)`. Оба этих `assert` проверяют одно и тоже.
|
||||
|
||||
Однако, между этими вызовами есть отличие в деталях сообщения об ошибке.
|
||||
|
||||
При `assert` мы видим `Unspecified AssertionError`, то есть просто "что-то пошло не так", а при `assert.equal(value1, value2)` -- будут дополнительные подробности: `expected 8 to equal 81`.
|
||||
|
||||
**Поэтому рекомендуется использовать именно ту проверку, которая максимально соответствует задаче.**
|
||||
|
||||
Вот самые востребованные `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.isNaN`, но, увы, такого метода нет, поэтому приходится использовать самый общий `assert(...)`. В этом случае для того, чтобы сделать сообщение об ошибке понятнее, желательно добавить к `assert` описание.
|
||||
|
||||
**Все вызовы `assert` позволяют дополнительным последним аргументом указать строку с описанием ошибки, которое выводится, если `assert` не проходит.**
|
||||
|
||||
Добавим описание ошибки в конец наших `assert'ов`:
|
||||
|
||||
```js
|
||||
describe("pow", function() {
|
||||
|
||||
// ...
|
||||
|
||||
it("при возведении в отрицательную степень результат NaN", function() {
|
||||
*!*
|
||||
assert( isNaN( pow(2, -1) ), "pow(2, -1) не NaN" );
|
||||
*/!*
|
||||
});
|
||||
|
||||
it("при возведении в дробную степень результат NaN", function() {
|
||||
*!*
|
||||
assert( isNaN( pow(2, 1.5) ), "pow(2, 1.5) не NaN" );
|
||||
*/!*
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
Теперь результат теста гораздо яснее говорит о том, что не так:
|
||||
|
||||
[iframe height=450 src="pow-nan-assert" edit border="1"]
|
||||
|
||||
В коде тестов выше можно было бы добавить описание и к `assert.equal`, указав в конце: `assert.equal(value1, value2, "описание")`, но с равенством обычно и так всё понятно, поэтому мы так делать не будем.
|
||||
|
||||
|
||||
## Итого
|
||||
|
||||
Итак, разработка завершена, мы получили полноценную спецификацию и код, который её реализует.
|
||||
|
||||
Задачи выше позволяют дополнить её, и в результате может получиться что-то в таком духе:
|
||||
|
||||
```js
|
||||
//+ src="pow-full/test.js"
|
||||
```
|
||||
|
||||
[edit src="pow-full"]Открыть полный пример с реализацией в песочнице[/edit]
|
||||
|
||||
Эту спецификацию можно использовать как:
|
||||
<ol>
|
||||
<li>**Тесты**, которые гарантируют правильность работы кода.</li>
|
||||
<li>**Документацию** по функции, что она конкретно делает.</li>
|
||||
<li>**Примеры** использования функции, которые демонстрируют её работу внутри `it`.</li>
|
||||
</ol>
|
||||
|
||||
Имея спецификацию, мы можем улучшать, менять, переписывать функцию и легко контролировать её работу, просматривая тесты.
|
||||
|
||||
Особенно важно это в больших проектах.
|
||||
|
||||
Бывает так, что изменение в одной части кода может повлечь за собой "падение" другой части, которая её использует. Так как всё-всё в большом проекте руками не перепроверишь, то такие ошибки имеют большой шанс остаться в продукте и вылезти позже, когда проект увидит посетитель или заказчик.
|
||||
|
||||
Чтобы избежать таких проблем, бывает, что вообще стараются не трогать код, от которого много что зависит, даже если его ну очень нужно переписать. Жизнь пробивается тонкими росточками там, где должен цвести и пахнуть новый функционал.
|
||||
|
||||
**Код, покрытый автотестами, являет собой полную противоположность этому!**
|
||||
|
||||
Даже если какое-то изменение потенциально может порушить всё -- его совершенно не страшно сделать. Ведь есть масса тестов, которые быстро и в автоматическом режиме проверят работу кода и, если что-то падает -- это можно будет легко локализовать и поправить.
|
||||
|
||||
**Кроме того, код, покрытый тестами, имеет лучшую архитектуру.**
|
||||
|
||||
Конечно, это естественное следствие того, что его легче менять и улучшать. Но не только.
|
||||
|
||||
Чтобы написать тесты, нужно разбить код на функции так, чтобы для каждой функции было чётко понятно, что она получает на вход, что делает с этим и что возвращает. Это означает ясную и понятную структуру с самого начала.
|
||||
|
||||
Конечно, в реальной жизни всё не так просто. Зачастую написать тест сложно. Или сложно поддерживать тесты, поскольку код активно меняется. Сами тесты тоже пишутся по-разному, при помощи разных инструментов.
|
||||
|
||||
## Что дальше?
|
||||
|
||||
В дальнейшем условия ряда задач будут уже содержать в себе тесты. На них вы познакомитесь с дополнительными примерами.
|
||||
|
||||
Как правило, они будут вполне понятны, даже если немного выходят за пределы этой главы.
|
1
01-js/03-writing-js/04-testing/beforeafter/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/beforeafter/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"beforeafter","plunk":"5fvCTOfHF4djqEp4DdbK"}
|
24
01-js/03-writing-js/04-testing/beforeafter/index.html
Executable file
24
01-js/03-writing-js/04-testing/beforeafter/index.html
Executable file
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
12
01-js/03-writing-js/04-testing/beforeafter/test.js
Executable file
12
01-js/03-writing-js/04-testing/beforeafter/test.js
Executable file
|
@ -0,0 +1,12 @@
|
|||
describe("Тест", function() {
|
||||
|
||||
before(function() { alert("Начало тестов"); });
|
||||
after(function() { alert("Конец тестов"); });
|
||||
|
||||
beforeEach(function() { alert("Вход в тест"); });
|
||||
afterEach(function() { alert("Выход из теста"); });
|
||||
|
||||
it('тест 1', function() { alert('1'); });
|
||||
it('тест 2', function() { alert('2'); });
|
||||
|
||||
});
|
36
01-js/03-writing-js/04-testing/index.html
Executable file
36
01-js/03-writing-js/04-testing/index.html
Executable file
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
/* код функции, пока что пусто */
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
1
01-js/03-writing-js/04-testing/pow-1/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/pow-1/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"pow-1","plunk":"003cupnp0B0pLFJtkZRu"}
|
36
01-js/03-writing-js/04-testing/pow-1/index.html
Executable file
36
01-js/03-writing-js/04-testing/pow-1/index.html
Executable file
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
/* код функции, пока что пусто */
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
7
01-js/03-writing-js/04-testing/pow-1/test.js
Executable file
7
01-js/03-writing-js/04-testing/pow-1/test.js
Executable file
|
@ -0,0 +1,7 @@
|
|||
describe("pow", function() {
|
||||
|
||||
it("возводит в n-ю степень", function() {
|
||||
assert.equal( pow(2, 3), 8);
|
||||
});
|
||||
|
||||
});
|
1
01-js/03-writing-js/04-testing/pow-2/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/pow-2/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"pow-2","plunk":"DufbDFHjzwfDWcDrXblv"}
|
36
01-js/03-writing-js/04-testing/pow-2/index.html
Executable file
36
01-js/03-writing-js/04-testing/pow-2/index.html
Executable file
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
return 8;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
11
01-js/03-writing-js/04-testing/pow-2/test.js
Executable file
11
01-js/03-writing-js/04-testing/pow-2/test.js
Executable file
|
@ -0,0 +1,11 @@
|
|||
describe("pow", function() {
|
||||
|
||||
it("при возведении 2 в 3ю степень результат 8", function() {
|
||||
assert.equal( pow(2, 3), 8);
|
||||
});
|
||||
|
||||
it("при возведении 3 в 4ю степень равен 81", function() {
|
||||
assert.equal( pow(3, 4), 81);
|
||||
});
|
||||
|
||||
});
|
1
01-js/03-writing-js/04-testing/pow-3/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/pow-3/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"pow-3","plunk":"d2QCHJuI0x9ripxINGYf"}
|
43
01-js/03-writing-js/04-testing/pow-3/index.html
Executable file
43
01-js/03-writing-js/04-testing/pow-3/index.html
Executable file
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
var result = 1;
|
||||
|
||||
for(var i = 0; i < n; i++) {
|
||||
result *= x;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
14
01-js/03-writing-js/04-testing/pow-3/test.js
Executable file
14
01-js/03-writing-js/04-testing/pow-3/test.js
Executable file
|
@ -0,0 +1,14 @@
|
|||
describe("pow", function() {
|
||||
|
||||
function makeTest(x) {
|
||||
var expected = x*x*x;
|
||||
it("при возведении "+x+" в степень 3 результат: " + expected, function() {
|
||||
assert.equal( pow(x, 3), expected);
|
||||
});
|
||||
}
|
||||
|
||||
for(var x = 1; x <= 5; x++) {
|
||||
makeTest(x);
|
||||
}
|
||||
|
||||
});
|
1
01-js/03-writing-js/04-testing/pow-4/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/pow-4/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"pow-4","plunk":"gqoZ6Zd89sbh11s7k5BK"}
|
43
01-js/03-writing-js/04-testing/pow-4/index.html
Executable file
43
01-js/03-writing-js/04-testing/pow-4/index.html
Executable file
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
var result = 1;
|
||||
|
||||
for(var i = 0; i < n; i++) {
|
||||
result *= x;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
20
01-js/03-writing-js/04-testing/pow-4/test.js
Executable file
20
01-js/03-writing-js/04-testing/pow-4/test.js
Executable file
|
@ -0,0 +1,20 @@
|
|||
describe("pow", function() {
|
||||
|
||||
describe("возводит x в степень n", function() {
|
||||
|
||||
function makeTest(x) {
|
||||
var expected = x*x*x;
|
||||
it("при возведении "+x+" в степень 3 результат: " + expected, function() {
|
||||
assert.equal( pow(x, 3), expected);
|
||||
});
|
||||
}
|
||||
|
||||
for(var x = 1; x <= 5; x++) {
|
||||
makeTest(x);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// ...
|
||||
|
||||
});
|
1
01-js/03-writing-js/04-testing/pow-min/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/pow-min/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"pow-min","plunk":"LU4R80zpWQ0bipwsNfi7"}
|
36
01-js/03-writing-js/04-testing/pow-min/index.html
Executable file
36
01-js/03-writing-js/04-testing/pow-min/index.html
Executable file
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
return 8;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
7
01-js/03-writing-js/04-testing/pow-min/test.js
Executable file
7
01-js/03-writing-js/04-testing/pow-min/test.js
Executable file
|
@ -0,0 +1,7 @@
|
|||
describe("pow", function() {
|
||||
|
||||
it("возводит в n-ю степень", function() {
|
||||
assert.equal( pow(2, 3), 8);
|
||||
});
|
||||
|
||||
});
|
1
01-js/03-writing-js/04-testing/pow-nan-assert/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/pow-nan-assert/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"pow-nan-assert","plunk":"BKnkwEAsGv1PYcKzj3ej"}
|
40
01-js/03-writing-js/04-testing/pow-nan-assert/index.html
Executable file
40
01-js/03-writing-js/04-testing/pow-nan-assert/index.html
Executable file
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
var result = 1;
|
||||
for(var i=0; i<n; i++) {
|
||||
result *= x;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
26
01-js/03-writing-js/04-testing/pow-nan-assert/test.js
Executable file
26
01-js/03-writing-js/04-testing/pow-nan-assert/test.js
Executable file
|
@ -0,0 +1,26 @@
|
|||
describe("pow", function() {
|
||||
|
||||
describe("возводит x в степень n", function() {
|
||||
|
||||
function makeTest(x) {
|
||||
var expected = x*x*x;
|
||||
it("при возведении "+x+" в степень 3 результат: " + expected, function() {
|
||||
assert.equal( pow(x, 3), expected);
|
||||
});
|
||||
}
|
||||
|
||||
for(var x = 1; x <= 5; x++) {
|
||||
makeTest(x);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
it("при возведении в отрицательную степень результат NaN", function() {
|
||||
assert( isNaN( pow(2, -1) ), "pow(2, -1) не NaN" );
|
||||
});
|
||||
|
||||
it("при возведении в дробную степень результат NaN", function() {
|
||||
assert( isNaN( pow(2, 1.5) ), "pow(2, -1.5) не NaN" );
|
||||
});
|
||||
|
||||
});
|
1
01-js/03-writing-js/04-testing/pow-nan/.plnkr
Executable file
1
01-js/03-writing-js/04-testing/pow-nan/.plnkr
Executable file
|
@ -0,0 +1 @@
|
|||
{"name":"pow-nan","plunk":"3vsl9BHBHwyWIyAoRNZL"}
|
40
01-js/03-writing-js/04-testing/pow-nan/index.html
Executable file
40
01-js/03-writing-js/04-testing/pow-nan/index.html
Executable file
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<!-- подключаем стили Mocha, для отображения результатов -->
|
||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.css">
|
||||
<!-- подключаем библиотеку Mocha -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.13.0/mocha.js"></script>
|
||||
<!-- настраиваем Mocha: предстоит BDD-тестирование -->
|
||||
<script> mocha.setup('bdd'); </script>
|
||||
|
||||
<!-- подключаем chai -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/chai/1.9.0/chai.js"></script>
|
||||
<!-- в chai есть много всего, выносим assert в глобальную область -->
|
||||
<script> var assert = chai.assert; </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
function pow(x, n) {
|
||||
var result = 1;
|
||||
for(var i=0; i<n; i++) {
|
||||
result *= x;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- в этом скрипте находятся спеки -->
|
||||
<script src="test.js"></script>
|
||||
|
||||
<!-- в элементе с id="mocha" будут результаты тестов -->
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!-- запустить тесты! -->
|
||||
<script> mocha.run(); </script>
|
||||
</body>
|
||||
</html>
|
26
01-js/03-writing-js/04-testing/pow-nan/test.js
Executable file
26
01-js/03-writing-js/04-testing/pow-nan/test.js
Executable file
|
@ -0,0 +1,26 @@
|
|||
describe("pow", function() {
|
||||
|
||||
describe("возводит x в степень n", function() {
|
||||
|
||||
function makeTest(x) {
|
||||
var expected = x*x*x;
|
||||
it("при возведении "+x+" в степень 3 результат: " + expected, function() {
|
||||
assert.equal( pow(x, 3), expected);
|
||||
});
|
||||
}
|
||||
|
||||
for(var x = 1; x <= 5; x++) {
|
||||
makeTest(x);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
it("при возведении в отрицательную степень результат NaN", function() {
|
||||
assert( isNaN( pow(2, -1) ) );
|
||||
});
|
||||
|
||||
it("при возведении в дробную степень результат NaN", function() {
|
||||
assert( isNaN( pow(2, 1.5) ) );
|
||||
});
|
||||
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue