Что пишут в блогах

Подписаться

Конференции

Конференция по тестированию Heisenbug 2022 Autumn

Большая техническая конференция по тестированию Heisenbug 2022 Autumn
7–8 ноября в онлайне и 18 ноября в офлайне в Москве.

Что пишут в блогах (EN)

Разделы портала

Онлайн-тренинги

Как выбрать инструмент для тестирования API
17.08.2022 00:00

Оригинальная публикация

Статья компании SimbirSoft

В список требований, предъявляемых к QA-специалистам, включают умение тестировать API приложений.

Обращения к API помогают оптимизировать процесс тестирования: сократить время на проведение, расширить покрытие кейсами, минимизировать зависимость от внешних систем, например, клиентской части приложения. Кроме того, обращения к эндпойнтам позволяют проверить тестовые случаи, которые невозможно воспроизвести, используя только графический интерфейс.

Чтобы выбрать инструмент для тестирования API на своем проекте, вам нужно четко представлять свои цели, объект и результат, который хотите получить. Неправильно выбранный инструмент может привести к увеличению трудоемкости и затягиванию процесса тестирования, а также к пропуску багов. 

В этом материале мы рассмотрим наиболее распространенные виды API, выделим их характерные особенности, а также разберем популярные инструменты для тестирования API и опишем применение на практике. Изучив этот материал, вы сможете выбрать наиболее подходящий инструмент и использовать его на своем проекте.

Что такое API

API (Application Programming Interface) – это программный интерфейс приложений. Чтобы понять, как он работает, возьмем классический пример: клиент и сервер. API можно представить как рычаги, протянутые с сервера на клиент. Благодаря им клиент может воспользоваться функциями, реализованными на сервере. То есть API – это интерфейс, с помощью которого одна система может связываться с другой.

Рассмотрим характерные особенности Web-API, наиболее распространенных в настоящее время: SOAP, REST и gRPC.

SOAP API

Первоначально предназначался преимущественно для удаленного вызова процедур. Сейчас протокол используется также для обмена произвольными сообщениями в формате XML. Основная отличительная черта SOAP API в том, что вся информация передается в XML-сообщениях между клиентом и сервером

SOAP может использоваться с любым протоколом прикладного уровня: SMTP, FTP, HTTP, HTTPS и другими. Однако взаимодействие с каждым имеет свои особенности. Например, в случае реализации с помощью HTTP/HTTPS применяется только метод POST. Одним из ключевых понятий в данном типе API является файл WSDL, включающий себя описание методов тестируемого сервиса. Импортируя такой файл, вы получаете список готовых обращений к эндпойтам.

REST API 

Архитектурный стиль сетевого взаимодействия компонентов распределенного приложения. Впервые термин был использован в 2000 году одним из создателей НТТР. Сам по себе REST не является протоколом. Это набор правил того, как разработчику организовать написание кода серверного приложения, чтобы все системы эффективно обменивались данными, и приложение можно было масштабировать. 

В стиле REST можно выделить несколько характерных особенностей:

  1. Привязка к методам HTTP и, соответственно, использование только этого протокола для передачи данных. 

  2. Использование различных форматов для передачи данных, таких как JSON, XML, HTML. Наиболее часто используется JSON ввиду его легкости, простоты и человекочитаемости.

gRPC

Система удаленного вызова процедур, разработанная компанией Google в 2015 году. В качестве транспорта gRPC использует протокол HTTP v2. Чаще всего gRPC помогает организовать взаимодействие в микросервисной архитектуре. Реализация общения через gRPC происходит следующим образом: клиентское приложение может напрямую вызвать метод серверного приложения так же, как если бы это был локальный метод клиента. 

Отличительная черта реализации приложений с помощью gRPC API — наличие компонента gRPC STUB. Это модуль, который конвертирует данные из человекочитаемых в бинарные файлы и передает их между клиентом и сервером. Еще одна неотъемлемая часть gRPC API это .proto файл – описание того, какие методы есть в приложении, и взаимосвязь между запросом и ответом.

Познакомившись с примерами реализации API, становится понятно, что они представляет собой структуру вида «запрос — ответ». В запросе нужно передавать некоторые параметры, в ответ на которые приходят соответствующие данные. 

Инструменты для тестирования API

