Интеграция автоматизированного веб-тестирования в процесс сборки - PullRequest
19 голосов
/ 06 августа 2009

Я ищу предложения по улучшению процесса автоматизации функционального тестирования сайта. Вот что я пробовал в прошлом.

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

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

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

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

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

БОЛЬШЕ ДЕТАЛЕЙ Поскольку люди просили более подробную информацию, вот оно. Я использую ASP.NET, используя Visual Studio и Cassini (встроенный веб-сервер). Мои модульные тесты выполняются в MbUnit (но это не так важно. Может быть NUnit или XUnit.NET). Как правило, у меня есть отдельная структура модульных тестов, запускающая все мои тесты WATIN. На этапе AssemblyLoad я запускаю веб-сервер и локально копирую весь код своего веб-приложения.

Мне интересны решения для любой платформы, но мне может понадобиться больше описаний того, что означает каждая вещь. :)

Ответы [ 6 ]

11 голосов
/ 08 августа 2009

Фил,

Автоматизация может быть сложной в обслуживании, но чем больше вы используете вашу автоматизацию для развертывания, тем больше вы сможете использовать ее для настройки теста (и наоборот).

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

Итак, некоторая часть вашей борьбы по сути связана с инструментами. Чтобы ваша автоматизация была разумной и поддерживалась, вам следует остерегаться препятствий, которые создают статические инструменты сборки, такие как NAnt и MSBuild.

Я бы посоветовал вам не связывать загрузочную привязку тестовой среды с загрузкой сборки. Это внутренняя муфта, которая служит лишь краткому удобству. Нет ничего плохого (и, вероятно, все в порядке) с переходом в командную строку и выполнением задачи сборки, которая устанавливает среду перед запуском тестов либо из IDE, либо из командной строки, либо из интерактивной консоли, например C # REPL из Mono Project или от IRB.

Настройка тестовых данных - это просто боль в заднице. Это должно быть сделано.

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

Я управляю всеми примерами управления данными из HTTP. Я пишу контроллеры с действиями специально для управления примерами данных и выдаю GET против этих действий через Selenium. Я использую их для создания и очистки данных. Я могу составить GET для этих действий, чтобы создать общие сценарии данных настройки, и я могу передать конкретные значения для данных в качестве параметров запроса (или параметров формы, если это необходимо).

Я держу эти контроллеры в области, которую я обычно называю "test_support".

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

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

Существует большое вторичное значение для контроля выборочных данных вашего веб-приложения или тестовых данных из Интернета: при демонстрации приложения или при проведении исследовательского тестирования вы можете создать необходимые сценарии данных, просто выполнив некоторые действия против известных (или предположительно) URL в области test_support. На самом деле делает дисциплинированное усилие, чтобы придерживаться успокоительных маршрутов и ресурсов ориентации здесь будет действительно окупается.

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

Например, написание кода модели домена поверх семантической модели ваших веб-страниц поможет создать гораздо более понятный тестовый код и уменьшить хрупкость. Если вы делаете это хорошо, вы можете использовать те же модели с различными драйверами, чтобы вы могли использовать их в стресс-тестах и ​​нагрузочных тестах, а также в функциональных тестах, а также использовать их из командной строки в качестве исследовательских инструментов. Кстати, такого рода вещи легче делать, когда вы не привязаны к типам драйверов, как при использовании статического языка. Есть причина, по которой многие ведущие мыслители и разработчики работают в Ruby и почему Watir написан на Ruby. Повторное использование, компоновка и выразительность в Ruby намного проще, чем в тестовом коде C #. Но это другая история.

Давайте подождем и поговорим подробнее о других 90% этого материала:)

2 голосов
/ 08 августа 2009

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

Он был на удивление стабильным - не копировал файлы и не запускал внепроцессный сервер.

Вот как выглядит тест с использованием плазмы для нас ...

    [Test]
    public void Can_log_in() {
        AspNetResponse response = WebApp.ProcessRequest("/Login.aspx");
        AspNetForm form = response.GetForm();

        form["UserName"] = User.UserName;

        form["Password"] = User.Password;

        AspNetResponse loggedIn = WebApp.ProcessRequest(Button.Click(form, "LoginUser"));


        Assert.IsTrue(loggedIn.IsRedirect());

        AspNetResponse homePage = WebApp.ProcessRequest(loggedIn.GetRedirectUrl());

        Assert.AreEqual(homePage.Status, 200);
    }

Все классы AspNetResponse и AspNetForm включены в состав плазмы.

1 голос
/ 08 августа 2009

Зачем вам нужно копировать код? Дитч Кассини и позвольте Visual Studio создать виртуальный каталог для вас. Конечно, разработчики должны помнить о необходимости сборки перед запуском веб-тестов, если веб-приложение изменилось. Мы обнаружили, что это не имеет большого значения, особенно если вы запускаете веб-тесты в CI.

Данные - это большая проблема. Насколько я понимаю, вы должны выбирать между несовершенными альтернативами. Вот как мы с этим справимся. Во-первых, я должен объяснить, что мы работаем с большим сложным унаследованным приложением WebForms. Также я должен отметить, что код домена не подходит для создания тестовых данных из тестового проекта.

Это оставило нам пару вариантов. Мы могли бы: (а) запустить сценарии настройки данных при сборке или (б) создать все данные с помощью веб-тестов с использованием реального веб-сайта. Проблема с опцией (а) заключается в том, что тесты соединяются со скриптами на минутном уровне. Это заставляет меня задуматься о синхронизации кода веб-теста с T-SQL. Итак, мы пошли с (б).

Одним из преимуществ (b) является то, что ваша установка также проверяет поведение приложения. Проблема в том ... время .

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

