Skip to main content

Структурируйте тесты по шаблону AAA



Объяснение в один абзац

Нашей самой большой проблемой тестирования является отсутствие свободного пространства - у нас уже есть производственный код, который заставляет нас быть очень занятыми. По этой причине тестовый код должен оставаться очень простым и легким для понимания. При чтении контрольного примера - это не должно восприниматься как чтение императивного кода (циклы, наследование), а скорее как HTML - декларативный опыт. Чтобы добиться этого, придерживайтесь соглашения AAA, чтобы читатели могли легко проанализировать тест. В этом шаблоне есть и другие похожие форматы, такие как XUnit "Setup, Excercise, Verify, Teardown". Это три А:

Первая A - Arrange: Весь код установки, чтобы привести систему к сценарию, который тест должен симулировать. Это может включать создание экземпляра тестируемого модуля, добавление записей БД, обертки/зацепки над объектами и любой другой подготовительный код.

Вторая A - Act: Выполнить тестируемый модуль. Обычно 1 строка кода

Третья A - Assert: убедитесь, что полученное значение соответствует ожидаемому. Обычно 1 строка кода



Пример кода: тест, структурированный по шаблону AAA

describe.skip('Customer classifier', () => {
test('When customer spent more than 500$, should be classified as premium', () => {
//Arrange
const customerToClassify = {spent:505, joined: new Date(), id:1}
const DBStub = sinon.stub(dataAccess, 'getCustomer')
.reply({id:1, classification: 'regular'});

//Act
const receivedClassification = customerClassifier.classifyCustomer(customerToClassify);

//Assert
expect(receivedClassification).toMatch('premium');
});
});



Пример кода - Антипаттерн: нет разделения, сплошной объем, труднее интерпретировать

test('Should be classified as premium', () => {
const customerToClassify = {spent:505, joined: new Date(), id:1}
const DBStub = sinon.stub(dataAccess, 'getCustomer')
.reply({id:1, classification: 'regular'});
const receivedClassification = customerClassifier.classifyCustomer(customerToClassify);
expect(receivedClassification).toMatch('premium');
});



"Включите 6 частей в каждом тесте"

From the blog "30 Node.js testing best practices" by Yoni Goldberg

A test report example



"Для читателя теста важно иметь возможность быстро определить, какое поведение проверяет тест"

Из книги XUnit Patterns:

Для читателя теста важно иметь возможность быстро определить, какое поведение проверяет тест. Это может быть очень запутанным, когда вызываются различные варианты поведения тестируемой системы (SUT), некоторые для настройки предтестового состояния (фиксатора) SUT, другие для проверки SUT и третьи для проверки пост-теста состояние СУТ. Четкое определение четырех фаз значительно облегчает понимание цели теста.