Содержание:
1. Введение
2. Установка
3. Создание тестов с помощью ArtoOfTest WebAii
4. Конфигурирование тестов
5. Первый тест
6. Работаем с AJAX
7. Поиск элементов и автосгенерированные Id элементов в ASP.NET
Введение
Итак, закомимся – WebAii – framework для автоматизированного тестирования web приложений. Сайт разработчиков: http://www.artoftest.com.
Что же предлагает WebAii:
- Автоматизация с использованием событий DOM, или вызов событий клавитуры/мыши напрямую (клики, перетаскивание и прокрутка, ввод текста).
- Подежка приложений Ajax и JavaScript Unit-testing.
- Возможность поиска элементов на странице с возможностью указания «упрощенных» названий элементов для упрощения поиска их на странице.
- Реализация DOM-модели в .NET, что дает возможность навигации по элементам из кода тестового модуля.
- Поддержка NUnit и Visual Studio Team Test шаблонов и расширений.
- Поддержка visual capturing элементов и состояний браузера.
- А также многие другие полезные возможности, облегчающие процесс тестирования и написания unit-тестов (TestRegions, HTML popups, frames support, etc).
- Большое количество примеров использования.
Установка
Для того, чтобы скачать WebAii, необходимо зарегистрироватся у них на форуме. Ну что ж, регистрируемся, качаем. Далее устанавливаем:
Установка проходит простыми нажатиями Next в инсталяторе J.
После установки заглянем в папку, в которую мы поставили WebAii.
Подробно о назначении каждой сборки я расказывать не буду. Просто отмечу что главной сборкой является ArtoOfTest.WebAii.dll, которая является ядром test framework, и в которой собраны такие важные классы, как Settings, Manager, Browser, Find и т. д.
Замечу что в это папке находится add-in для FireFox, который тоже необходимо установить. Откройте FireFox и просто перетяните файл webaii@artoftest.com.xpi в окно FireFox, дождитесь пока станет активной кнопка Install Now и нажмите ее, все, add-in готов к использованию:
Создание тестов с помощью ArtoOfTest WebAii.
В этом примере я раскажу как использовать WebAii в Visual Studio Team Test / Team Suite. Использование WebAii совместно с NUnit описано здесь.
Итак, запускаем Visual Studio, и создаем новый проект теста: File -> New -> Project. В дереве: Visual C# -> Test -> Test Project.
После создания проекта, удаляем все созданные автоматически файлы (мы будем использовать темплейты, которые были установлены, при установке WebAii). Для этого нажимаем правой кнопкой на проекте и выбираем Add -> New Item .. а в появившемся окне ищем WebAii VsUnit Test, даем «человеческое» имя файлу теста и жмем Add.
Все, шаблон «готов к употреблению».
Здесь на минутку остановимся и взглянем на базовый класс нашего Unit Test – BaseVsUnitTest. В нем есть несколько полезных, часто используемых свойств: Manager, Settings, Browser, Desktop, Log, Find, которые используются чаще всего, при этом они уже есть (как видим в базовом классе, и нам не прийдется заботится об их создании/инициализации) .
|
using ArtOfTest.WebAii.Core; using System;
namespace ArtOfTest.WebAii.TestTemplates { public abstract class BaseVsUnitTest { protected BaseVsUnitTest(); public Actions Actions { get; } public Browser ActiveBrowser { get; } public Desktop Desktop { get; } public Find Find { get; } public Log Log { get; } public Manager Manager { get; }
public void CleanUp(); public static Settings GetSettings(); public void Initialize(); public void Initialize(string logLocation); public void Initialize(TestContextWriteLine vsWriteLineDelegate); public void Initialize(Settings settings, TestContextWriteLine vsWriteLineDelegate); public void Initialize(string logLocation, TestContextWriteLine vsWriteLineDelegate); public void SetTestMethod(object testObject, string testMethodName); } } |
Конфигурирование тестов
Вместо того, чтобы конфигурировать тест из кода, в WebAii существует возможность конфигурирования с помощью файла конфигурации App.config. Возьмем за основу ранее созданный проект (или скачиваем его здесь) и добавим к нему файл конфигурации. Жмем правой кнопкой мыши на пректе и выбираем Add -> New Item .. а в диалоге выбираем "Application Configuration File" -> жмем Add.
После чего файл конфигурации будет добавлен в проект. Теперь мы можем добавить секцию конфигурации. Открываем App.config файл. Выглядеть он должен где-то так:
|
<?xml version="1.0" encoding="utf-8" ?> <configuration> </configuration> |
Для начала зарегистрируем конфигурационную секцию WebAii.Settings. Для этого, внутри элемента configuration добаляем новый элемент configSections, в котором регистрируем секцию WebAii.Settings.
|
<configuration> <configSections> <section name="WebAii.Settings" type="ArtOfTest.WebAii.Core.SettingsConfigSectionHandler,ArtOfTest.WebAii, Version=1.0.600.0, Culture=neutral, PublicKeyToken=4fd5f65be123776c" /> </configSections> </configuration> |
А затем добавляем саму конфигурацию (ниже, под элементом /configSections). Всё вместе это должно выглядеть следующим образом:
|
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="WebAii.Settings" type="ArtOfTest.WebAii.Core.SettingsConfigSectionHandler,ArtOfTest.WebAii, Version=1.0.600.0, Culture=neutral, PublicKeyToken=4fd5f65be123776c" /> </configSections> <WebAii.Settings annotateExecution="false" baseUrl=http://www.testserver.net/ clientReadyTimeout="50000" defaultBrowser="InternetExplorer" enableScriptLogging="false" enableUILessRequestViewing="false" executionDelay="0" executionTimeout="60000" localWebServer="None" logLocation="C:\WebAiiLog\" queryEventLogErrorsOnExit="false" scriptLoggingPort="8099" simulatedMouseMoveSpeed="0.5" webAppPhysicalPath="" /> </configuration> |
К сожалению, ArtOfTest не поставляет XSD схему для своей секции, следовательно Intellisence отсутствует при редактровании секции WebAii.Settings. Более подробно о свойствах WebAii.Setting можно узнать здесь, я же отмечу наиболее важные/полезные настройки:
- baseUrl – указывает базовый URL приложения, если эта опция указана, то при использовании методов NavigateTo() надо указывать относительные пути (довольно удобно, если предполагается, что тест должен работать вне зависимости от того, где находится сайт)ю
- clientReadyTimeout – время ожидания клиента (при тестировании во время разработки на локальном сервере и при прогоне тестов на продакшене, время отклика может оказатся разным).
- defaultBrowser – Браузер по умолчанию, в котором будет выполнен тест (по умолчанию Internet Explorer).
Первый тест
Пришло время сделать первый тест. Сделаем его очень простым (как делают приложения "Hello, World", когда начинают изучать язык программирования).
Для начала, в метод, помеченный атрибутом [TestInitizalize()] добавим следующий код:
|
if (Manager.Browsers.Count == 0) { Manager.LaunchNewBrowser(); } |
Это позволит при запуске каждого теста проверять, существует ли запущенный браузер, и запускать новый, если нет запущенных.
А теперь наш Hello, World.
|
[TestMethod] public void FirstTestMethod() { Manager.ActiveBrowser.NavigateTo(http://google.com/);
// Insert "Hello, World" to seach field. HtmlInputText searchField = Find.ByAttributes<HtmlInputText>("name=\"q\""); searchField.Text = "Hello, World";
// Find search button and click. HtmlInputSubmit submit = Find.ByName<HtmlInputSubmit>("btnG"); submit.Click();
// Wait till browser gets ready. Manager.ActiveBrowser.WaitUntilReady(); HtmlInputText searchField2 = Find.ByAttributes<HtmlInputText>("name=\"q\"");
Assert.AreEqual(searchField.Text, searchField2.Text); } |
Простой тест, позволяющий проверить, работает ли Google J. Все довольно просто: открываем браузер, открываем страницу поиска Google, ищем поле ввода по имени (name = "q") и кнопку поиска, указываем, что хотим искать "Hello, World", и жмем на кнопку, проверяем, что в поле поиска осталось значение ("Hello, World"), которое мы искали. Пример можно скачать здесь.
А теперь о плохом:
Иногда можно получить следующую ошибку: ArtOfTest.WebAii.Exceptions.ExecuteCommandException
Это по всей видимости проиходит потому, что браузер не готов выполнять посланные команды, в часности, NavigateTo, поэтому, если такое возникает, добавьте в начало теста строку ожидания браузера (пока он не перейдет в состояние ready)
Manager.ActiveBrowser.WaitUntilReady();
Работаем с AJAX
Первое впечатление при попытке подружить WebAii и AJAX было – «не работает». Проверим так ли это. Создадим простое Web-приложение, которое использует ASP.NET AJAX.
Замечание:
В дальнейшем предполагается, что ASP.NET AJAX установлен.
Для этого выбираем File -> Add -> New Web Site. Из предложенных вариантов выбираем ASP.NET AJAX-Enabled Web Site и «поселяем» новый веб-сайт в IIS: выбираем
- Location: HTTP
- Language: Visual C#
- Жмем Browse и создаем приложение/виртуальную директорию, к которой будет находится сайт
Далее, сделаем простой пример с применением AJAX. Это немного выходит за рамки темы даного поста, поэтому чтобы чтобы не делать все описанное ниже, можно просто скачать демо-проект и разместить его в IIS.
Итак, добавим на страницу для начала компонент UpdatePanel (тем самым обеспечив асинхронное обновление части страницы). Внутрь UpdatePanel поместим Label и Button, при клике на последнюю, будем асинхронно обновлять надпись в Label.
Исходный код ASPX (Default.aspx):
|
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head>
<body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div> <asp:UpdatePanel runat="server" ID="demoUpdatePanel"> <ContentTemplate> <asp:Label runat="server" ID="lblTitle"></asp:Label> <br /> <asp:Button runat="server" ID="btnGo" Text="Press to go!" OnClick="OnGoButtonClick" /> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html> |
Исходный код code-behind (Default.aspx.cs):
|
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { }
protected void OnGoButtonClick(object sender, EventArgs e) { this.lblTitle.Text = "Async GO"; } } |
Вот такое простое web-приложение получилось. Запускаем, жмем кнопку "Press to go!" и убеждаемся, что приложение работает асинхронно, и окно браузера не перерисовается полностью (а только меняется надпись).