Существуют десятки различных инструментов, с помощью которых тестируют API. Все их можно разделить по уровню освоения на простые, средние и сложные. Чтобы их сравнить, сформулируем основные критерии.

  1. Принципиальная возможность обратиться к эндпойнтам приложения.

  2. Возможность отправить свои собственные параметры запроса.

  3. Способность хранить тест-кейсы.

  4. Быстрота написания тестов.

  5. Скорость освоения инструмента.

  6. Возможности автоматизации проверки ожидаемых результатов.

  7. Дополнительные возможности автоматизации тестирования.

  8. Возможности использования переменных окружения.

  9. Способность использовать мок-сервисы, заглушки и т. д.

  10. Особенности запуска готовых тестов.

  11. Интеграция с системами CI/CD.

  12. Дополнительный функционал, облегчающий тестирование.

Сваггероподобные системы

Это инструменты простого уровня — Swagger UI, Яндекс Полигон, а также прочие внутрипроектные интерактивные виды документации API.

В стандартный функционал сваггероподобных систем входят: отправка запросов, просмотр ответов, возможность посмотреть готовые примеры запросов и ответов, варианты авторизации, возможность экспорта ответа в файл и генерация cURL запроса.

Плюсы сваггероподобных систем:

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

  2. Они очень быстры и просты в освоении и использовании из-за элементарного функционала. 

  3. Содержат примеры ответов и описание приходящих в них параметров. 

  4. Не требуют установки на устройство пользователя, они уже развернуты на стенде. 

  5. Генерируют cURL, который можно приложить к баг-репорту, чтобы разработчик мог быстрее воспроизвести  баг и исправить его. 

Минусы сваггероподобных систем:

  1. Они хранят только заранее прописанные разработчиком параметры запросов, которые могут быть избыточными или наоборот, неполными. 

  2. Нельзя сохранять свои параметры запросов. То есть после обновления страницы сваггероподобной системы пропадет все, что вы туда ввели. Таким образом, параметры запросов, использующиеся в тест-кейсах, придется хранить в отдельных документах, а это неудобно.

  3. Нельзя создавать коллекции запросов, так как невозможно сохранять свои варианты запросов.

  4. Нельзя создавать скрипты-проверки, ожидаемый результат с фактическим придется сверять глазами/руками.

  5. Невозможны прогоны, то есть автоматизированный последовательный запуск запросов.

  6. Нельзя создавать и использовать никакие окружения, переменные. 

  7. Полезность описаний в сваггероподобных системах очень разнится от проекта к проекту.

Когда выбирать сваггероподобные системы? Так как это не инструмент тестирования, а интерактивная документация по API, такие системы чаще используются для ознакомления с эндпойнтами и исследовательских проверок. В остальных случаях использовать сваггероподобные системы не рекомендуется, разве что вы работаете на специфическом проекте, и другие инструменты использовать невозможно. Например, закрытый проект, где вы работаете на виртуальных машинах и удаленных рабочих столах, и при этом нет возможности установить никакой из API-клиентов. Тогда все, что вы можете — использовать Swagger или подобную систему, чтобы тестировать эндпойнты сервиса. 

API-клиенты 

Инструменты среднего уровня сложности. Это, как правило, десктопные приложения, которые позволяют обратиться к эндпойнтам. Также они предоставляют дополнительные возможности — использование переменных, рандомайзеров, скриптов и других функций. 

Insomnia

При открытии Insomnia мы видим главную страницу, на которой можно настроить само приложение и свой аккаунт, меню создания проектов, а также список уже созданных. Добавить новый проект можно различными способами: импортирование из локального файла, «подтягивание» с внешнего ресурса по URL, копирование API проекта из Git. 

При открытии проекта становится доступным функционал добавления новых и список созданных запросов. Окно запроса дает возможность вводить и сохранять отправляемые параметры. Посмотреть и сохранить в качестве примера приходящий ответ можно в окне справа.

Insomnia поддерживает широкий набор возможностей для обращений к различным API: набор методов HTTP/s, обращения к gRPC API, а также кастомные методы со своими параметрами. Вариантов форматов передаваемых сообщений тоже много: JSON, XML, YAML, EDN, бинарные файлы, GraphQL Query.

