Доклад с SQA Days — Автоматизация тестирования: отбрасываем лишнее и проверяем суть

    Приводим доклад khroliz Игоря Хрола, компания Wargaming, Минск, с конференции SQA Days 15.

    Видео доклада:
    vimeo.com/93944414

    Презентация:
    www.slideshare.net/slideshow/embed_code/33725306#

    Я 8 лет работаю в этой отрасли, и я считаю, что у нас есть проблемы )

    Прежде всего, тестирование считается неинтересной профессией. Что из этого следует? В отрасль приходят неопытные люди, либо недостаточно квалифицированные. Сложную работу, т.к. люди неопытные, некому делать. И получается, что мы делаем несложную работу. А т.к. мы делаем несложную работу, то нам мало платят, т.к. бизнесу мы приносим не так много, как хотели бы. И круг замыкается.




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

    В первую очередь, я призываю вас вспомнить: Кто мы? Software testing engineer. Инженеры. То есть мы не называемся тестерами, тестировщиками и проч., мы — инженеры. И я считаю, что ситуацию как раз могут менять инженеры своими техническими навыками, своими подходами.

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

    Название играет роль.
    • Автоматизация тестирования (мы что-то делаем руками, и мы это автоматизируем)
    • Автоматическое тестирование (что он нас хочет бизнес? чтобы тестирование шло как-то само, автоматом, а мы там логи смотрели и проч. Цель — не автоматизировать тестирование, а сделать тестирование автоматическим)
    • Эффективное автоматическое тестирование

    Рассмотрим абстрактный проект в вакууме.
    Это — модель, она описывает жизненную ситуацию в какой-то мере приближения.
    У нас есть 5 модулей. В первом надо протестировать 5 вариантов, во втором — 8, а третьем — 2 варианта и т.д. Всего надо провести 800 тестов, чтобы убедиться, что все работает.



    Меняем цифры на V: V1 * V2* V3*...*Vn В итоге Vn — средняя сложность модуля. Что такое Vn? Математическая сложность и экспонента. Все строится на том, что задача, имеющая такую сложность решается очень плохо.
    Экспоненциальная сложность. См график.



    Зеленый график, который долгое время держится ниже других, но в какой-то момент уходит стремительно вверх. И когда мы тестируем методом черного ящика, когда мы пытаемся перебрать все варианты, у нас получается, что черный ящик (сложность такого тестирования) — это экспоненциальная сложность. У нас появляется много автотестов, которые работают часами, что мы дальше делаем? Запускаем их параллельно. Мы делим эту сложность на константу. У нас та же экспонента, но чуть-чуть уменьшенная константа. То есть это не решает проблему.



    Разделяй и властвуй

    Давайте посмотрим на нашу задачу с другой стороны.
    У нас было 26 тестов (если тестировать каждый модуль по-отдельности). Но вы скажете, что надо убедиться, что все это вместе работает. Хорошо, давайте протестируем отдельным тест-кейсом каждую связь и прогоним какой-нибудь сквозной сценарий. Получился 31 тест. В итоге, мы экспоненциальную сложность меняем на линейную. И задача становится эффективно решаема. То есть если мы плохо тестировали, и наняли еще 10 тестировщиков, то мы просто распараллелили на 10, а если мы поменяли саму сложность задачи, то не надо так сильно увеличивать ресурсы, требуемые для тестирования.

    Если у нас есть некая абстрактная система, которая имеет по одному варианту, а в конце — 10, если перемножим, то у нас 10 тест-кейсов, а суммарно — 14. А плюс еще связи проверить — 19. Но тесты стали проще. Вместо одного длинного теста, мы пишем 10 маленьких. То есть по факту сложность тестов все равно упрощается.



    “Пирамида” автоматизации.

    Если мы не будем строить наши тесты на этой “пирамиде”, мы получим экспоненциальную сложность нашей задачи, нашего тестирования. Самый мелкий модуль декомпозиции задач — это отдельные классы, отдельные методы. Главное — это декомпозиция задач. Если она — односложна, то мы получаем умножение, если нет, то мы получаем сложение, и в долгосрочной перспективе это будет лучше.

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



    Проект из жизни.
    Siebel, Oracle — жесткое enterprise решение, это был проект по кастомизации, по внедрению мобильного оператору решений на основе технологий Siebel. До того как я присоединился к проекту, тесты писались на QTP. Они представляли из себя такую структуру: там был внутренний API, и тесты ходят, кликают на кнопочки, в середине — черный ящик, и снизу база данных. Достаточно типовая картина.



    Как результат: тесты долгие, тесты нестабильные. Пришла задача: оптимизировать предусловия, которые делаются часами.

    Я написал на java скриптик, который отправляет GET запрос, парсит XML, смотрит XML, отправляет еще один GET запрос и т.д. Тесты стали работать 20 минут и стали хорошо параллелиться.

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

    Вопрос “не видно” решился как в старом анекдоте: “Вам шашечки или ехать?” Вам на тесты смотреть, или надо тестирование проводить? Т.е. тут вопрос: мы хотим автоматическое тестирование или автоматизировать тестирование?

    Структура решения: Java + TestNG + Maven + HttpClient. Положить несколько уровней абстракций, чтобы не работать напрямую, запросы не писать, а работать с сущностями, которые специфичны для Siebel’а.



    Но оказалось, что от браузера не уйти, и часть логики оказалась реализована в самом браузере. Т.е. часть логики была на сервере, а часть логики — в браузере. Поэтому появился Selenium. Но зная о том, что браузер — это долго, нестабильно и непрочно, мы это делали аккуратно. Запускали только тогда, когда реально нужен браузер, когда в тест-кейсе появляется логика, которая реализована в браузере, и которую мы хотим проверить (около 3% сценариев). Также реиспользуется headless-сессия с безбраузерного взаимодействия.

    Дальше декомпозируем эту задачу на какие-то кусочки. Оказалось, что верстка браузера генерируется самим Siebel’ом. И нам не важно, чтобы нажатие на кнопку было реальным, потому что это уже разработано в Siebel’е, это протестировано в Siebel’е, нам надо просто отбросить лишнее и тестировать только то, что мы делали.
    Оказалось, что для разработки браузерной логики есть API (оф. документация Oracle): хочешь что-то сделать в UI — вызови вот тот метод.



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

    Web-сервисы
    JAX-WS — это протокол в Java для работы с web-сервисом. Вместо того чтобы тестировать наш Siebel в контексте всех других систем, мы заглушили все внешние взаимодействия, и когда нам надо было проверить, что из Siebel’а что-то уходит, мы смотрели это не на каких-то внешних системах, а на заглушках. Также мы отправляли java запросы на web-сервисы для проверки исходящей информации.

    Наш сервер состоит из двух частей: Web-сервер и Application-сервер. Web-сервер отвечает за верстку и отсылку ответов, а Application-сервер за логику приложения. И есть доступ к логике через Java Data Bean.И через нее мы получили полный программный интерфейс для создания логики приложений в Siebel’е из Java.

    Тесты производительности.
    Т.к. наши тесты пишутся на java, т.к. они хорошо параллелятся, мы можем просто “натравить” на JMeter наши тесты, и по сути нагрузить систему функциональными тестами. Также тесты суппортились вместе с поддержкой функциональных тестов. Т.е. если для нового билда нужны были новые версии скриптов, мы все равно для проведения функциональных тестов эти скрипты обновляем.



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

    Мне бы не хотелось, чтобы мой доклад воспринимался как инструкция: “Как работать с Siebel “. Мне бы хотелось, чтобы вы глянули на свой стек технологий и посмотрели, что там “под капотом”, т.к. это делает нашу работу качественней и интересней.
    Взгляд на тестирование со стороны реализации системы позволяет:
    • уменьшить сложность самой задачи тестирования
    • уменьшить сложность и длину сценариев
    • увеличить скорость и стабильность работы
    • найти новые области применения автотестов

    Лаборатория тестирования

    33,00

    Компания

    Поделиться публикацией
    Комментарии 10
      0
      «Ловкость рук и никакого мошеничества...»

      Мне кажется автор пишет не о том, как более эффективно решать поставленные задачи, а как ставить более упрощённые задачи.
      Например:
      когда мы пытаемся перебрать все варианты, у нас получается, что черный ящик (сложность такого тестирования) — это экспоненциальная сложность…
      … Хорошо, давайте протестируем отдельным тест-кейсом каждую связь и прогоним какой-нибудь сквозной сценарий. Получился 31 тест. В итоге, мы экспоненциальную сложность меняем на линейную. И задача становится эффективно решаема.


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

      То же самое и в случае перехода с тестов в браузере на тесты через веб-сёрвисы. Это не упрощённое решение задачи — это другая, более простая задача.
        0
        Создал аккаунт и могу ответить.
        На самом деле задача не становится «эффективно решаема», а становится другая задача.

        Задача другая, но суть в том, что она эквивалентна первой. Вместо большого сценария мы пишем много маленьких. Кажется, что их много, но по факту в долгосрочной перспективе их нужно меньше, чем если бы тестировать то же самое end-to-end тестами.
        Плюс мы можем выбросить те вещи, которые заведомо нам не интересно тестировать. Например, third-party вещи, с которыми нам нужно протестировать только совместимость.
        То же самое и в случае перехода с тестов в браузере на тесты через веб-сёрвисы. Это не упрощённое решение задачи — это другая, более простая задача.

        Тут аналогично. Если перестать тестировать в браузере, а тестировать только веб-сервисы, то мы потеряем покрытие, полностью согласен. Но если мы покроем тестами отдельно back-end, отдельно front-end, а затем посмотрим их интеграцию, то суммарный результат будет лучше, чем если мы будем все автотесты писать для системы целиком.
        На моём проекте, о котором я рассказывал, вёрстка была коробочной, поэтому отдельно front-end не имело особого смысла тестировать.
        «Ловкость рук и никакого мошеничества...»

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

        Несколько пруф-ссылок:
        Те же мысли другими словами от Мартина Фаулера
        Доклад с Selenium-конференции, в котором говорят о том, что не надо всё покрывать всё end-to-end тестами через Selenium
        +1
        Поспорю с завершающим слайдом. Совет по повторному использованию кода функциональных тестов не универсален.

        Представьте, подготовка БД завершена, контекст настроен, в системе есть контакт с ИД 42.
        Функциональный тест: открыть карточку контакта с ИД 42, проверить, что в поле Статус значение Действующий, и что значение можно сменить, убедиться, что в логах не появилось ошибок и предупреждений.
        Если распараллелить такой тест на 100 пользователей, то проверим эффективную работу с кешем. А если работа с кешем эффективна, то нагрузка не будет создана. Для того, чтобы кеш испытал шок и рассыпался в пыль, придётся подключить 50 000 пользователей, а имеющееся оборудование может не позволить этого, или бизнесу может быть не интерсна поддержка такого количества, или, вообще, схватим deadlock при разборе логов уже на 10-м потоке.

        Если переписать функциональный тест так: открыть карточку произвольного контакта, проверить, что значение в поле Статус можно сменить на случайное и код ответа сервиса — 200 (OK).
        То тест становится более подходящим для нагрузки.
        Но когда бизнес спросит: «Действующие контакты в новом билде по-прежнему действуют, при открытии карточки в логах нет предупреждений?», — дать положительный ответ, на основе функционально-нагрузочного теста не получится.
          +1
          Подход не универсален, согласен на 100%.
          Случай достаточно уникален, так как редко такое удаётся провернуть. В виду итересности случая он и был упомянут в докладе.

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

          Были сделаны определённые допущения исходя из знаний Siebel'a. Нам было важно реалистично нагрузить базу, так как для Siebel'a чаще всего она узкое место. Поэтому мы в некотором роде пренебрегли реалистичностью нагрузки на web-сервер.

          В общем, нужен был результат и его достигли, затратив на это меньше, чем если бы мы писали отдельные тесты на LoadRunner'e.
          Вспоминается первая заповедь перфекциониста-прокрастинатора: «Лучше сделать хорошо, но никогда, чем кое-как и сегодня»
          0
          Что делать если поднял что-то похожее, оно работает, даже простой как пробка синтаксис для автотестов придумали, писать может практически любой, и вот все вертится, тесты потихоньку пишутся (скучно), параллельно тебе отдают задачки ручного тестирования (еще скучнее) и даже когда появляются задачи оптимизации готового стека тебе тоже скучновато, а иногда они даже не перепадают так как есть другие инженеры.

          Ну в общем сплошная скука.

          При этом времени на разработку чего-то крутого и получение опыта нет и не предвидится (особо нечего пилить по должности) — до разработчика как бы не дотягиваешь. Что делать в таком случае? До смерти пилить какой-то свой домашний «проект» и по капле получать опыт разработчика, или есть более гуманные методы?
            0
            Влюбиться.
              +1
              Направлений для развития полно. Поглядите эти схемы, например.
                0
                Я бы посоветовал критично взглянуть на свою текущую деятельность: всегда есть места, что улучшать и оптимизировать. И чаще всего это те проблемы, которые непонятно, как решать.

                Бывает, для «просветления» нужно сходить в отпуск или съездить на профильную или смежную по тематике конференцию.
                +1
                Как уже было отмечено выше, тестирование каждого модуля по отдельности — это далеко не тоже самое, что протестировать все модули в связке. В сложных проектах между отдельными модулями иногда бывают не тривиальные связи — например, ошибка возникает в модуле 3, при специфических параметров в модулях 2 и 7. Потому для полной гарантии наверное действительно надо совершить полный перебор все возможных комбинаций параметров для всех модулей. Иначе говоря точное решение имеет экспоненциальную сложность. Пара десятков параметров, каждый из которых может принимать несколько значений и задача полного перебора фактически становиться нерешаемой.

                Здесь можно сделать шаг назад, и спросить: а нужна ли нам 100% уверенность? Может достаточно 99% или там 99.9%. В последнем случае достаточно покрыть полными тестами основные сценарии использования. А для проверки случаев экзотических нетривиальных связей между модулями — использовать тесты со случайными (но естественно в разрешенных границах) наборами параметров. Если параметры выбираются действительно случайным образом в каждом тестовом случае, то достоверность такого тестирования растет как квадратный корень от общего числа испытаний. Получаем своеобразное тестирование по методу Монте-Карло. :)
                  +1
                  Про 100% уверенность более чем согласен, немногие из нас делают софт для атомных электростанций.
                  В сложных проектах между отдельными модулями иногда бывают не тривиальные связи — например, ошибка возникает в модуле 3, при специфических параметров в модулях 2 и 7.

                  Наступили на больной мозоль. Если нам надо перебрать варианты работы модуля 3, то модули 2 и 7 не только не нужны, но будут только мешать. Сэмулировать ответ от 2 и 7 гораздо проще с заглушек, чем довести 2 и 7 до того состояния, при котором они самостоятельно нужным образом дёрнут модуль 3.
                  Если стоит задача протестировать модуль 3, то гораздо проще и дешевле во всех смыслах (время выполнения, время на разработку автотеста) сделать это в изоляции от 2 и 7.
                  Немного больше информации по этому поводу — Test Double Pattern
                  Получаем своеобразное тестирование по методу Монте-Карло.

                  Эта штука работает. Знаю несколько удачных случаев, где подобный подход принёс хорошие результаты.

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

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