Интеграция автоматизированного веб-тестирования в процесс сборки

StackOverflow https://stackoverflow.com/questions/1240057

Вопрос

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

Раньше у меня был тестовый проект, использующий ВАТИН.Вы эффективно пишете то, что выглядит как "модульные тесты", и используете WATIN для автоматизации перехода браузера по вашему сайту и т.д.

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

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

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

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

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

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

Это было полезно?

Решение

Фил,

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

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

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

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

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

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

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

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

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

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

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

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

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

Давайте как-нибудь наверстаем упущенное и подробнее поговорим об остальных 90% этого материала :)

Другие советы

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

Это было на удивление стабильно - никакого копирования файлов или запуска нерабочего сервера.

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

    [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" включены в Plasma.

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

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

  • Командный город
  • SVN
  • нАнит
  • Селен

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top