Важная особенность Insomnia — возможность создавать переменные окружения, которые будут подтягиваться или автоматически генерироваться в зависимости от настройки. Значения из переменных можно использовать в тестах, чтобы автоматизировать их и упростить себе работу. 

На странице проекта во вкладке “Test” добавляются проверки к отправляемым запросам, сравнивающие пришедший ответ с ожидаемым результатом. Запрос с добавленными проверками называется Тестом. Несколько запросов можно объединить в Тест-сьют. 

Insomnia поддерживает возможность запускать тесты списками с помощью раннера. При этом отображаются отправляемые запросы и результаты проверок

Плюсы Insomnia: 

  1. Легкий в освоении интерфейс относительно других подобных API-клиентов. 

  2. Кроссплатформенность.

  3. Возможность загрузки проектов из Swagger. Можем по URL импортировать проект, и у нас появятся все те же списки с описаниями, как это было в Swagger. 

  4. Возможность настройки окружения.

  5. Возможность создавать динамические переменные. 

  6. Возможность создавать и прогонять тест-кейсы.

  7. Возможность поддержки версионности кейсов с подключением их к Git. 

  8. Возможность тестирования разных API, таких как REST, SOAP, gRPC, GraphQL и другие. 

Минусы Insomnia: 

  1. Создание тест-кейсов из нескольких запросов затруднено. Если тест-кейс состоит из нескольких последовательных шагов/запросов, то он будет обозначаться как тест-сьют, соответственно, построить иерархию кейсов сложно из-за одного уровня вложенности (папка (тест-сьют) – запрос). 

  2. Невозможен параллельный запуск запросов и кейсов. 

  3. Настройка переменных окружения сложная относительно других API-клиентов.

  4. Небольшой выбор встроенных скриптов-рандомайзеров по сравнению с другими инструментами.

  5. Нет встроенного списка проверок к ответам.

Используйте Insomnia, когда нужно тестировать разные виды API, использовать окружения, переменные, скрипты, и при этом функции Postman для вас избыточны. Или если вам нужен удобный API-клиент для тестирования gRPC.

Postman 

Очень популярный API-клиент. Хоть его интерфейс и пугает насыщенностью, разобраться в нем достаточно просто. На домашней странице предлагается выбрать рабочее пространство. Это своеобразная «папка», в которую добавляются коллекции запросов, окружения, переменные, мок-заглушки и другое. Такое разделение очень удобно, если у вас есть несколько тестируемых проектов или сервисов.

В каждом рабочем пространстве есть: 

  • список коллекций, расположенный в окне “Collections”; 

  • документация API, сюда можно импортировать Swagger; 

  • окно, в котором редактируются окружение и переменные; 

  • функционал создания мок-заглушек.

  • «монитор» — функция, позволяющая по таймеру запускать коллекции запросов. Причем это можно делать облачно, без необходимости держать свой компьютер включенным.

Окно запроса состоит из поля для указания HTTP-метода и URL запроса, настройки параметров (заголовки и тело), Pre-request Script — скриптов, которые будут исполняться до отправки сообщения, Tests — кода, который будет исполняться после выполнения запроса.

Оранжевым цветом выделяются переменные в Postman. Они бывают автоматически генерируемые (имя начинается с $, например, $randomInt — генерирует рандомное число) и созданные пользователем (куда можно записать все что угодно).

В данном случае создается переменная ‘CreateTime’ в которую записывается время, генерируемое с помощью JS в Pre-request Script.

Во вкладке Test мы видим код, который сверяет ожидаемый и фактический результат. Проверки в Postman начинаются с конструкции ‘pm.test”. Первым тестом мы проверяем статус-код. Если он равен 200, то во вкладке Test results в ответе появится сообщение “Status code is 200”. Второй тест — проверка id животного. Видим, что в ответе пришел именно тот id животного, которое мы создавали, то есть сверяем со значением из переменной окружения.

Также во вкладку Test можно добавить код, выполняющий любые действия — например, достающий из ответа значение, которое хранится в произвольном поле, и передающий его в переменную окружения.

