12 февраля 2013 в 07:25

Девять кругов автоматизированного тестирования



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

Я отвечу на вопросы: Что тестируем? Кто этим занимается? Зачем это все происходит? Что у нас есть?
А затем расскажу как все работает: опишу круги тестирования — с первого по девятый.

Что?

Наш продукт — корпоративное web-приложение Service Desk, написано на java.

Кто?

Я — лид группы автоматизированного тестирования; программисты код которых тестируем; ручные тестировщики, рутину которых мы искореняем; менеджеры верящие, что если тесты прошли, то все не так уж и плохо.

Зачем?

Цель моей группы — уберечь продукт от регрессионной спирали смерти.
Задача группы — необнаружение дефектов максимумом интересных способов с минимальным количеством ручного труда.

Что у нас уже есть?

900 коротких и не очень сценариев использования приложения закодированых в тесты.
CI Jenkins на шести серверах, три СУБД, два семейства ОС и три браузера под которые пишем продукт.

Как это работает?



Круг первый — сценарий теста.

Мельчайшая единица — тест, начинается со сценария.
Javadoc тестового метода, который мы потом собираем и показываем ручным тестерам и ПМам.

  1. Заголовок теста — коротко и ясно описывает, что мы проверяем.
  2. Ссылка на постановку по которой написан тест; если ее нет, то кейс лишь игра воспаленного воображения тестировщика, у нас корпоративное ПО, мы не шутки шутим.
  3. Сценарий теста на русском, описывающий три фазы теста — подготовка, выполнение действия и верификацию.

Note: Сценарий — не перевод с java на русский, напротив, сценарий первичен, причем на написание качественного кейса уходит больше времени, чем на его кодирование. В нашем случае он, как правило, пишется не тем человеком, который кодирует тест.

Первая фаза теста — подготовка тестирующей системы.
Catalog catalog = DAOCatalog.create(true, false);
catalog.set(Catalog.TITLE, “Я хочу чтоб в этом тесте у объекта было такое название”)
DSLCatalog.add(catalog);
CatalogItem item = DAOCatalogItem.create(catalog);
DSLCatalogItem.add(item);

Концепция — есть модель системы, описываемая методами из DAO; есть методы с префиксом DSL которые приводят тестируемую систему к состоянию, описываемому моделью.
Методы из DSL меняют приложение через API системы, в нашем случае это restfull сервис. Всю первую фазу теста проводим через API.
Note: Правило — для каждого закодированного тестового действия написать DSL, чтоб в дальнейшем выполнять его через API.

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

Вторая фаза теста — тестовое действие с использованием selenium, через браузер.
DSLCatalog.goToCard(tester, item.get(CatalogItem.PARENT_CODE));
tester.clickElement(ADD_ELEMEMT);
DSLForm.assertFormAppear(tester, DSLForm.DIALOG);
tester.sendKeys(DSLForm.TITLE_INPUT, item.get(CatalogItem.TITLE));
tester.sendKeys(DSLForm.CODE_INPUT, item.get(CatalogItem.CODE));
tester.clickElement(DSLForm.SAVE_ON_FORM);
DSLForm.assertFormDisappear(tester, DSLForm.DIALOG);

Note: Также для обеспечения тестируемости каждый новый элемент интерфейса в системе имеет свой id уникальный в рамках страницы. Поэтому наши xpath выглядят так:
 "//*[@id='description-value']"
или
 "//*[@id='description-input']"

А не так:
"/html/body/table/tbody/tr/td[6]/table/tbody/tr[4]/td/div" 

Решается класс проблем с изменениями верстки.


Третья фаза — проверка или верификация. Хотя бы раз выполняем ее через интерфейс:
Assert.assertEquals("Название  отображается неверно в карточке шаблона отчета",  template.get(ReportTemplate.TITLE), tester.getTextElement(DSLForm.TITLE_VALUE));

А затем можно проверять уже через API.
ModelMap map = SdDataUtils.getObject(sc.get(Bo.METACLASS_FQN), Bo.UUID, sc.getUUID());
String message = String.format("Атрибут БО с uuid-ом '%s' имеет другое значение.", sc.getUUID());
Assert.assertEquals(message, team.get(Bo.TITLE), SdDataUtils.getMapValue(map, "responsibleTeam").get("title"));

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

