Главная страница   /   20.1. Тестирование пользовательского интерфейса (ASP.NET MVC 4 в действии

ASP.NET MVC 4 в действии

ASP.NET MVC 4 в действии

Джеффри Палермо

20.1. Тестирование пользовательского интерфейса

В данной книге до настоящего момента мы занимались изучением множества индивидуальных компонентов и возможностей расширения ASP.NET MVC, включая роуты, контроллеры, фильтры и механизмы связывания данных модели. Несмотря на то, что изолированное модульное тестирование каждого компонента является важным, окончательным тестом работающего приложения является взаимодействие веб-браузера с реальным экземпляром. Благодаря всем компонентам, из которых состоит единичный запрос, и чье взаимодействие и зависимости могут усложняться, убедиться в том, что ваше приложение работает от начала до конца так, как вы и хотели, вы можете только при помощи тестирования через веб-браузер. При разработке приложения мы часто запускаем веб-браузер для того, чтобы вручную проверить, что наши изменения корректны и обеспечивают желаемое поведение.

Во многих организациях ручное тестирование принимает форму скрипта регрессионного тестирования, который выполняется разработчиком или QA-специалистом перед запуском. Ручное тестирование – медленное, довольно ограниченное, поскольку выполнение отдельного теста может занимать несколько минут. В большом приложении регрессионное тестирование в лучшем случае минимально, а в большинстве случаев является ужасающе недостаточным. К счастью, существует множество бесплатных, автоматизированных инструментов для тестирования пользовательского интерфейса. Ниже перечислены некоторые наиболее популярные инструменты, которые хорошо работают в рамках ASP.NET MVC:

Помимо этих проектов с открытым исходным кодом, многие коммерческие решения предоставляют дополнительную функциональность или интеграцию с такими системами составления отчетов об ошибках или с системами отслеживания рабочих элементов, как Microsoft’s Team Foundation Server. Инструменты не привязаны ни к одному из фреймворков тестирования, поэтому интеграция с существующим проектом довольно тривиальна. Вместо того чтобы полагаться на медленные, подверженные ошибкам ручные тесты пользовательского интерфейса, мы будем автоматизировать универсальный сценарий тестирования пользовательского интерфейса.

Установка программного обеспечения для тестирования

В этом разделе мы рассмотрим тестирование пользовательского интерфейса с помощью WatiN, который обеспечивает простую интеграцию с фреймворками модульного тестирования. WatiN (аббревиатура для Web Application Testing in .NET) – это .NET библиотека, которая предоставляет интерактивный API веб-браузера как для взаимодействия с веб-браузером (посредством нажатия на ссылки и кнопки), так и для поиска элементов в DOM (объектной модели документа).

Тестирование с помощью WatiN обычно подразумевает взаимодействие с приложением с целью отправки формы, а затем проверки результатов на экране представления. Поскольку WatiN не привязан ни к какому конкретному фреймворку модульного тестирования, мы можем использовать любой фреймворк модульного тестирования, какой только пожелаем. Платформа для автоматизации тестов Gallio (http://www.gallio.org/) предоставляет важные дополнительные возможности, которые упрощают автоматизацию тестов пользовательского интерфейса:

  • Регистрирует индивидуальные взаимодействия в рамках теста
  • Запускает тесты параллельно
  • Вставляет скриншоты в отчет теста (в случае, если тест не выполняется)

Для того чтобы приступить к работе, вам необходимо загрузить Gallio с сайта Gallio. После его загрузки запустите мастер установщика для того, чтобы установить комплекты Gallio и интегрировать его в Visual Studio. В Gallio входит внешний инструмент для запуска тестов (Icarus), а также возможность интеграции со многими инструментами для запуска модульных тестов, включая TestDriven.Net, ReSharper и другие. Также в состав Gallio входит MbUnit – фреймворк модульного тестирования, который мы будем использовать для того, чтобы составлять наши тесты.

После загрузки и установки Gallio вам необходимо создать проект Class Library и добавить указатели как на Gallio.dll, так и на MbUnit.dll. Затем вам необходимо загрузить WatiN и добавить в ваш проект теста указатель на комплект WatiN.Core.dll.

После добавления указателей вы готовы к созданию простого теста.

Прогон теста вручную

Базовым, но полезным сценарием в приложении является тестирование с целью испытания того, можем ли мы редактировать базовую информацию. Наше пробное приложение "Product Catalog" позволяет пользователю просматривать и редактировать подробную информацию о товаре, что является критичной коммерческой возможностью. Тестирование вручную предусматривает последовательное выполнение следующих шагов:

  1. Переход на домашнюю страницу
  2. Нажатие на вкладку Products, как это продемонстрировано на рисунке 20-1
Рисунок 20-1: Нажатие на вкладку Products
  1. Нажатие на ссылку Edit для одного из перечисленных товаров, что продемонстрировано на рисунке 20-2
Рисунок 20-2: Нажатие на ссылку Edit для товара
  1. Изменение информации о товаре и нажатие Save, что продемонстрировано на рисунке 20-3
Рисунок 20-3: Изменение информации о товаре и сохранение
  1. Проверка того, что мы были перенаправлены обратно на страницу со списком товаров.
  2. Проверка того, что информация о товаре была обновлена корректно, как это продемонстрировано на рисунке 20-4.
Рисунок 20-4: Контроль корректности перехода на страницу размещения списка товаров и изменения информации

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

Автоматизация теста

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

Листинг 20-1: Первая попытка написания теста пользовательского интерфейса
[TestFixture]
[ApartmentState(ApartmentState.STA)]
public class ProductEditTester
{
	[Test]
	public void Should_update_product_price_successfully()
	{
		using (var ie = new IE("http://localhost:8084/"))
		{
			ie.Link(Find.ByText("Products")).Click();
			ie.Link(Find.ByText("Edit")).Click();
			var priceField = ie.TextField(Find.ByName("Price"));
			priceField.Value = "389.99";
			ie.Button(Find.ByValue("Save")).Click();
			ie.Url.ShouldEqual("http://localhost:8084/Product");
			ie.ContainsText("389.99").ShouldBeTrue();
		}
	}
}

Строка 2: Устанавливает для теста режим STA

Строка 8: Создает веб-браузер

Строка 10-11: Нажимает на ссылку

Строка 14-15: Находит текстовое поле и изменяет значение

Строка 16: Нажимает на кнопку Save

Строка 17-18: Добавляет перенаправление URL

Строка 19: Добавляет обновленную цену

Сначала мы создаем класс и помечаем его TestFixtureAttribute. Как и большинство фреймворков автоматизированного тестирования в .NET, MbUnit требует, чтобы вы помечали классы тестов атрибутом, поскольку MbUnit выполняет поиск этих атрибутов для того, чтобы определить, какой класс из упряжки тестов необходимо исполнить. Затем мы помечаем класс теста атрибутом ApartmentState. Этот атрибут необходим, поскольку WatiN использует COM (компонентную объектную модель) для автоматизации окна веб-браузера Internet Explorer (IE). Каждый тест, который мы создаем, – это открытый void метод, помеченный атрибутом Test. MbUnit будет выполнять каждый метод с атрибутом Test и записывать результат.

После того, как мы разместили наш класс теста и метод, для выполнения нашего сценария теста нам необходимо использовать WatiN. Сначала мы создаем экземпляр нового IE объекта в блоке using. При создании экземпляра IE объекта окно веб-браузера запустится незамедлительно и перейдет к URL, указанной в конструкторе. Нам необходимо заключить жизненный цикл IE в блоке using для того, чтобы убедиться в том, что COM-ресурсы, которые использует WatiN, должным образом ликвидируются. IE объект – это наш главный шлюз для автоматизации веб-браузера с помощью WatiN.

Для взаимодействия с веб-браузером IE объект предоставляет методы для поиска, контроля и управления DOM-элементами. Мы используем метод Link для того, чтобы найти ссылку Products по ее тексту, а затем нажимаем на нее с помощью метода Click. В метод Link входит множество перегрузок, а мы используем ту, которая делает выбор на основании объекта BaseConstraint инструмента WatiN. Статический класс Find включает вспомогательные методы для создания ограничений, которые используются для фильтрации элементов в DOM.

После нажатия на ссылку Products мы переходим к первой на странице ссылке Edit и нажимаем на нее. После нажатия на эту ссылку мы попадаем на страницу редактирования единичного товара.

Теперь нам необходимо найти и заполнить элемент ввода данных о цене. Глядя на исходный код, мы можем увидеть, что элемент ввода данных обладает атрибутом name со значением "Price", поэтому мы выполняем поиск по атрибуту name для того, чтобы найти нужный элемент ввода данных Price. Для того чтобы изменить значение элемента, как если бы мы вводили его в веб-браузере вручную, мы устанавливаем новое значение для свойства Value. После изменения значения мы теперь можем найти кнопку Save по имени и нажать ее.

Если наше сохранение выполнится успешно, то нас должны перенаправить обратно к странице со списком товаров. Если мы сталкиваемся с ошибкой валидации, мы останемся на странице редактирования товара. В нашем сценарии мы вводили все валидные данные, поэтому мы выполняем проверку, чтобы убедиться, что нас перенаправят на страницу со списком товаров. Наконец, мы можем проверить, что значение нашего товара обновлено, путем поиска значения цены на странице. ShouldBeTrue() – это метод расширения библиотеки тестов NBehave.

Запуск теста

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

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

  • При изменении текста ссылки Products
  • При изменении текста ссылки Edit
  • При изменении первой строки списка
  • При изменении названия элемента ввода данных
  • При изменении текста кнопки Save
  • При изменении URL (либо названия контроллера, действия, хоста, либо порта)
  • Другой товар имеет ту же цену

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

Решение в пользу хрупких тестов следует принимать ради тестируемости. До настоящего времени мы относились к нашему приложению как к черному ящику. Тест всего лишь использовал окончательный отображаемый HTML для того, чтобы создать взаимосвязь с приложением. Вместо того чтобы относиться к нашему приложению как к черному ящику, мы можем конструировать наш пользовательский интерфейс таким образом, чтобы тесты этого интерфейса были стабильными и полезными.

В следующем разделе мы рассмотрим создание работоспособных элементов навигации для нашего сайта.