Приложение есть, и оно работает используя ASP.NET AJAX. Пришло время протестировать его. Снова воспользуемся ранее созданным проектом BaseWebAiiProject (в котором мы тестировали Google). Открываем файл FirstTest.cs, находим в нем FirstTestMethod() и под ним добавляем следующий метод:
|
[TestMethod] public void TestAjaxApplication() { Manager.ActiveBrowser.WaitUntilReady(); } |
|
В этот метод будет добавлен код, которым мы проверим, как изменилось состояние надписи после нажатия на кнопку. Прежде чем написать сам тест, отмечу, что в WebAii, а точнее у класса Actions, существует метод, с помощью которого можно ждать измения состояния элементов страницы – WaitForEment(FindParam, waitTimeout, invertCondition [optional]). Пример...
|
[TestMethod] public void TestAjaxApplication() { Manager.ActiveBrowser.WaitUntilReady(); Manager.ActiveBrowser.NavigateTo("~/TestAjax/Default.aspx");
// Check intial state. HtmlSpan label1 = Find.ById<HtmlSpan>("lblTitle"); Assert.AreEqual(string.Empty, label1.InnerText);
// Search for "go" button. HtmlInputSubmit goButton = Find.ByName<HtmlInputSubmit>("btnGo"); goButton.Click();
FindParam seachParam = new FindParam("id=\"lblTitle\"", "innerText=\"\""); Manager.ActiveBrowser.Actions.WaitForElement(seachParam, 500, true);
HtmlSpan label2 = Find.ById<HtmlSpan>("lblTitle"); string text = label2.InnerText; Assert.AreEqual("Async GO", text); } | |
.. и объяснения: для начала находим элемент span (наш asp:Label), и проверяем его innerText, убеждаемся что он равен «», затем нажимаем кнопку и ждем пока изменится состояние описанное в FindParam. Замечу, что в FindParam можно указывать несколько условий, по которым будет производится поиск. В нашем случае – ищем кнопку с id = "lblTitle" и аттрибутом innerText = "". Учитывайте, что WaitForElement будет «ждать» элемент 500ms (столько, сколько ему «сказали» ждать), и по истечению этого периода времени выполнение теста будет продолжено.
Поиск элементов и автосгенерированные Id элементов в ASP.NET.
Учитывая то, что в ASP.NET идентификаторы элементов создаются автоматически, то прямой поиск по id = "myButton" не удастся, т.к. в HTML этот Id для кнопки ASP.NET будет преобразован, например в такой ID: GridView1$ctl07$myButton. Как же делать поиск в таком случае? К сожалению Find.ById не поддерживает регулярные выражения (что бы в значительной мере облегчило жизнь), но существует такой метод как FindCustom, где можно указывать предикаты поиска.
Пример:
|
[TestMethod] public void FindCustomTest() { Manager.ActiveBrowser.WaitUntilReady(); Manager.ActiveBrowser.NavigateTo("~/TestAjax/Default.aspx");
// Original control ID within DOM is GridView1$ctl02$myButton. IdSearch searchPredicate = new IdSearch("myButton"); HtmlInputSubmit myButton = Find.ByCustom<HtmlInputSubmit>(searchPredicate.Search); Assert.AreEqual("Do", myButton.Value); } |
Далее, если посмотреть в отладчике, на тест с использованием предиката, то можно увидеть следующее
Таким образом, указывая только часть имени и используя предикаты поиска, можно искать элементы с Id, автосгенерированными ASP.NET. Пример, и класс предиката, можно скачать здесь.
На этом пожалуй и все. Happy coding.