Вторая и третья фаза могут проходить без использования браузера, как например почти сотня тестов на API.
Note: У кого-то должна возникнуть мысль: а не слишком ли много внимания уделяется тестированию через UI и на поднятом приложении?
Отвечу: особенность нашего ПО — высокая сложность не отдельных функций, но бизнес-логики. Практически каждый тест требует наличия БД и большого контекста. В таком случае unit-тесты не намного выигрывают по времени и значительно проигрывают по сложности написания.


Круг второй. Окружение теста.

Перед каждым запуском тестирующей системы:
  • проверяем доступность системы и возможность в нее залогиниться
  • проверяем глобальные настройки системы и если нужно устанавливаем нужные значения

Перед каждым классом с тестами
  • перезапускаем браузер
  • проверяем доступность системы

После каждого теста:
  • удаляем все созданные им объекты — это необходимо для поддержания скорости работы системы и изоляции тестов. При создании объекты помещаются в очередь и удаляются в обратном порядке.


Круг третий — иерархия тестов.


  • Один тест — одно действие. Исключений не больше 5%
  • Тесты объединены в классы по 3-10 штук, они тестируют бизнес-требование
  • 5-15 классов объединены в пакеты. Пакет тестирует сущность или аспект работы приложения
  • Пакетов 15


Note: Javadoc, собирается командой
mvn -f sdng-inttest/pom.xml javadoc:test-javadoc  -e 

Помогает ручным тестировщикам и ПМам узнать, какие есть тесты, позволяет не искать нужное в web-интерфейсе git и не устанавливать IDE.
Корень выглядит так:



Круг четвертый — организация проекта тестирующей системы.


60 000 строк кода тестирующей системы это
  • Код тестов
  • Утилитарные методы домена: код DSL(работа с тестируемой системой) и DAO(работа с моделями)
  • Утилитарные методы не привязанные к тестируемому приложению — работа со строками, файлами, JSON и т.п.
  • Ядро тестирующей системы: логи, скриншоты, очистка, интерфейс к webdriver, механизм исключений.


Note: Так выглядят настройка браузера для тестов, надеюсь кому-нибудь будет полезна:
FirefoxProfile
 /**
     * Открыть Firefox браузер.
     * http://code.google.com/p/selenium/wiki/FirefoxDriver
     * @return возвращает экземпляр класса FirefoxDriver, реализующий интерфейс WebDriver.
     * @exception WebDriverException если невозможно открыть браузер.
     */
    private WebDriver openFirefox()
    {
        FirefoxProfile firefoxProfile = new FirefoxProfile();

        //Память на вкладки
        firefoxProfile.setPreference("browser.sessionhistory.max_total_viewer", "1");
        //Значение 3 не просто так, иначе не работает авторефреш
        firefoxProfile.setPreference("browser.sessionhistory.max_entries", 3);
        firefoxProfile.setPreference("browser.sessionhistory.max_total_viewers", 1);
        firefoxProfile.setPreference("browser.sessionstore.max_tabs_undo", 0);
        //Асинхронные запросы к серверу
        firefoxProfile.setPreference("network.http.pipelining", true);
        firefoxProfile.setPreference("network.http.pipelining.maxrequests", 8);
        //Задержка отрисовки
        firefoxProfile.setPreference("nglayout.initialpaint.delay", "0");
        //Сканирование внутренним сканером загнрузок
        firefoxProfile.setPreference("browser.download.manager.scanWhenDone", false);
        //Анимация переключения вкладок
        firefoxProfile.setPreference("browser.tabs.animate", false);
        //Автоподстановка
        firefoxProfile.setPreference("browser.search.suggest.enabled", false);
        //Анимация гифок
        firefoxProfile.setPreference("image.animation_mode", "none");
        //Резервные копии вкладок
        firefoxProfile.setPreference("browser.bookmarks.max_backups", 0);
        //Автодополнение
        firefoxProfile.setPreference("browser.formfill.enable", false);
        //Убрал дисковый кеш и кеш в памяти
        //firefoxProfile.setPreference("browser.cache.memory.enable", false);
        firefoxProfile.setPreference("browser.cache.disk.enable", false);
        //Сохранять файлы без подтверждения в tslogs
        firefoxProfile.setPreference("browser.download.folderList", 2);
        firefoxProfile.setPreference("browser.download.manager.showWhenStarting", false);
        firefoxProfile.setPreference("browser.download.dir", new File("").getAbsolutePath());
        firefoxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk",
                "application/xml,application/pdf,application/zip,text/plain,application/vnd.ms-excel");
        return new FirefoxDriver(firefoxProfile);
    }

