company_banner

Тестирование с инструментами Microsoft — полевой опыт

    Эта статья создана нашими друзьями, партнерами из компании Лаборатория Касперского и описывает реальный опыт использования инструментов тестирования от Microsoft с рекомендациями. Автор — инженер по тестированию в Лаборатории Касперского, Игорь Щегловитов.


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

    Команда состоит из разработчиков и тестировщиков (примерно в соотношении 1 к 3). Разработчики пишут код на C# и практикуют TDD и DDD, благодаря этому код получается пригодным для тестирования и слабосвязанным.  Тесты, которые пишут разработчики, запускаются либо вручную из Visual Studio, либо автоматически при сборке билда на TFS. Для запуска билда у нас установлен триггер Gated Check-In, таким образом он запускается при чекине в Source Control. Особенностью данного триггера является, то что если по каким-то причинам (будь то ошибка компиляции либо тесты не прошли) билд падает, то сам чекин, который запустил билд не попадает в SourceControl.
    Вы, наверное, сталкивались с утверждением, что код протестировать сложно? Некоторые прибегают к парному программированию. В других компаниях специально выделены отделы тестирования.  У нас же это обязательное код-ревью и автоматизированное интеграционное тестирование. В отличие от модульных — интеграционные тесты разрабатываются специально выделенными инженерами по тестированию, к которым отношусь и я.

    Клиенты взаимодействуют с нами через удаленное SOAP и REST API. Сами сервисы основаны на WCF, MVC, данные же хранятся в Azure Storage. Для надежности и масштабирования длительных бизнес-процессов используются Azure Service Bus и Azure Cloud Queue.

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

    Интеграционные тесты, также как и основной код, разрабатываются на C#. Имитируя действия конечного потребителя, они проверяют бизнес процессы на сконфигурированных и запущенных сервисах. Для написания этих тестов используется Visual Studio и фреймворк MsTest. Разработчики используют то же самое. В процессе тестировщики и разработчики производят взаиморевью кода, благодаря чему члены команды могут всегда говорить на одном языке. 

    Тестовые сценарии (тест-кейсы) живут и управляются через MTM (Microsoft Test Manager). Тест кейс в данном случае — такая же сущность TFS, как баг или таск. Тест-кейсы бывают ручными или автоматическими. В связи со спецификой нашей системы, мы используем только вторые.

    Автоматические тест кейсы связываются по полному CLR наименованию с тестовыми методами (один кейс — один тестовый метод). До момента появления MTM (Visual Studio 2010) я запускал тесты как модульные, ограничиваясь студией. Было сложно строить отчеты по тестированию, управлять тестами. Теперь это делается напрямую через MTM.

    Появилась возможность объединять тест кейсы в планы тестирования, а внутри планов строить плоские и иерархические группировки через TestSuite.

    У нас Feature Branch разработка, т.е. крупные доработки делаются в отдельных ветках, стабилизационных и релизных. Под каждую ветку у нас создан тест план (чтобы избежать хаоса). После завершения стабилизации в Feature Branch ветке, в основную ветку переносится код, а тесты переносятся в соответствующий ей тест план. Тест-кейсы очень легко добавлять в тест-планы (Ctrl+C Ctrl+V, либо через TFS query).

    Немного рекомендаций. Лично я стараюсь для каждой ветки разделять стабильные тесты от новых. Это легко делать через TestSuite.  Особенность здесь в том, что стабильные (или регрессионные) тесты должны проходить на 100%. Если у вас не так, то стоит задуматься. Ну, а после того, как новый функционал становится стабильным, то соответствующие ему тесты просто переносятся в регрессионный Test Suite.

    Лично для меня одним из самых скучных и рутинных процессов было создание тест-кейсов. Процесс разработки автотестов у всех разный. Кто-то в начале пишет подробные тестовые сценарии, а потом на основе создает авто тесты. У меня наоборот. Я пишу в коде (в тестовом классе) тесты-пустышки (без логики).  Потом уже идет реализации логики, архитектуры компонент тестирования, тестовых данных и так далее.

    После того как тесты созданы, их надо перенести в TFS. Одно дело, когда тестов штук 10, а если 50 или 100, придется потратить кучу времени на рутинное заполнение шагов, связывания каждого нового тест-кейса с тестовым методом.

    Для упрощение данного процесса Microsoft придумал утилиту tcm.exe, которая умеет автоматически, создавать тестовые сценарии в TFS и включать в план тестирования.  Данная утилита имеет ряд недостатков, в один тест план почему-то нельзя добавить тесты из разных сборок или для тест-кейса нельзя задать шаги и нормальное название. Кроме того, сама утилита появилась сравнительно недавно. Когда ее еще не было —  мы создали самописную утилиту которая автоматизирует процесс создания тестовых сценариев. Также разработаны специальные кастомные атрибуты TestCaseName и TestCaseStep, для задания имени и шагов тестового сценария.

    Сама утилита может как обновлять, так и создавать тестовые сценарии, включать в нужный план. Утилита может работать в silent режиме, ее запуск включен в Worfklow TFS билда. Таким образом она запускается автоматически сама и добавляет либо обновляет существующие тестовые сценарии. В результате мы имеем актуальный тест-план.
     Статус прогона тестов в тест-плане (что эквивалентно качеству кода) виден в специальных отчетах. В TFS есть набор шаблонов готовых отчетов, которые на основе данных OLAP кубов строят диаграммы по статусам тест кейсов и тест планов. Но у нас отчет самописный и упрощенный. Мы сделали его таким, чтобы каждый, кто на него бы ни посмотрел, сразу все понял. 

    Вот пример:


    Особенностью отчета является то, что он строится не на основе кубов, которые перестраиваются не синхронно и могут содержать еще не актуальные данные, наш отчет использует данные, которые подтягиваются напрямую через МТМ API. Таким образом мы в любой момент времени получаем актуальный статус плана тестирования.
    Отчет строится в HTML формате и рассылается на всю команду через SmtpClient. Делается это все с помощью простой утилиты, запуск которой включен прямо в Workflow билда: скачать утилиту.
     
    Кроме управления тестовыми сценариями, МTM используется и для управления окружениями тестирования и настройкой агентов, запускающих тесты. Чтобы ускорить выполнение тестов (здесь идет речь о тестах, проверяющих длительные асинхронные бизнес процессы) мы используем 6 агентов тестирования, т.е. за счет горизонтального масштабирования агентов у нас достигается параллельность выполнения тестов.
     
    Сами по себе интеграционные авто тесты можно вручную запускать как через MTM, так и через Visual Studio. Но ручной запуск происходит во время отладки (либо тестов, либо кода). У нас в команде почти на каждый баг заводится воспроизводящий тест. Далее баг вместе с тестом передается в разработку. И разработчикам проще смоделировать проблемную ситуацию и исправить ее.

    Теперь о процессе регресса.

    В нашем проекте есть специальный билд, который инициирует полный прогон тестов, он запускается по триггеру как Rolling Build. Т.е., если прошел успешно быстрый Gated Checkin билд, то запускается Rolling Build. Особенность данного билда – в один момент времени собирается максимум один билд.

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

    Если все прошло успешно, то запускаются специально написанные Power Shell скрипты, которые деплоят пакет собранных сервисов в Azure. Для управлением деплоем используется REST API Azure. Сам деплой осуществляется на промежуточное развертывание облачной службы. Если деплой прошел успешно и роль запускается без ошибок, то стартую скрипты проверки конфигурации. Если все хорошо, то происходит переключение ролей (промежуточное развертывание становится основным) и запускаются сами интеграционные тесты.
    После прогона тестов на всю команду рассылается письмо, которое содержит отчет о  статусе выполнения тестов.

    Прежде чем писать тесты, классические модульные, так и интеграционные я рекомендую ознакомиться с книгами The Art of Unit Testing и xUnit Test Patterns: Refactoring Test Code
    Эти книги (лично я люблю первую), содержат большое число советов и приемов, как надо и не надо писать тесты на любом xUnit фреймворке.
     
    Я бы хотел закончить свою статью перечислением основных принципов написания кода авто-тестов в нашей команде:

    • “Понятное” CLR имя тестового метода. Здесь основная идея заключается в том, что посмотрев на одно название теста, программист может понять, что он проверят, с какими данными, и что ожидается. Имя теста должно состоять из 3х частей, разделенных нижним подчеркиванием, и выглядеть примерно так: FunctionalUnderTest_Conditions_ExpectedResult
    • Строгая структура теста — Arrange-Act-Assert. Подготовка данных, некое действие и проверка. Смысл такой, что тесты должны иметь максимально простую и компактную структуру, по сути состоящую из 3х описанных ранее шагов. Благодаря этому, достигается хорошая читабельность, а также простота поддержки и отладки тестов.
    • Тесты не должны содержать условной логики и циклов. Здесь без комментариев, если бы у нас были такие тесты, то пришлось бы писать тесты на тесты.
    • Один тест – одна проверка. Часто люди вставляют в свои тесты кучу Assert`s, а потом не могут понять, на каком именно из них тест упал. Старайтесь делать в тесте одну проверку, это очень упрощает отладку и поиск проблем. Здесь немного добавлю, что в некоторых случаях, после одного действия, требуется проверить состояние нескольких объектов, причем состояние каждого из них характеризируется множеством свойств. В таком случае целесообразно сделать два теста, а проверки всех свойств вынести в отдельные методы хелперы с нормальным именем, так чтобы вместо Assert.IsTrue вызывать ваш переопределенный ассерт. Еще, во время написания проверок на свойства, старайтесь писать читабельные сообщения ошибки. Здесь я просто привел пример. На самом деле существует масса различных шаблонов. 
    • Тесты, даже интеграционные, должны быть быстрыми. Старайтесь писать их с учетом этого. Я видел множество примеров тестов вот с такими вставками: Thread.Sleep(60000). Избегайте этого. Если вы ожидаете выполнения какого-то асинхронного действия, то прикиньте, как можно отследить его выполнение (например, асинхронный процесс меняет состояние в базе и тп). Или может стоит разбить тест на несколько?
    • Возможно вы это пока не делаете, но соблюдайте потокобезопасность в тестах. Т.к. в дальнейшем вы скорее всего придете к тому, что захотите ускорить выполнение тестов и чуть ли не одним из способов достижения данного ускорения окажется многопоточность.
    • Независимость. Тесты не должны зависеть от порядка их выполнения, да и друг от друга. Пишите тесты с учетом этого принципа. Старайтесь делать очистку тестовых данных, так как часто они приводят к различным непредвиденным последствия и замедляют выполнение тестов.

    Ну и напоследок хочу добавить, что правильные тесты действительно делают разработку быстрой, а код качественным.
    Microsoft
    382,72
    Microsoft — мировой лидер в области ПО и ИТ-услуг
    Поделиться публикацией

    Комментарии 13

      0
      "… В команде, занимающейся разработкой серверной облачной инфраструктуры на облачной платформе Microsoft Azure"

      А для чего конкретно используется Azure?
        +1
        Мы размещаем наши сервисы в Azure, потому что это удобно)
        Относительно простой деплой сервисов, удобная инфраструктура для горизонтального масштабирования, встроенные средства диагностики и много-много всего)
        +1
        Может вам будет полезной вот такая ссылочка на open-source: github.com/allure-framework/allure-mstest-adapter Это набор инструментов для того, чтобы сгенерировать Allure отчет по TRX файлам.
          +1
          Спасибо)
          Посмотрю обязательно.
          На самом деле я не вижу ничего сложного в написании парсера TRX файлов. Это же обычный XML с результатами тестов. Для простого отчета по результату прогона тестов действительно возможно достаточно любого парсера.
          Но, TFS база, откуда мы вытаскиваем результаты тест кейсов хранит очень много полезной информации — в частности это история прогона (по этой истории можно предположительно понять какой именно чекин сломал тест). Также при необходимости туда можно записывать intelliTrace и другую отладочную информацию, которая иногда требуется для поиска проблемы.
            0
            Парсер XML написать несложно. Сложнее написать хороший отчет. :)
          +1
          Тестировщики должны быть нацелены на разрушение в первую очередь

          Спорное утверждение. Зависит от того какие это тестировщики. Как по мне, так в первую очередь проверять надо, что всё работает в соответствии со спецификациями, а что не покрыто спецификациями, работает как минимум предсказуемо, а дальше уже ломать, крушить, заводить тикеты.
            +1
            Спецификация это очень общее понятие. Здесь все зависит от методологии. Стоимость исправления ошибок в спецификации (или в любой другой документации) велика по сравнение с банальными ошибками в коде.
            По своему опыту могу сказать, что тестировщики, как минимум, должны критически относится к документации, а не принимать ее как есть.
            Если мы говорим о спецификации интерфейсов (low level design), то следует проверять ее на соответствие бизнес спецификации и так далее. Есть даже такой отдельный вид тестирования как статическое, задача которого не только проверять качество кода, но и документацию.
            +1
            Спасибо за интересную статью. Используете ли вы Fuzzy тесты? Что о них думаете?
              0
              У нас строго типизированное публичное апи, которое и так фильтрует практически весь «мусор».
              Специально ни каких Fuzzy фреймворков мы не используем, но всегда пишем отдельные тесты проверяющие корректную обработку «не правильных входных данных».
              Опять же все зависит от системы.
              Года 3 назад читал книгу, «Исследование уязвимостей методом грубой силы» (вроде такое название), так там приводили примеры уязвимостей системы, которая написана на C или каком то подобном языке- и что при определенных входных данных в системе возникало переполнение буфера, которое открывало злоумышленнику возможность исполнения произвольного кода.

              в общем мое мнение- тесты на обработку некорректных данных, исключительных ситуаций (как минимум описанных в спецификации интерфейсов) должны быть включены в регресс.
              +1
              А скажите пожалуйста, какую литературу по тестам от MSTest стоит почитать? а то у меня имеется достаточно не мелкого объема приложение, но в списке тестов до сих пор висит один штатный тест и я не знаю, как к нему подойти дальше и понимаю что без тестирования уже сложно :(
                +1
                Кроме MsTest есть еще множетсво xUnit фреймворков. И все они очень похожи) Начните с моей любимой книги «Art of unit testing». Книга универсальная и читается очень легко). А по MsTest есть куча документации в msdn.
                  0
                  Ну хочется реальных примеров, если честно, как под десктопные/современно-универсальные так и под MS MVC
                0
                Если честно я не занимаюсь тестированием десктопных или веб приложений. Я же правильно понял, что вы имели ввиду их? Просто на базе MVC можно реализовывать простые REST API сервисы)
                Если я прав, то вам надо прочитать:
                habrahabr.ru/post/97012/
                msdn.microsoft.com/en-us/library/dd286726.aspx
                msdn.microsoft.com/en-us/library/dd286681(v=vs.100).aspx

                После этого у вас появится представление как реализовывать CodedUI тесты на базе MS Test.
                Там все довольно просто — записываете некоторую последовательность действий и проверок, а фреймворк сам генерирует код. Я рекомендую его использовать только в качестве примера, т.к. этот автосгенеренный код мягко говоря вообще не поддерживаемый.
                Но на базе CodedUI фреймворка, можно писать вполне хорошие тесты. В идеале, разработчики UI интерфейса также должны согласовывать изменения своих компонент с разработчиками UI тестов — это обеспечит надежность самих тестов. К сожалению это не всегда выполнимо. Особенно в тех случаях когда тесты и код разрабатываются разными командами или компаниями. В результате, иногда, я знаю сам лично несколько примеров, стоимости поддержки UI автотестов может стать очень высокой и от них придется отказываться.

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

                Самое читаемое