Тестирование сайта для всех
Мы зацикливаемся на мельчайших деталях веб-сайта на этапах планирования и разработки. Мы проверяем браузером каждую страницу, вплоть до использования виртуальной машины для тестирования IE5 на Win95 на всякий случай, кто-то использует его. Мы анализируем качество каждого изображения на сайте, чтобы убедиться, что они четкие и понятные пользователю. Но как только сайт запущен и находится в руках клиента, мы склонны отодвигать его на задний план и сосредотачиваться на новых блестящих проектах.
Это печально, потому что после запуска сайта должна начаться настоящая работа. Разработчики и агентства традиционно боролись с обслуживанием после запуска и обеспечением того, чтобы веб-сайт оставался таким же красивым и оптимизированным, как в первый день его запуска. Когда веб-сайт используется реальными посетителями, клиент делает обновления контента и генерируются данные о трафике, мы должны сосредоточиться на качестве.
Самая близкая аналогия, которую я могу придумать, это кто-то, кто покупает новый дом. Дом выглядит идеально, на участке нет ни пылинки, ни паутины. На плинтусах нет потертостей, а окна такие чистые, что в них влетают птицы. Что происходит с домом, когда в него въезжает семья? Если вы никогда не моете окно, не подметаете пол и не пылесосите спальню, все начинает выглядеть не так идеально, как в первый день, а некоторые вещи, вероятно, со временем ломаются.
Агентство Жизнь
Времени мало, особенно для агентств, у которых всегда есть другой клиент, ожидающий выполнения работы. Очень часто нет времени вернуться на запущенный веб-сайт и провести полную проверку качества, как перед запуском. Существует множество сервисов и компаний, которые будут отслеживать и предупреждать вас о проблемах, но они неэффективны с точки зрения затрат, если у вас нет только 1 веб-сайта с несколькими страницами.
К счастью, с развитием языков разработки в целом и NodeJS в частности за последние несколько лет даже начинающий разработчик может легко написать простые скрипты для проверки большинства вещей на веб-сайте.
NodeJS — отличный язык для написания быстрых сценариев, использующих существующие библиотеки. То, что может показаться большой проблемой (например, выяснить, есть ли битые изображения на веб-сайте), можно разбить на более мелкие проблемы, используя существующее программное обеспечение.
Настройка NodeJS
Если на вашем локальном компьютере не установлен Node, перейдите в их раздел загрузок и установите его. Пример ниже будет работать с любой версией Node 6+. Для этого руководства вам потребуется некоторое базовое понимание NodeJS, или вы можете посетить учебник для начинающих по NodeJS.
Готовый код
Посмотреть и скачать окончательный код можно на GitHub.
Установка пакета
Если вы проверяете что-то на каждой странице вашего сайта, то вы будете использовать какую-то версию сканера сайта. Webcrawler и Easy Crawler — два хороших варианта с открытым исходным кодом. Мы будем использовать SiteBot для сканирования и Got для проверки изображений.
Начните с установки SiteBot и Got
npm install sitebot got --save
Импортируем библиотеки в наш скрипт
const Crawler = require("sitebot"); const got = require("got"); const fs = require("fs");
Настройте сканер с URL-адресом, который мы хотим сканировать. Если вы хотите протестировать какой-либо код сканирования, обязательно ознакомьтесь с Страницами с примерами в Интернете. Мы будем использовать их пример с неработающими изображениями, чтобы протестировать наш скрипт.
const crawler = new Crawler({ url: "http://the-internet.herokuapp.com/broken_images" });
Определите нашу основную переменную для отслеживания страниц/изображений
const Images = {};
SiteBot — это поисковый робот, управляемый событиями. Есть два события, которые мы будем отслеживать, первое — foundResource.
. Оно срабатывает всякий раз, когда сканирование страницы завершено и все ресурсы (изображения, CSS, JS) проанализированы. Мы будем хранить список всех изображений и страниц, на которых они были найдены.
crawler.on("foundResources", function(queueItem, resources) { console.log("Finished", queueItem.href); Images[queueItem.href] = resources.images; });
Второе событие, которое мы рассмотрим, — это end
, которое происходит после сканирования всего сайта.
На этом этапе наша переменная Images
будет содержать список всех страниц сайта и всех изображений на каждой странице. Мы будем использовать эту информацию для проверки статуса каждого изображения.
crawler.on("end", async function() { const imageCodes = {}; const uniqueImages = []; for (let url in Images) { for (let image of Images[url]) { if (!uniqueImages.includes(image)) { uniqueImages.push(image); try { let head = await got.head(image); if (!imageCodes[head.statusCode]) imageCodes[head.statusCode] = []; imageCodes[head.statusCode].push({ url, image }); } catch (e) { const status = e.code || e.statusCode || e.response.statusCode; if (!imageCodes[status]) imageCodes[status] = []; imageCodes[status].push({ url, image }); } } } } fs.writeFileSync("./errors.json", JSON.stringify(imageCodes)); });
После того, как мы настроили наши события, мы можем запустить сканер.
crawler.start();
Более глубокое погружение
Давайте разберем событие end
немного дальше.
Начнем с установки двух временных переменных. Часто одно и то же изображение (например, логотип) появляется на каждой странице. Вместо того, чтобы тратить время на проверку каждый раз, мы будем хранить общее количество уникальных изображений и проверять только то, является ли оно новым.
const imageCodes = {}; //hold status codes of images const uniqueImages = []; //hold unique images
Теперь пришло время перебрать нашу основную переменную Images
, которую мы устанавливали в событии foundResources
. Внешний цикл for проходит через каждую страницу сайта, внутренний цикл for — каждое изображение, найденное на этой странице.
for (let url in Images) { for (let image of Images[url]) { } }
Проверим уникальность изображения, если оно новое, то добавим его в наш массив uniqueImages
.
if (!uniqueImages.includes(image)) { uniqueImages.push(image); }
Теперь мы собираемся использовать библиотеку Got
. Это извлекает страницу (и ее коды состояния). Мы используем метод head
, так как он быстрее проверяет код состояния (он не загружает тело страницы).
let head = await got.head(image); if (!imageCodes[head.statusCode]) imageCodes[head.statusCode] = []; imageCodes[head.statusCode].push({ url, image });
Приведенный выше код извлекает код состояния изображения с сервера. Если этот код состояния еще не был замечен, мы добавляем его в imageCodes. Затем мы помещаем последнее изображение в массив.
Если при выборке произошла ошибка (что может произойти, если домен написан неправильно или возникла какая-либо другая проблема на уровне сети), мы фиксируем ее в блоке кода try/catch.
const status = e.code || e.statusCode || e.response.statusCode; if (!imageCodes[status]) imageCodes[status] = []; imageCodes[status].push({ url, image });
Вывод
Конечным результатом является файл JSON, в котором перечислены два поврежденных изображения (404) и страница, на которой они были найдены, а также два изображения, которые были найдены и работают правильно (200).
{ "200": [ { "url": "http://the-internet.herokuapp.com/broken_images", "image": "http://the-internet.herokuapp.com/img/forkme_right_green_007200.png" }, { "url": "http://the-internet.herokuapp.com/broken_images", "image": "http://the-internet.herokuapp.com/img/avatar-blank.jpg" } ], "404": [ { "url": "http://the-internet.herokuapp.com/broken_images", "image": "http://the-internet.herokuapp.com/asdf.jpg" }, { "url": "http://the-internet.herokuapp.com/broken_images", "image": "http://the-internet.herokuapp.com/hjkl.jpg" } ] }
Небольшое замечание: в зависимости от размера веб-сайта и количества изображений на странице этот файл может стать довольно большим.
Резюме
Непрерывное тестирование имеет решающее значение для долгосрочного обслуживания веб-сайта. Запуск собственных тестов не должен быть сложным или дорогим. Используйте NodeJS и готовый сканер веб-сайтов, чтобы начать процесс создания набора тестов.
Если у вас есть вопросы по коду, не стесняйтесь комментировать ниже. Вы также можете подписаться на меня в LinkedIn, Twitter или GitHub.