Assert. Mocha. Организация тестов
Тациенко Антон
«Операция завершиться через 41 секунд»
Выбрать правильную форму склонения числительного
const forms = ['секунда', 'секунды', 'секунд'];
forms[0]; // 'секунда'
forms[1]; // 'секунды'
forms[2]; // 'секунд'
function getPlural(count, forms) {
/* ... */
}
const forms = ['секунда', 'секунды', 'секунд'];
getPlural(21, forms); // 'секунда'
getPlural(62, forms); // 'секунды'
getPlural(5, forms); // 'секунд'
const forms = ['секунда', 'секунды', 'секунд'];
1
, то forms[0]
2 - 4
, то forms[1]
0, 5 - 9
, то forms[2]
11 - 14
, то forms[2]
11-14
вернуть forms[2]
10
1
вернуть forms[0]
2-4
вернуть forms[1]
0, 5-9
вернуть forms[2]
function getPlural(count, forms) {
if (count > 10 && count < 15)
return forms[2];
const residue = count % 10;
if (residue === 1)
return forms[0];
if (residue > 0 && residue < 5)
return forms[1];
return forms[2];
}
// Для 11-14
// вернуть forms[2]
// отстаток от % 10
// Для 1
// вернуть forms[0]
// Для 2-4
// вернуть forms[1]
// Иначе forms[2]
const forms = ['секунда', 'секунды', 'секунд'];
getPlural(1, forms); // 'секунда'
getPlural(2, forms); // 'секунды'
getPlural(5, forms); // 'секунд'
getPlural(11, forms); // 'секунд'
getPlural(22, forms); // 'секунды'
const forms = ['секунда', 'секунды', 'секунд'];
getPlural(1, forms) === 'секунда'; // true
getPlural(2, forms) === 'секунды'; // true
getPlural(5, forms) === 'секунд'; // true
getPlural(11, forms) === 'секунд'; // true
getPlural(22, forms) === 'секунды'; // true
function assert(value) {
const hasError = !value;
if (hasError) {
throw new Error('Assertion failed');
}
}
const assert = require('assert');
const assert = require('assert');
const forms = ['секунда', 'секунды', 'секунд'];
const actual = getPlural(1, forms);
const expected = 'секунда';
assert(actual === expected);
>
const assert = require('assert');
const forms = ['секунда', 'секунды', 'секунд'];
const actual = getPlural(1, forms);
const expected = 'секунд';
assert(actual === expected);
assert.js:89
throw new assert.AssertionError({
^
AssertionError: false == true
at Object.<anonymous> (/plural.js:17:1)
const assert = require('assert');
const forms = ['секунда', 'секунды', 'секунд'];
const actual = getPlural(1, forms);
const expected = 'секунд';
assert(actual === expected,
'Должна вернуться`секунда`,' +
'если передать `1`');
assert.js:89
throw new assert.AssertionError({
^
AssertionError: Должна вернуться`секунда`, если передать `1`
at Object.<anonymous> (/plural.js:17:1)
const assert = require('assert');
const forms = ['секунда', 'секунды', 'секунд'];
const actual = getPlural(1, forms);
const expected = 'секунда';
assert.equal(actual, expected);
assert.js:89
throw new assert.AssertionError({
^
AssertionError: 'секунда' == 'секунд'
at Object.<anonymous> (/plural.js:17:8)
const assert = require('assert');
const actual = '1';
const expected = 1;
assert.equal(actual, expected); # нет ошибки
assert.strictEqual(actual, expected);
assert.js:42
throw new errors.AssertionError({
^
AssertionError [ERR_ASSERTION]: '1' === 1
at Object.<anonymous> (/path/to/file.js:6:8)
const assert = require('assert');
const actual = ['секунда'];
const expected = ['секунда'];
assert.equal(actual, expected);
assert.js:42
throw new errors.AssertionError({
^
AssertionError [ERR_ASSERTION]: [ 'секунда' ] == [ 'секунда' ]
at Object.<anonymous> (/path/to/file.js:6:8)
const assert = require('assert');
const actual = ['секунда'];
const expected = ['секунда'];
assert.deepStrictEqual(actual, expected);
>
assert.deepEqual
assert.deepStrictEqual
assert.doesNotThrow
assert.equal
assert.fail
assert.fail
assert.ifError
assert.notDeepEqual
assert.notDeepStrictEqual
assert.notEqual
assert.notStrictEqual
assert.ok
assert.strictEqual
assert.throws
const assert = require('assert');
const forms = ['секунда', 'секунды', 'секунд'];
assert.equal(getPlural(1, forms), 'секунда');
assert.equal(getPlural(2, forms), 'секунды');
assert.equal(getPlural(11, forms), 'секунд');
assert.equal(getPlural(22, forms), 'секунды');
assert.equal(getPlural(113, forms), 'секунд');
assert.js:89
throw new assert.AssertionError({
^
AssertionError: 'секунды' == 'секунд'
at Object.<anonymous> (/plural.js:22:8)
100
11-14
вернуть forms[2]
10
1
вернуть forms[0]
2-4
вернуть forms[1]
0, 5-9
вернуть forms[2]
function getPlural(count, forms) {
count %= 100;
if (count > 10 && count < 15)
return forms[2];
const residue = count % 10;
if (residue === 1)
return forms[0];
if (residue > 0 && residue < 5)
return forms[1];
return forms[2];
}
// отстаток % 100
// Для 11-14
// вернуть forms[2]
// отстаток % 10
// Для 1
// вернуть forms[0]
// Для 2-4
// вернуть forms[1]
// Иначе forms[2]
(автоматизированный тест) – это скрипт, имитирующий взаимодействия пользователя с приложением, цель которого – локализация ошибок в работе программного обеспечения.
Я - ответственный разработчик. Думаю перед тем как писать код.
npm install mocha --save-dev
// package.json
{
"devDependencies": {
"mocha": "7.1.1"
}
}
├── node_modules
├── package.json
├─┬ lib
│ └── plural.js
└─┬ tests
└── plural-test.js
// tests/plural-test.js
describe('getPlural', () => {
it('should return `секунда` for `1`');
it('should return `секунды` for `2`');
it('should return `секунд` for `5`');
it('should return `секунд` for `11`');
it('should return `секунды` for `22`');
it('should return `секунд` for `113`');
});
(Behavior-driven development) разработка через поведение.
// tests/plural-test.js
describe('getPlural', () => {
it('should return `секунда` for `1`');
it('should return `секунды` for `2`');
it('should return `секунд` for `5`');
it('should return `секунд` for `11`');
it('should return `секунды` for `22`');
it('should return `секунд` for `113`');
});
node_modules/.bin/mocha tests
getPlural
- should return `секунда` for `1`
- should return `секунды` for `2`
- should return `секунд` for `5`
- should return `секунд` for `11`
- should return `секунды` for `22`
- should return `секунд` for `113`
0 passing (6ms)
6 pending
const assert = require('assert');
describe('Calculator', () => {
it('should sum digits', () => {
assert.equal(1 + 1, 2);
});
});
Calculator
✓ should sum digits
1 passing (6ms)
const assert = require('assert');
describe('Calculator', () => {
it('should multiple digits', () => {
assert.equal(1 * 1, 2);
});
});
Calculator
1) should multiple digits
0 passing (9ms)
1 failing
1) Calculator
should multiple digits:
AssertionError [ERR_ASSERTION]: 1 == 2
+ expected - actual
-1
+2
at Context.it (tests/example-test.js:5:16)
// tests/plural-test.js
const getPlural = require('../lib/plural.js')
const assert = require('assert');
describe('getPlural', () => {
const forms = ['секунда', 'секунды', 'секунд'];
it('should return `секунда` for `1`', () => {
const actual = getPlural(1, forms);
assert.equal(actual, 'секунда');
});
// ...
});
node_modules/.bin/mocha tests
getPlural
✓ should return `секунда` for `1`
- should return `секунды` for `2`
- should return `секунд` for `5`
- should return `секунд` for `11`
- should return `секунды` for `22`
- should return `секунд` for `113`
1 passing (7ms)
5 pending
node_modules/.bin/mocha tests
getPlural
✓ should return `секунда` for `1`
✓ should return `секунды` for `2`
✓ should return `секунд` for `5`
✓ should return `секунд` for `11`
✓ should return `секунды` for `22`
✓ should return `секунд` for `113`
6 passing (9ms)
// tests/plural-test.js
const getPlural = require('../lib/plural.js')
const assert = require('assert');
describe('getPlural', () => {
const forms = ['секунда', 'секунды', 'секунд'];
const allCases = [
{ number: 1, form: 'секунда' },
{ number: 2, form: 'секунды'},
{ number: 5, form: 'секунд'},
{ number: 11, form: 'секунд'},
{ number: 22, form: 'секунды'},
{ number: 113, form: 'секунд'}
]
for(const testCase of allCases) {
it(`should return '${testCase.form}' for '${testCase.number}'`, () => {
const actual = getPlural(testCase.number, forms);
assert.equal(actual, testCase.form);
});
}
});
function getPlural(count, forms) {
if (isNaN(count)) {
throw new Error('Count is not a number');
}
// ...
}
it('should throw error when count is not a number', () => {
const cb = () => getPlural('NaN', forms);
assert.throws(cb, /Count is not a number/);
});
describe('getPlural', () => {
it('should return `секунда` for `1`');
it('should return `секунды` for `2`');
it('should return `секунд` for `5`');
it('should return `секунд` for `11`');
it('should return `секунды` for `22`');
it('should return `секунд` for `113`');
it('should throw error when ...');
});
describe('getPlural', () => {
describe('positive', () => {
it('should return `секунда` for `1`');
it('should return `секунды` for `2`');
describe('third form', () => {
it('should return `секунд` for `5`');
it('should return `секунд` for `11`');
it('should return `секунд` for `113`');
});
});
describe('negative', () => {
it('should throw error when ...');
});
});
getPlural
positive
- should return `секунда` for `1`
- should return `секунды` for `2`
third form
- should return `секунд` for `5`
- should return `секунд` for `11`
- should return `секунд` for `113`
negative
- should throw error when ...
0 passing (6ms)
6 pending
describe('hooks', () => {
beforeEach(() => {
// Код этой функции выполнится
// перед каждым тестом
});
// ...
});
beforeEach
afterEach
before
after
describe('Module name', () => {
before(() => console.log(1));
beforeEach(() => console.log(2));
describe('method name', () => {
before(() => console.log(3));
beforeEach(() => console.log(4));
it('should do ...', () => console.log(5));
it('should do other', () => console.log(6));
});
});
Module name
1
method name
3
2
4
5
✓ should do ...
2
4
6
✓ should do other
describe('Module name', () => {
it.only('should do ...', () => {
console.log('first');
});
it('should do other', () => {
console.log('second');
});
});
Module name
first
✓ should do ...
1 passing (7ms)
describe.only('Module name', () => {
it('should do ...', () => {
console.log('first');
});
it('should do other', () => {
console.log('second');
});
});
Module name
first
✓ should do ...
✓ should do other
2 passing (7ms)
describe('Module name', () => {
it('should do ...', () => {
console.log('first');
});
it.skip('should do other', () => {
console.log('second');
});
});
Module name
first
✓ should do ...
- should do other
1 passing (7ms)
1 pending
// package.json
{
"scripts": {
"test": "mocha tests"
}
}
npm run test
npm test
npm t
стратегия тестирования программы с точки зрения внешнего мира, при котором не используется знание о внутреннем устройстве тестируемого объекта.
метод тестирования программного обеспечения, который предполагает, что внутренняя структура системы известна тестировщику.
(Test Last Development) тесты после написания кода
Естественный процесс
Нет накладных расходов
Понятно как писать тесты
Ложно-положительные тесты
Нет гарантии 100% покрытия требований
(Test Driven Development) тесты до написания кода
100% покрытие требований тестами
Продумать поведение до реализации
Нет ложно-положительных тестов
Обнаружение 🐞 на ранней стадии
Непривычно, сложно начать