Мы используем Gallio (MbUnit 3), который предоставляет некоторые приятные функции, которые поддерживают нашу стратегию. Во-первых, он позволяет вам указать порядок выполнения на уровне прибора и теста. У нас есть четыре «установочных» светильника, которые заказаны -4, -3, -2, -1. Они запускаются в указанном порядке и перед всеми приборами «без настройки», которые по умолчанию имеют порядок 0.

Наш веб-тестовый проект зависит от сценария сборки только с одной стороны: одно общеизвестное имя пользователя / пароль. Это связь, с которой я могу жить. По мере выполнения тестов установки они создают объект «контекст данных», который содержит идентификаторы данных (компании, пользователи, поставщики, клиенты и т. Д.), Которые впоследствии используются (но никогда не менялись) во всех остальных устройствах. (Под идентификаторами я не обязательно имею в виду ключи. В большинстве случаев наш веб-интерфейс не предоставляет уникальных ключей. Мы должны перемещаться по приложению, используя имена или другие прокси для истинных идентификаторов. Подробнее об этом ниже.)

Gallio также позволяет вам указать, что тест или прибор зависит от другого теста или прибора. Когда прецедент терпит неудачу, зависимый пропускается. Это уменьшает зло временной связи, предотвращая «каскадные сбои», которые могут привести к путанице.

Создание базовых тестовых данных один раз, а не перед каждым тестом, значительно ускоряет процесс. Тем не менее, тесты настройки все еще могут занять 10 минут. Когда я работаю над новыми тестами, я хочу часто запускать их. Введите еще одну классную функцию Gallio: атмосфера. Ambience - это оболочка для DB4, которая обеспечивает очень простой способ сохранения объектов. Мы используем его для автоматического сохранения контекста данных. Таким образом, тесты установки должны выполняться только один раз между перестройками базы данных. После этого вы можете запускать любое или все другие приборы повторно.

Так как насчет очистки данных испытаний? Разве нам не нужно начинать с известного состояния? Это правило, которое мы сочли целесообразным нарушать. Стратегия, которая работает для нас, состоит в том, чтобы использовать длинные случайные значения для таких вещей, как название компании, имя пользователя и т. Д. Мы обнаружили, что не очень сложно поддерживать тестовый прогон внутри логического «пространства данных», чтобы он не сталкивался в другие данные. Конечно, я боюсь того дня, когда буду часами гоняться за фантомным провалом теста, только чтобы обнаружить, что это какая-то коллизия данных. Это компромисс, который работает для нас в настоящее время.

Мы используем Watin. Мне это очень нравится Еще один ключ к успеху - это то, на что ссылался Скотт Беллвер. При создании тестов мы создаем абстрактную модель нашего пользовательского интерфейса. Так что вместо этого:

browser.TextField("ctl0_tab2_newNote").TypeText("foo");

Вы увидите это в наших тестах:

User.NotesTab.NewNote.TypeText("foo");

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

Надеюсь, это поможет.

1 голос
/ 08 августа 2009

В настоящее время мы используем автоматизированный процесс сборки для нашего приложения asp.net mvc.

Мы используем следующие инструменты:

  • TeamCity
  • 1008 * SVN *
  • NUnit
  • Селен

Мы используем скрипт msbuild, который запускается на агенте сборки, который может быть любым количеством машин. Скрипт msbuild получает последнюю версию кода из svn и собирает ее.

В случае успеха он затем развертывает артефакты на заданной машине / в папке и создает виртуальный сайт в IIS.

Затем мы используем задачи contrib MSBuild для запуска сценариев sql для установки базы данных и загрузки данных, вы также можете выполнить восстановление.

В случае успеха мы запускаем тесты nUnit. Тестовая установка гарантирует, что селен запущен и работает, а затем запускает тесты на селен так же, как и Уотин. У Selenium есть хороший рекордер для тестов, который можно экспортировать в c #.

Хорошая особенность Selenium в том, что вы можете управлять FF, Chorme и IE, а не ограничиваться IE, как было с Уотином в последний раз, когда я смотрел на него. Вы также можете использовать Selenium для проведения нагрузочного тестирования с помощью Selenium Grid, поэтому вы можете повторно использовать те же тесты.

В случае успеха msbuild затем помечает сборку в SVN. У TeamCity есть задание, которое выполняется в одночасье, и развертывает последний тег в промежуточной среде, готовой для бизнес-пользователей проверить состояние проекта на следующее утро.

В прошлой жизни у нас были сценарии nant & msbuild для полного управления средой (установка java, selenium и т. Д.), Однако это занимает много времени, поэтому в качестве предварительного условия мы предполагаем, что они установлены на каждом агенте сборки. Со временем мы включим эти задачи.

0 голосов
/ 12 августа 2009

Вы имеете в виду автоматический запуск тестирования после завершения сборки? Вы можете написать автоматические сценарии для копирования файлов сборки в работающий IIS, пока сборка выполняется успешно. А затем запустите автоматический BVT с помощью вызова mstest.exe или других методов.

Вы можете попробовать autoitx или другой язык функций, например Python, ruby.

0 голосов
/ 06 августа 2009

Было сложно, но не невозможно, встроить этап интеграционного тестирования в процесс сборки с использованием maven. То, что произошло по сути, было так:

  • Игнорировать все тесты JUNit в определенном каталоге, если не запускается фаза интеграционного теста.
  • Добавьте профиль maven для выполнения интеграционных тестов.
  • Для этапа предварительного тестирования -

  • Запустите Jetty, запустив приложение, попавшее в тестовую базу данных.

  • Запустить селеновый сервер
  • Запуск интегральных тестов селена на этапе интеграционных испытаний
  • Остановить селеновый сервер
  • Стоп селена

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

...