Наступает 2019 год, и 2019 год станет годом бессерверных. Популярность Serverless стремительно растет. Однако из-за нехватки ресурсов сложно правильно настроить и протестировать функции. Конечно, есть много статей о том, как начать, но не много для тестирования. Я считаю, что многие из вас уже знают, сколько преимуществ дает TDD. Так что я не буду повторять это здесь. В этой статье я расскажу вам, как настроить облачные функции Firebase и написать для них модульный тест.

Перед тем, как мы начнем

Я предполагаю, что у вас уже есть хотя бы одна функция. В противном случае следуйте этому официальному руководству, чтобы создать новый проект (https://firebase.google.com/docs/functions/get-started).

Начиная

Позвольте мне вкратце объяснить функцию, которую мы собираемся создать.

Я создам триггер для метода user.onCreate. (Вы можете проверить, что это такое, на странице https://firebase.google.com/docs/functions/auth-events). Эта функция триггера сохранит только что аутентифицированного пользователя в нашей базе данных в реальном времени с несколькими необходимыми свойствами для моего простого игрового приложения. . Сначала посмотрите на приведенный ниже код.

Хорошо, ознакомьтесь с подробностями. Во-первых, метод onCreate принимает один параметр - user. Пользователь - это объект, возвращаемый после аутентификации по электронной почте / паролю, анонимной аутентификации, сторонним поставщикам аутентификации и т. Д. Мы можем использовать этот параметр для добавления новых свойств, как указано выше. Когда я делаю игровое приложение, я добавлял такие свойства, как очки и квесты. Затем я вызвал метод admin.database (). Ref (path) .set, чтобы сохранить нашего вновь созданного пользователя в базе данных. (Точно такой же процесс, как и при использовании базы данных с Firebase SDK)

Достаточно просто, правда?

Однако если вы попытаетесь протестировать эти триггерные функции, это станет огромной болью. Потому что сложно настроить клиентские приложения и вручную выполнить итерацию процесса аутентификации. (Нажмите кнопку аутентификации - введите адрес электронной почты / пароль - дождитесь завершения аутентификации - перейдите в консоль и проверьте, сохранен ли наш пользователь или нет)

Написать тест

Вот в чем преимущество автоматизированного тестирования. Вы можете повторять тестирование много раз без этих хлопот. Все, что вам нужно сделать, это просто ввести тестовые команды (тест пряжи) и повторить процесс красный / зеленый. Итак, давайте напишем тест для облачных функций Firebase. Для этого есть несколько примеров кода (https://github.com/firebase/functions-samples/blob/master/quickstarts/uppercase/functions/test/test.offline.js), но в этом примере кода используется Мокко и Чай. Как любитель Jest ( https://jestjs.io/), я хотел использовать Jest для своих тестов.

Хорошо, давайте добавим шутку в ваш проект. Я предпочитаю использовать Typescript для своих проектов, поэтому эта настройка может немного отличаться, если вы используете простой javascript, но большой разницы не будет.

  1. Добавьте jest.config.js в каталог функций.

2. Создайте каталог __tests__ в src и добавьте базовый тестовый файл.

it("should pass", () => {
// meaningless test
  expect(1).toBe(1);
});

3. Загрузите Сервисный ключ из консоли firebase.

Зайдите в настройки и щелкните вкладку учетной записи службы. Вы найдете кнопку создать новый ключ учетной записи ниже. Загрузите этот ключ и включите в свой проект. (Не забудьте включить этот файл в свой файл .gitignore - храните свои секреты в безопасности!)

4. Добавьте тестовую команду в файл package.json.

"scripts": {
...other commands
// I prefer to set verbose=false, because it shows console.logs in terminal window. You can remove this flag.
"test": "jest --watchAll --verbose=false"
},

5. Установите зависимости.

yarn add jest @types/jest firebase-functions-test ts-jest -D

Теперь все готово.

Напишите наш тестовый код для проверки нашей функции триггера.

Поскольку мы собираемся использовать базу данных в реальном времени (сохранить пользователя), нам нужно выйти в Интернет. Нам потребуется указать projectConfig и service-key.json. Если вы следовали моим инструкциям выше, тогда у вас должен быть файл service-key.json в каталоге вашего проекта. Тогда как вы можете проверить projectId и databaseURL?

Для databaseURL перейдите на вкладку базы данных и создайте новую базу данных в реальном времени, тогда вы должны увидеть свой databaseURL в таком виде.

А для projectId перейдите в настройки / common.

Хорошо, давайте напишем еще код.

Ооооо, здесь много чего происходит!

Я объясню код шаг за шагом. Первое, что вы увидите, это блок beforeAll. Я использовал метод jest.spyOn, чтобы заглушить наш метод admin.initializeApp. Затем я загрузил наши функции. (Чтобы предоставить нашему администратору надлежащие учетные данные, вам нужно запретить метод администратора). И в блоке afterAll , мы очищаем настройки.

Чтобы выполнить нашу функцию в правильной среде, мы используем метод wrap testEnv. Сделав это, мы можем вызвать событие создания пользователя в нашем тесте, просто вызвав wrapped (testUser). После вызова мы считываем нашего пользователя из базы данных и проверяем, есть ли у этого пользователя свойство с именем points и его значение равно 0 или нет.

И это все! С этого момента вы можете добавлять другие тесты. Теперь мы закончили тестирование триггеров, не связанных с HTTP. Нам все еще нужно тестировать функции http, однако тестирование функции http не сильно отличается от тестирования триггеров. Все, что вам нужно изменить, это то, что вместо передачи настраиваемого параметра в обернутую функцию вы вместо этого передаете объект req и res.

// code from https://github.com/firebase/functions-samples/blob/master/quickstarts/uppercase/functions/test/test.offline.js
const req = { query: {text: 'input'} };      
const res = {        
  redirect: (code, url) => {          
     assert.equal(code, 303);          
     assert.equal(url, 'new_ref');          
     done();        
  }      
};
myFunctions.addMessage(req, res);

Тест записи (в автономном режиме)

Есть еще один вариант, который вы можете выбрать при тестировании своих облачных функций. Это «автономный» режим. Этот быстрее (потому что вам не нужно иметь дело с транзакциями базы данных) и его легко написать.

При тестировании в автономном режиме мы должны отключить наш административный SDK, чтобы он не требовал учетных данных. Давайте погрузимся в код!

Как видите, я использовал метод jest.mock. Сначала я объявил наш макет «firebase-admin» (вы должны указать имя модуля в качестве параметра, а не сам объект модуля), а затем дал ему частичную реализацию. (initializeApp и метод базы данных) После этой фиктивной настройки все, что нам нужно проверить, это возвращаемое значение нашей триггерной функции, которое истинно, и параметр, который наш mockSet функция принимает, который будет нашим объектом newUser.

Итак, наш тестовый код должен выглядеть так.

Кажется, что эти издевательские испытания бесполезны. Я просто повторил свою реализацию функции еще раз. Однако это становится очень ценным, когда наша функция становится больше или включает в себя сложную логику if-else. Вы можете легко протестировать каждый случай с помощью этих тестовых тестов. (Это становится особенно ценным, когда вам приходится иметь дело с крайними случаями, которые нелегко проверить вручную)

Тестирование дает большую свободу. Вы можете быстро повторить столько раз, сколько сможете, с помощью автоматизированных тестов. Напишите свой собственный тест и уверенно разверните свои функции! Спасибо, что прочитали мою статью.