Плюсы Postman: 

  1. Относительно простой интерфейс. 

  2. Возможность подключения в Swagger.

  3. Возможность создавать рабочие пространства и коллекции. 

  4. Поддержка мок-серверов и прогонов коллекций (ручные и периодические).

  5. Отдельный компонент-перехватчик запросов. 

  6. Окружения, переменные и возможность их настраивать, создавать, редактировать.

  7. Возможность тестирования разных видов API, таких как REST, SOAP и т.д. 

  8. Поддержка интеграции с Git.

  9. Очень много встроенных скриптов-рандомайзеров. 

  10. Возможность написания кастомных скриптов проверок с помощью языка JavaScript.

  11. Очень много встроенных вариантов проверок в сниппетах.

  12. Возможность написания кастомных проверок с помощью JS. 

  13. Возможность запускать коллекции из командной строки с помощью инструмента-компаньона Newman.

  14. Возможность интеграции Newman с системами непрерывной сборки. Например, мы можем создать коллекцию в Postman, она передается Newman, интегрируется с системами непрерывной сборки, и Newman запускает эту коллекцию при обновлении версии стенда, приложения или в других подобных ситуациях.

Минусы Postman: 

  1. Коллекции и окружения к ним экспортируются отдельно.

  2. Невозможен параллельный запуск кейсов в Postman. Например, вы тестируете асинхронный сервис и есть некий этап ожидания между созданием задания и получением на него результата. В этом случае лучше, чтобы ваш инструмент тестирования позволял запускать проверки параллельно и ждать результата в каждом случае по отдельности. Иначе вы будете ждать их очень долго, особенно когда много тест-кейсов. Прогон такой коллекции будет растянутым.

  3. Раннер, который последовательно запускает запросы, видит именно список запросов, а не кейсы. Это несет в себе риски, когда кейс состоит из нескольких запросов. Например, папка представляет собой тест-кейс. У вас десять папок, в которых десять тест-кейсов, и в каждом по два-три шага. Когда запускаете раннер, вам видны 30 последовательных запросов. Поэтому в некоторых запросах в разных тест-кейсах вам нужно писать скрипты, которые в случае провала автоматически очистят некоторые переменные от своих значений. Тогда следующий кейс пройдет без ошибок и там не останется значений, которые не воспринимаются следующим кейсом. Это влияет на независимость тест-кейсов друг от друга.

Postman следует использовать, когда вам нужен удобный и мощный API-клиент для тестирования разных видов API с возможностью использовать продвинутые переменные и скрипты в запросах. При этом не важен параллельный запуск кейсов в вашем проекте и вы понимаете особенности построения кейсов из нескольких запросов.

SOAPUI 

Первоначально был создан для тестирования SOAP сервисов, но впоследствии стал применяться и для REST API. Инструмент позволяет создавать и импортировать проекты, в нем есть меню работы с тест-кейсами, список всех проектов и меню действий над текущим.

При открытии проекта становится доступным список всех запросов, существующих в вашем сервисе, и список тест-кейсов. Это одна из отличительных черт SOAPUI — запросы в библиотеке и тесты существуют отдельно. То есть мы описали 15 запросов, а потом можем в любых комбинациях использовать их в тестах, ставить в разном порядке в зависимости от потребности.

Тест-сьюты состоят из тест-кейсов, а тест-кейсы — из шагов. Шаги могут быть как запросами, так и служебными действиями. 

Запросы настраиваются в отдельном окне, где можно добавить и сохранить передаваемые данные, отправить запрос, посмотреть ответ на него, а также прикрепить проверки ожидаемого результата (в данном случае проверки Contains).

К служебным действиям относятся, например, таблицы с тестовыми данными (testdata), которые будут с помощью переменных подтягиваться в запросы. Таблицы имеют простую структуру “name-value”, причем value может быть не только статическим, но и генерироваться скриптом. 

Еще одним видом служебных действий являются шаги трансфера (Transfer mail), выполняющие передачу данных между запросами, либо между запросом и таблицей с данными. Структура передачи также простая “source-target ”. Единственная особенность тут: грамотно указать с помощью языка парсинга поля обмена данными.

Интуитивно понятный функционал запуска тест-кейсов состоит из: кнопки «старт/стоп» и переключателя последовательного  или  параллельного запуска проверок.  При нажатии на кнопку “Start” показывается список запущенных кейсов, а также результат их прохождения. Открыв проваленный кейс можно увидеть на каком шаге он «упал» и почему (в данном примере — потому что нет значения, который передается в “mail”). При этом следующий шаг не запускался, и это одна из особенностей SOAPUI. Он видит именно тест-кейсы, а не список шагов. Если какой-то шаг в тест-кейсе провалился, то остальные шаги он не запускает и переходит далее. Следующие кейсы работают только с переменными, скриптами и тестовыми данными внутри них самих, не видя переменные из других кейсов.