А еще у нас есть такая замечательная штука, как unit-тесты на ядро тестирующей системы.
Note: Тестирующая система, живет уже полтора года, пережила переезд из svn в git, 300 коммитов, поэтому 100 unit тестов жизненно необходимы

Два основных сценария использования — запуск из Jenkins и из eclipse
Алгоритм работы с конфигурацией запуска:
  1. Настройки тестирующей системы переданные из maven — самого высокого приоритета. Их пишем в конфиг. Если конфига нет, то создаем.
  2. Остальные настройки берем из конфига. Если конфига нет, то по умолчанию.
  3. Таким образом разработчики приложения и тестов настраивают свой персональный конфиг, а в CI все нужные параметры передаем через maven.

Мой файл конфигурации:
allowscreenshot=true
needinit=true
superlogin=naumen
allowsaveconfig=true
clickertime=3600000
testerpassword=atpassword
testerlogin=atlogin
superpassword=тутявсежезаменилтекст
needdelete=true
webaddress=http://localhost:9090/sd/
browsertype=firefox



Note: У ТС все по взрослому — есть свои постановки и сценарии использования.
“Я как автотестировщик хочу иметь возможность запускать тестирующее приложение на локальном компьютере, чтобы произвести определенные тесты на локальном стенде или клиентском, для дальнейшего анализа полученных данных, или для разработки новых тестов.”
“Я как разработчик хочу, чтобы ТС проверяла проект после каждого изменения, для своевременного выявления проблем и ошибок.
И так далее.


