От переводчика: «Elixir и Phoenix — прекрасный пример того, куда движется современная веб-разработка. Уже сейчас эти инструменты предоставляют качественный доступ к технологиям реального времени для веб-приложений. Сайты с повышенной интерактивностью, многопользовательские браузерные игры, микросервисы — те направления, в которых данные технологии сослужат хорошую службу. Далее представлен перевод серии из 11 статей, подробно описывающих аспекты разработки на фреймворке Феникс казалось бы такой тривиальной вещи, как блоговый движок. Но не спешите кукситься, будет действительно интересно, особенно если статьи побудят вас обратить внимание на Эликсир либо стать его последователями.» В этой части мы научимся тестировать каналы. В конце прошлой части мы доделали классную систему «живых» комментариев для блога. Но к ужасу, на тесты не хватило времени! Займёмся ими сегодня. Этот пост будет понятным и коротким, в отличие от чересчур длинного предыдущего. Прежде, чем перейти к тестам, нам нужно подтянуть несколько мест. Во-первых, давайте включим
флаг approved в вызов broadcast. Таким образом мы сможем проверять в тестах изменение состояния подтверждения комментариев. Также нужно изменить файл web/channels/comment_helper.ex, чтобы он реагировал на пустые данные, отправляемые в сокет запросами на одобрение/удаление комментариев. После функции approve добавьте: А после функции delete: Это позволит сделать код проще, обработку ошибок – лучше, а тестирование – легче. Будем использовать фабрики, которые написали с помощью ExMachina ранее. Нам нужно протестировать создание комментария, а также одобрение/отклонение/удаление комментария на основе авторизации пользователя. Создадим файл test/channels/comment_helper_test.exs, а затем добавим подготовительный код в начало: Здесь используется модуль ModelCase для добавления возможности использования блока setup. Ниже добавляются алиасы для модулей Comment, Factory и CommentHelper, чтобы можно было проще вызывать их функции. Затем идёт настройка некоторых основных данных, которые можно будет использовать в каждом тесте. Также как и раньше, здесь создаются пользователь, пост и комментарий. Но обратите внимание на создание "фальшивого сокета", который включает в себя лишь ключ assigns. Мы можем передать его в CommentHelper, чтобы тот думал о нём как о настоящем сокете. Затем возвращается кортеж, состоящий из атома :ok и словарь-список (также как и в других тестах). Давайте уже напишем сами тесты! Начнём с простейшего теста на создание комментария. Так как комментарий может написать любой пользователь, здесь не требуется никакой специальной логики. Мы проверяем, что комментарий действительно был создан и… всё! Для этого вызываем функцию create из модуля CommentHelper и передаём в неё информацию, как будто это информация была получена из канала.  Переходим к одобрению комментариев. Так как здесь используется немного больше логики, связанной с авторизацией, тест будет чуть более сложным: Схожим с созданием комментария образом, мы вызываем функцию CommentHelper.approve и передаём в неё информацию "из канала". Мы передаём "фальшивый сокет" в функцию и она получает доступ к значению assign. Мы тестируем их оба с помощью валидного сокета (с вошедшим в систему пользователем) и невалидного сокета (с пустым assign). Затем просто проверяем, что получаем комментарий в положительном исходе и сообщение об ошибке в отрицательном.  Теперь о тестах на удаление (которые по сути идентичны): Как я упоминал ранее, наши тесты практически идентичны, за исключением положительного исхода, в котором мы убеждаемся что комментарий был удалён и больше не представлен в базе данных. Давайте проверим, что мы покрываем код тестами должным образом. Для этого запустите следующую команду: Она создаст в директории [project root]/cover отчёт, который скажет нам какой код не покрыт тестами. Если все тесты зелёные, откройте файл в браузере ./cover/Elixir.Pxblog.CommentHelper.html. Если вы видите красный цвет, значит этот код не покрыт тестами. Отсутствие красного цвета означает 100% покрытие. Полностью файл с тестами хелпера комментариев выглядит следующим образом: Генератор уже создал для нас основу тестов каналов, осталось наполнить их мясом. Начнём с добавления алиаса Pxblog.Factory для использования фабрик в блоке setup. Собственно, всё как и раньше. Затем необходимо настроить сокет, а именно, представиться созданным пользователем и подключиться к каналу комментариев созданного поста. Оставим тесты ping и broadcast на месте, но удалим тесты, связанные с shout, поскольку у нас больше нет этого обработчика. В файле test/channels/comment_channel_test.exs: У нас уже написаны довольно полноценные тесты для модуля CommentHelper, так что здесь оставим тесты, непосредственно связанные с функциональностью каналов. Создадим тест для трёх сообщений: CREATED_COMMENT, APPROVED_COMMENT и DELETED_COMMENT. Если вы никогда раньше не видели тесты каналов, то здесь всё покажется в новинку. Давайте разбираться по шагам. Начинаем с передачи в тест сокета и поста, созданных в блоке setup. Следующей строкой мы отправляем в сокет событие CREATED_COMMENT вместе с ассоциативным массивом, схожим с тем, что клиент на самом деле отправляет в сокет. Далее описываем наши "ожидания". Пока что вы не можете определить список, ссылающийся на любые другие переменные внутри функции assert_broadcast, так что следует выработать привычку по определению ожидаемых значений отдельно и передачу переменной expected в вызов assert_broadcast. Здесь мы ожидаем, что значения body и author совпадут с тем, что мы передали внутрь. Наконец, проверяем, что сообщение CREATED_COMMENT было транслировано вместе с ожидаемым ассоциативным массивом.  Теперь переходим к событию APPROVED_COMMENT: Этот тест в значительной степени похож на предыдущий, за исключением того, что мы передаём в сокет значение approved равное false и ожидаем увидеть после выполнения значение approved равное true. Обратите внимание, что в переменной expected мы используем commentId и postId как указатели на comment.id и post.id. Это выражения вызовут ошибку, поэтому нужно использовать разделение ожидаемой переменной в функции assert_broadcast.  Наконец, взглянем на тест для сообщения DELETED_COMMENT: Ничего особо интересного. Передаём стандартные данные в сокет и проверяем, что транслируем событие об удалении комментария. Подобно тому, как мы поступали с CommentHelper, запустим тесты конкретно для этого файла с опцией --cover: Вы получите предупреждения, что переменная expected не используется, которые можно благополучно проигнорировать. Если вы открыли файл ./cover/Elixir.Pxblog.CommentChannel.html и не видите ничего красного, то можете кричать "Ура!". Полное покрытие! Финальная версия теста CommentChannel полностью должна выглядеть так: Так как отчёт о покрытии тестами можно легко создать с помощью Mix, то не имеет смысла включать его в историю Git, так что откройте файл .gitignore и добавьте в него следующую строчку: Вот и всё! Теперь у нас есть полностью покрытый тестами код каналов (за исключением Javascript-тестов, которые представляют собой отдельный мир, не вписывающийся в эту серию уроков). В следующей части мы перейдём к работе над UI, сделаем его немного симпатичнее и более функциональнее, а также заменим стандартные стили, логотипы и т.п., чтобы проект выглядел более профессионально. В дополнение, удобство использования нашего сайта сейчас абсолютно никакое. Мы поправим и это, чтобы людям хотелось использовать нашу блоговую платформу!