Настройка последовательного или параллельного запуска кейсов «из коробки» — это также отличительная особенность SOAPUI. Во многих случаях это сильно экономит ваше время. 

Плюсы SOAPUI: 

  1. Возможность создания проектов с помощью Swagger (для REST API) и файлов WSDL (для SOAP API). 

  2. Возможность тестировать REST и SOAP.

  3. Легкий экспорт и импорт проектов одним файлом. То есть вы экспортируете этот файл один раз, передаете коллеге, он устанавливает его и импортирует себе. Нет необходимости переносить отдельно переменные, окружение и сами запросы, как в Postman. 

  4. Возможность использовать окружения и переменные.

  5. Возможность написания кастомных скриптов для проверки ожидаемого и фактического результата.

  6. Встроенные варианты проверок. 

  7. Параллельный запуск кейсов, что очень важно. 

  8. Раннер видит именно список кейсов, а не список запросов и список шагов в них. 

  9. Можно сделать нагрузочные тесты.

  10. Можно написать мок-заглушки.

  11. Eсть возможность использовать функционал прокси. 

Минусы SOAPUI: 

  1. Сложный интерфейс относительно предыдущих API-клиентов. 

  2. Не поддерживает gRPC и GraphQL в бесплатной версии.

  3. Не поддерживает интеграцию с Git в бесплатной версии. 

  4. Не поддерживает интеграцию с системами непрерывной сборки в бесплатной версии.

SOAPUI подойдет, если у вас есть много тест-кейсов из нескольких запросов, а также нужен параллельный запуск этих кейсов. Когда у вас есть кейсы с вилкой результатов. Если на проекте нет потребности тестировать API кроме REST и SOAP. Когда вам не обязательно интегрировать тесты с системами непрерывной сборки.

Библиотеки. Rest Assured

Библиотеки это не самостоятельные инструменты, они написаны для использования внутри языков программирования. Так как на рассмотрение большого количества существующих библиотек тестирования API уйдет много времени. Рассмотрим их типичный функционал на примере популярной Rest Assured.

Так выглядит тест, написанный с использованием Rest Assured. С помощью public void объявляется тест “whenCreatePerson_thenStatus201” в given() задаются предварительные условия запроса, блок when() отправляет запрос к эндпойнту, а в then() происходит сверка ожидаемого и фактического результата. В данном примере проверяется, что при успешном создании пользователя приходит статус-код 201 (Created).

Следующий тест чуть более сложный: здесь обновляется предварительно созданный пользователь. При этом проверяются два ожидания: на статус-код 200 и в теле поле “name” будет иметь значение “Michail”. 

Плюсы Rest Assured: 

  1. Полная интеграция с системами CI/CD и возможность автоматически запускать проверки при появлении новой версии приложения на стенде.

  2. Возможность подключить инструмент Allure Reporting для автоматизированного формирования отчетов о тестировании. 

  3. Возможность реализовать практически любые проверки, которые можете написать сами, и практически любые предзапросные скрипты.

  4. Скорость работы тестов, написанных с помощью библиотек, и в частности Rest Assured, быстрее, чем у API-клиентов.

Минусы Rest Assured: 

  1. Нужно уметь писать код, причем хорошо. Rest Assured использует язык Java. Первый тест из учебника написать не сложно, но создать тесты которые действительно принесут пользу вашему проекту — это не так просто.

  2. Официальные туториалы для фреймворков и библиотек подходят только для мелких проектов либо для написания тестов а-ля “Hello, world!”. Наилучшие паттерны написания кейсов придется искать самостоятельно по форумам и другим источникам.

Фреймворки стоит выбирать, если вы уже умеете хорошо писать код или твердо намерены прокачаться в этом деле. Когда  хотите глубокой автоматизации и интеграции кейсов с CI/CD. Если  в кейсах много логик, для которых нужны сложные скрипты. Если для вашего проекта важно увеличение скорости повторного тестирования, в первую очередь — регрессионного. 

Сравнение реального использования инструментов

