В прошлой статье мы познакомились с тестами для Django и создали личного пользователя-тестировщика. Самое время продолжить изучать тестирование сайта, написав проверку русских символов на английских страницах и разобрав тесты для JavaScript. UPD: Часть 3. Отправка результата на почту, TestExplorer и декоратор tag Когда страница, предназначенная для иностранного пользователя, содержит русский текст (или наоборот), это, мягко говоря, не очень приятно. Поэтому лучше такие ситуации протестировать и вовремя избавиться от них. Наши тесты перевода делятся на два типа: Проверка отсутствия русских символов на английских страницах; Проверка отсутствия ошибок в django.po файлах. Перейдём к первому тесту. Его полный код выглядит так: Разберём его детально. Для получения контента со страницы нам нужно отправить на неё GET-запрос. С этим успешно справляется метод get. Чтобы получать контент конкретного блока страницы, нам понадобится Beautiful Soup. Для type hinting импортируем Tag. И также не забудем про TestCase, который позволяет создавать тесты. У каждого символа есть его числовой код. В Python этот код можно получить с помощью функции ord. Коды русских символов имеют диапазон от 1040 (А) до 1103 (я). Также к ним относятся 1025 (Ё) и 1105 (ё). Именно эти коды мы заносим в переменную CODES_OF_RUSSIAN_SYMBOLS. С её помощью будет осуществляться поиск русских символов. В ENGLISH_PAGES мы заносим страницы, которые будем проверять: Проверку на русский символ выполняет функция is_russian_symbol. Она получает код и проверяет его наличие в переменной CODES_OF_RUSSIAN_SYMBOLS. Контент страницы содержит помимо текста ещё и ненужные нам элементы. Например, теги. Чтобы убрать их, у BeautifulSoup есть крутой метод get_text. Он извлекает только текст из HTML-разметки (1). Мы могли бы использовать лишь этот метод, но текст, который он выдаёт, содержит большое число подряд идущих пробелов. Поэтому их мы заменяем на одиночные с помощью split и join (2). Получив строку, мы разбиваем её на список слов (3), чтобы в дальнейшем итерироваться по нему. Тест работает так: Обходит все английские страницы; Из каждой страницы извлекает весь контент (похожий пример был в прошлой статье); На нашем сайте большая часть текста, который видит пользователь, хранится в div с классом b-content. Поэтому тест извлекает контент из него с помощью метода find. Остальные блоки div мы тестируем отдельно; Получает из контента все слова; Проходится по каждому слову и по каждому символу; Проверяет, что символ не является русским. Запустив сейчас тест, мы не увидим ошибок. Чтобы убедиться, что он действительно работает, проверим его для русской страницы. Возможно, увидев этот заголовок, вы задались вопросом: «Зачем тестировать файлы django.po, если мы уже напрямую проверяем отсутствие русских символов на английских страницах?». На это есть минимум 2 причины: Тест django.po помогает отловить часть ошибок и выполняется быстро. А значит, его можно проводить после каждого коммита; Если перевод фразы – пустая строка (т. е. msgstr хранит пустую строку), тест файла django.po поможет это обнаружить, в отличие от теста, написанного ранее. Всего мы будем проверять 3 условия. А именно то, что в файле django.po не должно быть: Строки с пустым значением msgstr; Строки, начинающейся с «msgid»; Строки, начинающейся с «#, fuzzy». Невыполнение хотя бы одного из этих пунктов говорит о том, что компиляция перевода выполнена с ошибками. Полный тест django.po файлов выглядит так: Рассмотрим, что в нём происходит. В них мы просто формируем русский и английский пути к django.po файлам. Например, первый будет таким: pvs/locale/ru/LC_MESSAGES/django.po. Первая функция проверяет, есть ли в строке msgstr с пустым значением. Если же перевод будет маленьким, то он останется на одной строке с msgstr. А следующая строка будет равна «\n». Перейдём к функции get_msgstr_errors. Она выдаёт номера строк, где msgstr имеет пустое значение. Принцип работы функции, следующий: Проходится по строкам файла; Заносит текущую строку в переменную line; Заносит следующую строку в переменную next_line; С помощью ранее описанной функции проверяет, содержит ли текущая строка пустой msgstr; Если да, то заносит номер строки в общий список. Идём дальше. Функция get_fuzzy_and_msgid_errors обходит строки файла и проверяет, что они не начинаются с «#, fuzzy» или с «#~ msgid». Если это не так — добавляет номер строки в список ошибок. get_locale_files_errors выдаёт словарь с языком файла django.po и его ошибками. Перейдём к самому тесту. Вот что он делает: Проходится по словарю с языком и ошибками django.po файла; Проверяет, что число ошибок равно 0. Проверим тест для следующего django.po файла: Результат будет следующим: В этой части на примере двух наших тестов я коротко расскажу о том, как тестировать JS. Для более детальной информации рекомендую прочитать эту статью от learn.javascript.ru. Начнём с создания файлов. Нам нужен scripts.js с тестируемыми функциями и tests.html, в котором будут находиться и запускаться тесты. Для JS тестов у нас используется фреймворк mocha. Он позволяет выполнять тесты как в консоли, так и в браузере. Мы остановимся на втором варианте. Для этих тестов я взял максимально простые функции. Вот они: Первая выдаёт расширение файла. Вторая проверяет, валидно ли оно. Мы не принимаем файлы с расширением «i» либо «exe», поэтому такие файлы будут считаться невалидными. Обе функции используются для валидации формы фидбека. Полный код файла tests.html выглядит так: Разберём, что тут происходит. Начнём с тега head. В нём мы выполняем следующие действия: Подгружаем тестируемые функции; Подключаем mocha и её стили. Именно они будут использоваться для отображения тестов; Настраиваем mocha, указывая, какую методику тестирования мы будем использовать. BDD Позволяет наиболее полно описать, что делает тест. Обо всех методиках можно почитать тут; Подгружаем библиотеку chai. В ней находятся функции проверки тестов (should, assert и expect). Хотя для BDD больше подходят should и expect, мы будем использовать знакомый нам из Python метод assert. Поэтому заносим его в константу. Перейдём к body и его тегу script. Первое, что мы делаем, — это создаём константы для тестов. После констант идут тесты функции getFileExtension. Вот как они создаются: Создаём блок с названием getFileExtension.Функция describe позволяет отделять тесты друг от друга, вынося их в разные блоки. Т.е. мы можем разделить тесты для getFileExtension и для isExtensionValid. Тогда в браузере они будут отображаться порознь. Первый аргумент describe — это название блока. Оно может быть любым, поскольку используется только при отображении в браузере. Второй аргумент – функция, выполняющая тесты для данного блока; В цикле проходимся по элементам filesAndExtensions и получаем файл вместе с его ожидаемым расширением; В функцию it (она создаёт один тест) передаём описание теста и сам тест в виде функции; У assert-а вызываем метод equal. Его суть работы такая же как для assertEqual в Python. В данном случае мы сравниваем два расширения: полученное с помощью getFileExtension и ожидаемое. Результат выполнения этих тестов будет таким: В данном случае все 4 теста прошли успешно. Теперь рассмотрим тесты для функции isExtensionValid. В них мы: Создаём describe с названием isExtensionValid; Разделяем наш describe ещё на два блока, поскольку у нас два разных типа тестов: для валидных и не валидных расширений. В первом функция isExtensionValid должна возвращать true, во втором – false. Поэтому будет разумно разграничить эти тесты. Благо describe позволяет создавать вложенные блоки; Проходимся по валидным расширениям и создаём для них тест, проверяющий что isExtensionValid возвращает true; Проходимся по не валидным расширениям, так же создаём для них тест, но теперь он проверяет, что isExtensionValid возвращает false. Результат выполнения этих тестов будет таким: Все тесты будут отображаться в блоке div с id mocha. А для их запуска нужно вызвать команду run. Открыв tests.html в браузере, вы получите такую картину: Помимо наших тестов справа вверху отображается панель. В ней можно увидеть: Число успешно выполненных тестов; Число упавших тестов; Время выполнения всех тестов; Сколько тестов (в процентах) уже успели прогнаться. Запустить конкретный тест можно с помощью кнопки, находящейся справа от его названия. Если нажать на название блока, например на getFileExtension, откроется результат выполнения тестов только этого блока. Также, если нажать на конкретный тест, можно увидеть команду его вызова. В случае падения тестов, вы увидите, что именно пошло не так. Итак, сегодня мы разобрали тесты для JavaScript и написали проверку русского текста на английских страницах. Если вы ещё не читали первую часть, рекомендую это сделать. В ней много интересного и полезного. В следующей статье мы рассмотрим автозапуск тестов и некоторые полезные инструменты. Для фидбека или критики пишите в комментарии либо в мой инстаграм. Спасибо за внимание и до встречи в следующей статье) Чистый кот