tl;dr

Используйте capture-stdout, чтобы легко протестировать протоколирование ошибок (или любого другого ожидаемого вывода на стандартный вывод) в приложениях узла.

Условия отказа

Как вы пишете свой код для обработки сбоев?

Когда у меня появился некоторый опыт (и синяки) поддержки кода в продакшене, я начал осознавать важность обработки исключений и ошибок отдельно от увещеваний моих руководителей. Было много написано о написании защитного кода, который обрабатывает «вещи, которые идут не так». Часто эти ошибки обрабатываются (каламбур) посредством ведения журнала и мониторинга журнала. Например, при попытке загрузить записи из базы данных мы обычно перехватываем любые ошибки, регистрируем их, а затем представляем пользователю нечто более удобное, чем стек вызовов. Регистрация этой ошибки только что стала требованием. Хотя мы можем не захотеть вести журнал, когда столкнемся с конфликтом ключей при создании записи, я хочу знать, когда, где и как вызовы базы данных терпят неудачу, и я, вероятно, хочу знать это раньше, чем позже.

При регистрации исключений это, вероятно, требование.

Часто регистрация этих сбоев делала их обязательным требованием. Если у меня есть уведомление, связанное с несколькими сообщениями журнала уровня «ошибка» в течение периода времени, это ОПРЕДЕЛЕННО требование. По сути, в любое время, когда вы думаете, что захотите поближе взглянуть на статус приложения из-за некоторых сообщений журнала, они, скорее всего, являются «Требованиями к отказу».

Вы тестируете на «Требования к отказу»?

Затем тестирование ведения журнала становится немного сложнее. Да, мы можем заглушить регистратор и обрабатывать его таким образом. Но на уровне интеграции я хочу знать, что ожидаемое сообщение журнала о завершении доходит до ожидаемого места назначения, поэтому я знаю, что не пойду на работу в понедельник утром, только чтобы обнаружить, что сбой компонента, который не был зарегистрирован должным образом снизил часть моего приложения. Достаточно просто добавить кейс в модульные и/или интеграционные тесты, чтобы вызвать сбой и убедиться, что тесты возвращают ожидаемое значение. Вот одно из решений для тестирования вывода журнала в приложении node.js.

захват-stdout

Есть и другие проекты, но большинство из них имеют значительные накладные расходы или копируют только вывод. Нет ничего более уродливого, чем видеть исключения, разбросанные по результатам теста. Итак, я написал очень простой класс ES6 (эй, храните данные, отбросьте свои прототипические страхи и предубеждения и просто работайте с ним), чтобы собирать данные stdout и делать эти данные доступными. Взгляните на репозиторий github и пакет модуля в npm. Вот класс (без документации):

class CaptureStdout {
  constructor() {
    this._capturedText = [];
    this._orig_stdout_write = null;
  }
  startCapture() {
    this._orig_stdout_write = process.stdout.write;
    process.stdout.write = this._writeCapture.bind(this);
  }
  stopCapture() {
    if (this._orig_stdout_write) {
      process.stdout.write = this._orig_stdout_write;
    }
  }
  _writeCapture(string) {
    this._capturedText.push(string.replace(/\n/g, ''));
  }
  getCapturedText() {
    return this._capturedText;
  }
  clearCaptureText() {
    this._capturedText = [];
  }
}

Вот и все. Easy Peasy, никаких зависимостей, просто подключите и работайте с ним.

Установка

npm install capture-stdout

Пример использования

it('should error and log an error message if the persistence call throws an error', async () => {
    const captureStdout = new CaptureStdout();
    const msg = 'some error text here';

    // stub out the persistence call
    const findAll = sandbox.stub(orm.books, 'findAll');
    // stubbed persistence call is a promise, fail as one.
    findAll.rejects(Error(msg));

    captureStdout.startCapture();

    controller.getAll(req, res, next);
    await res;
    await next;

    captureStdout.stopCapture();
    const arrJson = captureStdout.getCapturedText().map(JSON.parse);
    captureStdout.clearCaptureText();

    expect(arrJson).has.lengthOf(1);
    expect(arrJson[0]).has.property('msg').contains(msg);
    expect(arrJson[0]).has.property('level').which.equals(50);
  });

Подведение итогов

Использование Capture-stdout уже помогло мне в некоторых моих проектах. Надеюсь, вы найдете это полезным, и, по крайней мере, это заставит вас задуматься о том, как вы проверяете свои «Требования к неудаче».

Если у вас есть какие-либо вопросы или проблемы, напишите мне. 🙂 Чао!

Первоначально опубликовано на blueottersoftware.com 25 июля 2017 г.