На проекте автора статьи последовательно вводилось использование инструментов тестирования API. 

Сервис назовем условно «Квартет», так как он включает в себя 4 микросервиса. Тип работы — асинхронный. На данном проекте произошла последовательная смена инструментов “Postman — SOAPUI — Rest assured”. Swagger присутствует, но для тестирования он не использовался, так как прохождение кейсов с его помощью, в нашем сервисе, не сильно быстрее использования графического интерфейса. Прохождение кейсов с помощью GUI возьмем за начальную точку сравнения. 

Написание каждого тест-кейса заняло 6 минут. 200 кейсов — это 1200 минут или 20 часов. Ручной прогон каждого end to end кейса в среднем занимает 4 минуты с учетом скорости работы фронта, бэка и QA специалиста. 200 кейсов это 800 минут или 13,5 часов.

То есть, если проводить регресс вручную, на это каждый раз будет уходить 13-14 часов. И это без учета времени на баг-репорты, без поправки на усталость специалиста и так далее. Конечно же, такое время неприемлемо в условиях ограниченной QA-команды.

Первым используемым инструментом стал Postman. Скорость погружения в инструмент с момента установки до написания первого кейса, который можно реально использовать — 2 часа. Время на создание первого полностью автоматизированного кейса, который ждет построения файла, проверяет ожидаемый результат и т.д. — 8 часов. То есть освоение инструмента заняло 10 часов. После этого написание и отладка кейсов стали занимать по 10 минут в среднем, то есть на 200 кейсов ушло 34 часа.

Автоматизированное прохождение такого кейса в Postman занимает 50 секунд, то есть 200 кейсов проходят за 2 часа 47 минут. Вроде бы все хорошо, но из за особенностей работы системы, 50 секунд уходит только на успешный кейс, а на неуспешный — до 30 минут. Если проваливаться будут все 200, то такое прохождение займет до 100 часов. Конечно, такого никогда не случалось, но теоретическая возможность такого сценария заставляла искать инструмент с параллельным запуском кейсов. Тем более, что сам сервис мог обрабатывать результаты параллельно.

Им стал SOAPUI. Время погружения в инструмент с установки до написания первого полезного кейса составило 3 часа. Пилотный автоматизированный кейс был написан за 10 часов. 200 кейсов в SOAP UI были написаны за 44 часа. Да, делать тест-кейсы в этом инструменте немного дольше из-за своеобразного интерфейса. Но параллельный запуск полностью окупает этот недостаток. Кейсы запускались порциями по 100 и с учетом особенностей работы сервиса это давало 18 минут на порцию в случае успешного прохождения и 46 минут при неуспешном. То есть 200 успешных кейсов проходили за 36-37 минут, 200 неуспешных 1 час 32 минуты. Это был успех, который позволил не следить за прогоном, чтобы вовремя остановить его при нескольких неуспешных кейсах подряд. Но SOAPUI не хватает отчетности о тестировании, а главное — нет интеграции с CI/CD, а этого очень хотелось.

Поэтому перешли на Rest Assured в связке с JUnit 5. Погружение заняло 10 часов, еще 11 на написание пилотного кейса. 200 кейсов были созданы за 42 часа. JUnit  умеет запускать кейсы параллельно, поэтому запускали теми же порциями по 100, что в итоге дало прохождение 200 успешных кейсов за 35 минут в среднем, неуспешных — за 1 час 29 минут. С виду ускорение незначительное, но не стоит забывать, что появилась отчетность о каждом прогоне и главное — кейсы автоматически запускались при срабатывании определенного триггера. Регресс стал полностью автоматизированным.

Заключение

Мы рассмотрели наиболее распространенные Web-API и инструменты для тестирования разных уровней: от специфичных сваггероподобных систем до библиотек языков программирования. Несмотря на то, что фреймворки и библиотеки кажутся панацеей, это не так. Из приведенного примера внедрения видно — чем «способнее» инструмент, тем он сложнее и дольше в освоении. Выбор решения для тестирования API должен совершаться, исходя из конкретных потребностей проекта. Так, если интеграция с CI/CD не особа нужна, плюс в команде нет специалистов должного уровня, то не надо гнаться за фреймворками, достаточно выбрать подходящий API-клиент. 

Лучший инструмент не совершеннее других, а полезнее. 

Обсудить в форуме