Балансировку тестов для их распараллеливания мы выполняем достаточно некрасивым образом.
Профиль запуска в pom.xml
      <profile>
            <id>smoke-snap2-branch</id>
 ...
                            <execution>
                                <id>integration-tests</id>
                                <configuration>
                                    <excludes>
                                        <exclude>all</exclude>
                                    </excludes>
                                    <includes>
                                        <include>**/selenium/**/advlist/*Test.java</include>
                                        <include>**/selenium/**/bo/*Test.java</include>
                                        <include>**/selenium/**/advimport/*Test.java</include>
                                        <include>**/selenium/**/user/*Test.java</include>
                                        <include>**/selenium/**/rights/*Test.java</include>
                                    </includes>
...
        </profile>


Есть несколько таких профилей, по которым вручную разбиты пакеты.

Круг пятый. Управление исходным кодом.

Мы используем эту модель ветвления git как наиболее адекватную нашим потребностям.
Note: Тесты находятся в одном месте с кодом приложения. Таким образом, отцепляя ветку, разработчик отцепляет и код тестов, это обеспечивает синхронизацию тестов и приложения. Даже к этому очевидному решению мы пришли не сразу.


Круг шестой. Отдельная сборка в CI Jenkins.

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


Полезные плагины для настройки сборок:
  • Clone Workspace, позволяющий избежать рассинхронизации, когда между компилированием кода в родительской сборке и запуском тестов в дочерней кто-то сделал коммит.
  • Xvfb — виртуальный экран.


Запуск тестов:
export DISPLAY='localhost:'$DISPLAY_NUM'.0';
mvn verify -P war-deploy,$TEST_PROFILE -Dext.prop.dir=$WORKSPACE/$PROP_DIR -Dwebaddress=http://localhost:$DEPLOY_PORT/sd -Dselenium.deploy.port=$DEPLOY_PORT -Dcargo.tomcat.ajp.port=$ARJ_PORT -Dcargo.rmi.port=$RMI_PORT

где профиль war-deploy — поднятие приложения с помощью maven-cargo-plugin

Послесборочные операции.
  • Заархивировать артефакты, сохранить отпечатки
  • Jabber и email notification
  • Blame Upstream Committers позволяет отправлять письма коммитерам родительской сборки.


Круг седьмой. Иерархия сборок.

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

Родительская сборка — компиляция проекта.
Дочерние сборки второго уровня — unit-тесты для postgresql, mssql, oracle; статический анализ кода (CPD, PMD, findbugs); сборка war файла (под один браузер для экономии времени) для UI тестов.
Третий уровень — UI тесты в три потока и тесты на миграции.

Типичная третья ветка

Note: Сборка тестирования миграций — простой и эффективный тест, в котором мы берем бекап древней базы с данными и поднимаемся на последнем war файле. Позволяет удостовериться, что пройдут все миграции данных и приложение поднимется на непустой БД.


Восьмой круг, уровень системы непрерывной интеграции

Наша CI — это 4 ветки, в которых программисты могут прогонять тесты, запуская вручную и указывая свой branch. И одна main ветка, запускающаяся по коммиту в develop, от остальных отличающаяся наличием сборок тестирования на всех поддерживаемых СУБД. Не раньше, чем две недели назад каждая ветка располагалась на отдельном сервере (мы выбрали EX4, так как нам не нужна надежность, но критична скорость процессора; эксперименты показали что оптимально — три ноды Jenkins на сервер). После перенастройки виртуальных экранов, портов и настроек СУБД у нас появилось общее пространство нод.
График загрузки выглядит так:


Jenkins promoted builds plugin, позволяющий рисовать красивые звездочки сборкам, все дочки которых прошли без упавших тестов. Он оказался полезней, чем три сотни тестов через интерфейс или тысяча unit-тестов. До него отдельные несознательные ПМы выпускали релизы, невзирая на наличие упавших тестов, уговоры и угрозы не помогали. Но как только у каждого билда появились звездочки — сработала первая сигнальная система и раз в две недели лейтмотив дня — ждем двух звезд. Это вылилось в повышенные требования к скорости исправления ошибок программистами и к качеству кода тестирующей системы — случайные срабатывания теперь стоят дороже.
На эту картинку медитируют ПМы в день релиза


Сборка, использующая Performance Plugin — отслеживание производительности типовых операций, позволяет достаточно быстро обнаружить самые грубые ошибки связанные с производительностью системы.
Результат выглядит примерно так:


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

Note: Еще несколько полезных штук:


Девятый круг, люди и процессы.

Самое сложное в автоматизированном тестировании — добыть хороший кейс. На это уходит до половины времени. Основной поставщик — ручные тестировщики, их кейсы мы съедаем и просим еще, но у них масса другой интересной работы. Поэтому пишем тесты на дефекты, и вообще каждая выполненная таска в JIRA проходит через мой пристальный взгляд — можно ли на нее написать тест? Еще у нас есть Emma Plugin и три сборки сборки подсчета покрытия — для uint-тестов, для UI тестов и суммарное. По этим отчетам мы пишем тесты на API системы. Но для остальной функциональности отчет по покрытию ценности не имеет — специфика нашего ПО такова, что нужно ориентироваться на покрытие тестами не кода, но требований.
Простенький график покрытия


Разработка фичи в контексте автоматизированного тестирования выглядит так:
Отцепить ветку в git. Написать код фичи. Прогнать тесты в ветке. Исправить тесты в ветке. Получить две звезды. Слить с develop.

Принцип, замедливший скорость разработки, повысивший готовность кода к релизу и сэкономивший массу времени моей группе:
Моральным правом на коммит обладает программист, сборка тестирования в ветках которого получила две звезды.
Если программист отцепился от коммита, в котором все тесты проходили, то и его коммит должен обладать таким же свойством.
На первых порах принцип был подкреплен revert'ом коммитов и запретом коммитов в develop.

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

Послесловие


Все, о чем я рассказал — не моя заслуга. Мой вклад в код тестов — треть строк. В CI — четверть конфигов. Над системой тестирования и непрерывной интеграции работали два десятка людей — от техподдержки и тестировщиков до руководителя разработки и аналитиков.

Хочу услышать от вас не только вопросы, но и мудрые советы, полезные настройки и классные идеи. Только помните о моей роли в проекте — я могу что угодно менять в коде, многое в CI, кое-что в процессах. Людей я изменить не в силах.

Если найдется желающий не только дать ценное указание, но например научиться все это делать самому — или научить меня, как нужно правильно работать — добро пожаловать в личку, я ищу коллегу.
Максим Захаров @Wolonter
карма
24,0
рейтинг 0,0

Комментарии (41)

  • +1
    Из описанного у вас достаточно стройная и эффективная система. Есть два вопроса: почему вы не используете распространенный шаблон PageObject (по крайней мере такое ощущение сложилось из ваших примеров) и почему не взяли за основу существующий фреймворк, например Thucydides?
    • +1
      Ответ ниже, промахнулся кнопкой.
  • +2
    PageObject рассматривали, он нам не подошел, так как логика нашей системы — не экраны, а объекты. Но многие подходы взяли оттуда, я слежу за ним.

    Фреймворки даже не рассматривали, хотя и зря. Из-за наивного желания сделать самостоятельно и хорошо. В середине 2011 года я еще не знал, по каким критериям их выбирать, теперь знаю, но у нас уже есть свой. Со всеми его плюсами и минусами.
  • 0
    Про фреймворк спросил, потому что мне очень не нравится подход с хранением шагов в javadoc. Нужно постоянно заботиться об их синхронности с тестом, что нелегко при постоянно меняющихся тестах. Взгляните на систему отчетов Thucydides — там все генерируется из тестового кода, шаги легко повторно использовать, привязка к требованиям через аннотации и куча полезностей. Наличие своего фреймворка не преграда, знаю команды, которые перешли с самописных и очень счастливы.

    Еще пара советов по вашей статье:

    — если вы для каждого элемента имеете ID, то используйте CSS локатор #my_id или на крайний случай оптимизированный XPath локатор id(«my_id») на основе функций XPath

    — EMMA как инструмент для измерения покрытия кода отмирает, в Java мире сейчас принято использовать JaCoCo
    • +1
      Наши тесты пишутся по постановкам и на самом деле меняются достаточно редко. Но — я думал о переходе на готовый фреймворк, Очень уж нравится балансировка тестов, в меньшей степени — синхронизация сценариев и отчеты. Вполне возможно, что это нам светит.

      Xpath ищем по id через нашу обертку, проблем нет.
      За JaCoCo спасибо, не слышал, Скоро посмотрим, что это.
      • 0
        По поводу XPath вопрос не в проблемах, а в компактности записи и скорости работы.
      • 0
        По CSS локатору #id скорость поиска раз в 10 выше, чем через xpath, который вы используете. Я понимаю, что разницу почувствовать сложно, но все же :)
        • 0
          Если бы мы решили перейти, то изменения затронули бы 1-2 класса.

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

          Впрочем, ничего не мешает поставить эксперимент.
  • 0
    Отличаются ли локаторы элементов в зависимости от того, какому браузеру отдается страница? Как обходите данное неудобство?
    • 0
      Если ищут по id, то проблем быть не должно. Они точно во всех браузерах одинаковые.
      Вообще очень круто, когда все тестируемые элементы имеют уникальные идентификаторы. Завидую ТС в этом плане, так как у нас вечная проблема с изменяющейся версткой :)
      • 0
        Да с идентификатором все просто и понятно. Я имел ввиду запущенные случаи. Мы для таких придумали комбинировать XPath селекторы в один с помощью операторов «or» или "|". Но, может, существует какой-нибудь иной элегантный метод?
  • +1
    Функциональные тесты на одном браузере. Под верстку отдельные тесты. Разные действия и проверки.
    • 0
      На каком, если не секрет? Firefox?
      • 0
        Да, в свое время он лучше всего поддерживался.
  • 0
    завидую черной завистью :) Превосходная работа.
    • +1
      Надо завидовать белой и стремиться к лучшему. Эти ребята еще круче сделали, с полным циклом от приемочных критериев до тестов с детальными отчетами по покрытию функциональности. Вот ссылка на их прошлое выступление.
      • 0
        Хороший доклад. Интересно было бы посмотреть на код и CI.
      • 0
        «Слона надо есть по кусочкам» — на моей памяти сделать сразу и по всем канонам — провальная затея. Только когда все осознают, что нам необходимо переходить на новый уровень — тогда дело и двинется.

        Так что для меня пока и описанная система — верх совершенства :)
  • 0
    Круто у вас все! Статья очень интересная, спасибо!

    А как вы параллелите тесты Selenium? Я в эту сторону особо не копал, у нас они выполняются в пределах 30-40 минут, ввиду их немногочисленности. Есть мысли покопать в сторону Selenium Grid.

    В целом у нас считается что тесты через UI имеют наименьшую ценность. Все покрывается Unit тестами, в том числе и бизнес логика. Хотя есть целое API для быстрого написания устойчивых тестов Selenium, но менеджмент не считает это возможностью как-то упростить жизнь ручным тестеровщикам (к слову редко кто воспринимает тесты через UI всерьез, по моим наблюдениям). Может у вас есть весомый комментарий к этому, как повлиять на такое мировоззрение менеджмента?

    Тестируем мы вот это (например): Пример решения на платформе

    А тесты выглядят так (мы завязываемся на серверную реализацию, и управляем UI с точки зрения более высокоуровневых объектов, таких как форма, кнопка, поле ввода, список, вкладка, окно, а не HTML элементов):
    Пример кода
    [Test]
            public void CreateDocumentFromOperation()
            {
                var operationCaption = "LinkedDocDocumentOperation";
    
                var linkedDocEntity = new EntityTestInfo()
                                          {
                                              EntityName = typeof(LinkedDoc).Name, 
                                              EntityCaption = "The linked doc."
                                          };
    
                var grid = Env.Navigation.OpenList(linkedDocEntity);
                
                grid.Toolbar.Click(operationCaption);
    
                var docForm = Env.TabPanel.GetForm(linkedDocEntity.EntityName);
                docForm.GetField<TextField>(ReflectionHelper.GetMemberInfo<LinkedDoc>(f => f.Caption).Name).SetText("Boo-yaa!");
                docForm.Toolbar.Click("Создание", "Завершить операцию {0}".FormatWith(operationCaption));
                docForm.Toolbar.Click("Черновик", "AutoGenerated {0}".FormatWith("Создать SampleDoc из текущей операции"));
    
                var sampleDocEntity = new EntityTestInfo()
                                          {
                                              EntityName = typeof(SampleDoc).Name, 
                                              EntityCaption = "The sample doc."
                                          };
    
                var newDocForm = Env.TabPanel.GetForm(sampleDocEntity.EntityName);
    
                var caption = newDocForm.GetField<TextField>(ReflectionHelper.GetMemberInfo<SampleDoc>(f => f.Caption).Name).GetValue();
    
                Assert.AreEqual("Boo-yaa!", caption, "Кэпшен созданого документа отличается от ожидаемого");
            }
    

    • 0
      А вот пример отчета о падении: www.peeep.us/0586b385
      • +2
        Хм.

        Отчет удобен в том плане, что генерируется автоматически.

        А скажите, кто читает ваши отчеты? Тестировщики? Программисты? Менеджеры? Кто с ними реально работает.

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

        Ну или какие у вас там есть роли?
        • 0
          Есть роли менеджер и разработчик.
          Менеджер смотрит факт падения теста (красный кружочек в TeamCity), блокирует выпуск версии, ставит задачу разработчику разобраться с тестом.

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

          Как-то так. Там кстати есть стектрейс:
          NUnit.Framework.AssertionException: Форма не содержит информацию о зависимостях Expected: True But was: False at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression, String message, Object[] args) at Selenium.GridActionTest.OnlyOpenActionFoms() in d:\Team\BuildAgent\SedDatServAgent2\work\195b9fcc838c17ee\Source\Selenium\GridActionTest.cs:line 105

          Упал на Assert. Если бы была серверная ошибка, то показался бы её трейс.

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

          Т.к. этим ограниченно пользуются, то мне непонятно в какую сторону развивать. Вышло во все по немногу. Конечного потребителя, плотно работающего с этими тестами нет :\ Собственно отсюда мой местами нелепый интерес, посмотреть как оно у белых людей :)
          • +2
            У нас три роли-потребителя.
            АТ пишет тесты.
            Ручной тестер читает кейсы.
            Разработчик чинит приложение.

            Выглядит тоже не очень презентабельно,
            Как-то так:
    • +3
      Параллелим — просто 3-6 дочерних сборок с разным набором тестов. В круге четвертом об этом есть.

      А я со своей колокольни считаю, что менеджмент ваш прав. Мы писали UI тесты, решая определенный класс проблем. Если у вас их нет — зачем вам UI? А если есть — так его и предъявить менеджерам.

      Воспримут всерьез когда вы этими тестами начнете решать проблемы неработающего интерфейса при работающей бизнес логике. Когда UI тесты писать будет проще, чем Unit. Когда UI будут писать все, а юнит только программисты. Например так.
      • 0
        А не думали о настоящей паралельности? Ведь большинство тестов UI не конфликтуют друг с другом, а серверную часть нагружают крайне мало. Выходит что весь пакет тестов можно выполнить за время самого длинного теста.

        Я вообще разработчик View. Мои проблемы тесты UI решают — мы не выпускаем продукт, в котором не запускается интерфейс (а раньше были прецеденты). А какие классы проблем решаете вы? По статье понятно что у вас большой стек кейсов по прикладным и бизнес задачам, но например какие они? Что конкретно решают, кто решил что это важные аспекты, от кого исходила инициатива написать тест кейс, или зафиксировать процесс (кроме ручных тестеровщиков, как я понял из статьи)?
        • +2
          Наши UI друг с другом еще как конфликтуют — специфика приложения плюс большие фикстуры.

          У нас намного больше клиентского кода, чем серверного. Соответственно и ошибки могут проявляться только при отображении данных, работе с данными в интерфейсе.

          Приоритеты кейсов — опыт тестировщиков и мудрые указания аналитиков.

          Имитация бизнес процесса проще решается через нашу тестирующую систему, а не unit тестами благодаря развитым DSL.
          • 0
            DSL в смысле языка для тестов, или в смысле языка для прикладной (бизнес) логики? А в целом понял, спасибо!

            В идеале бы свести написания хотя бы скелета теста к тому, чтоб протыкать аналитику по его же процессу в интерфейса. Тогда, наверно, этим реально начнут пользоваться. Своего рода запись макросов.
            • +2
              Язык для бизнес логики.
        • 0
          Прокомментирую за wolonter насчет настоящей параллельности (я также работаю в этой компании):
          Приближенно: Время выполнения тестов=Общее время тестов / Количество серверов
          Сейчас у нас Время выполнения тестов 2 ч.
          Чтобы сделать прохождение тестов за 15 минут надо всего лишь увеличить количество серверов в 8 раз.

          Также для тестов на Selenium основная загрузка не из-за серверной части приложения, а из-за браузера, который очень интенсивно потребяет память и CPU.
          Предвосхищая вопрос о headless браузере, скажу, что у нас динамическое приложение со сложной клиентской логикой на JavaScript.
  • +1
    Отлично! Спасибо за статью и расскрытия темы с плагинами для дженкинса. Обнаружил пару интересных.

    Меня интересует несколько иной вопрос.
    В дженкинсе тестируются только постоянно присутствующие ветви в git?
    Всмысле если девелопер делает свою ветвь для конкретной фичи то он тестирует «у себя» или есть автоматизация создания дженкинс-джоба?

    П.С. как вы в плане непрерывной развертки (Continuous Delivery)? Какие принципы? Наработки?
    • 0
      Автоматически — только develop.
      Ветвь для фичи можно протестировать, запустив специально созданную для этого сборку. Они уже есть, 4 штуки.

      С ужасом и радостью осознаю, что и к Continuous Delivery мы идем. Медленно, но идем.
      • 0
        А почему с ужасом? :)
        • 0
          Много точек отказа, новые риски, нельзя сейвиться.
      • 0
        Ветвь для фичи можно протестировать, запустив специально созданную для этого сборку

        А подробности не расскорите… я как-то не придумал как к этому лучше подойти…

        и да почему с ужасом? ;)
        • 0
          Ужас от того, что работать придется с боевыми серверами. Не тестовыми.

          А какие именно подробности?
        • 0
          Я также причастен к этой системе, могу прокомментировать:
          * В сборке для develop константа «develop» зашита в настройке job, сборка инициируется по коммиту.
          * В сборках веток используется параметр с нетривиальным именем BRANCH :), сборка запускается вручную.
          • 0
            ок, видимо я просто не работал с параметризируемыми джобами. вот и туплю
  • 0
    Почему вы выбрали Git вместо Mercurial? Рассматривался ли Mercurial в качестве DVCS вообще?
    • 0
      Изначально мы вообще на Subversion начинали.
      Рассматривали Git vs Mercurial, победил Git в силу большей распространенности в нашей компании и того, что не нашли ни одного аргумента против Git
      • 0
        Случались ли у вас проблемы с необходимостью небольших исправлений в уже выпущенных релизах, и в связи с чем как часто вы выполняете git rebase?
        ( Проблема описана здесь: habrahabr.ru/post/123700/ )
  • 0
    Краткий ответ — мы очень часто выполняем git rebase, но это не имеет отношения к необходимости небольших исправлений в уже выпущенных релизах.

    Полный ответ —

    Мы используем модель git flow (можно посмотреть nvie.com/posts/a-successful-git-branching-model/)

    Проблем при необходимости внесения небольших изменений нет. Делается обычно 3 коммитами
    * от тега с версий отцепляется ветка, изменяются номера версий на следующую младшую + SNAPSHOT (мы используем Maven)
    * в этой ветке делается исправляющий коммит (или он забирается из ветки develop с помощью git cherry-pick)
    * убирается из версий слово SNAPSHOT,

    Работа по изменению номеров версий выделена в отдельные задачи Jenkins, разработчику надо лишь сделать исправляющий коммит.

    git rebase делается в рамках работы над задачей
    * разрабтчик отцепляет ветку от develop
    * делает коммит
    * тесты, тесты, тесты
    * перед слиянием в ветку develop выполняется git rebase develop для получения изменений от других разработчиков, разрешаются конфликты.
    * выполняется git merge в ветке develop

    По проблемам автора статьи habrahabr.ru/post/123700/
    1. Мне нужно знать на какой ветке было зафиксировано ab3e2afd для того, чтобы знать, включать ли его в описание изменений будущего релиза.
    Мы описываем изменения по задачам. Все изменения всегда фиксируются лишь в ветке develop. Лишь багофиксовые изменения фиксируются в несколько веток, тогда задачу привязываем к нескольким версиям.

    2. Мне нужно знать какое изменение было первым в ветке «release», потому что я хочу начать новую тематическую ветку с этого изменения в качестве начальной точки так, чтобы я всегда был в курсе происходящего в главной ветке насколько это возможно, и быть уверенным, что смогу выполнить чистое слияние в главную ветку и выпустить релиз.

    У нас главная ветка — develop, мы постоянно делаем в нее слияние. Релиз выпускается не слиянием в главную ветку кучи коммитов и последующим разгребанием проблем, а отцеплением от всегда стабильной (ну почти :)) develop. Выпуск версии — посмотреть, что все тесты проходят и запустить задачу в Jenkins. которая проставит версию.

    3. Мне нужно знать где началась ветка «topic» для того, чтобы я мог сложить все патчи вместе и отослать их своим коллегам для рецензии.

    Для выполнения отдельной задачи создается патч и коллегам высылается ветка, которую надо сравнивать лишь с develop. Тем более мы пользуемся gitlab для рецензирования, достаточно указать ветку с изменениями и ветку, изменения относительно которой надо посчитать.

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