среда, 16 ноября 2011 г.

Грешки Автоматизатора. Часть 1 и, думаю, не последняя

Не автоматизируйте thirdparty компоненты.

Каждый раз, когда вы пишите автоматический тест на проверку thirdparty компонент, умирает пушистый котенок.

Нет, ну серьезно, зачем писать автоматические тесты проверку получения почты через GMail-морду? Или виджеты типа кнопочки like? Зачем писать автоматические тесты на проверку thirparty процессора кредитных карт? Зачем писать автоматические тесты на авторизацию вашего приложения через твиттер?

Даже не так.

Что вы хотите узнать?

Если GMail перестанет работать, то вы с этим ничего не поделаете. А ваш тест свалится.
Если банк не проведет платеж через кредитную карту, то что вам это даст? Вы узнаете много нового о своем приложении?
А если платеж где-нибудь зависнет? Вы сможете из теста автоматически узнать, где там в банке завис ваш платеж? А сколько ваш тест готов будет ждать? Час? День? Неделю? Или нужно ставить тест в зависимость от состояния счета?
Вы действительно хотите, чтобы ваши тесты зависели, скажем, от того, упадет ли сеть в Берлине? Или получить кучу ложных срабатываний из-за того, что заглючило корпоративную прокси и у вас не открылось окошко твиттера на авторизацию приложения?

Нет.

Конечно, вам может быть и правда нужно проверить почту. Например, когда туда отправили линку на авторизацию. Только не нужно делать работу ребят из Google, занимающихся тестированием вебморды GMail. То же про виджеты facebook. То же про twitter. То же про системы процессинга кредитных карточек.

Делая это вы убиваете котят.

Всегда есть решения проще, к тому же не пахнущие плохим дизайном тестов.
  • Можно проверить почту через POP/IMAP напрямую, используя библиотеки доступные в вашем языке (а они есть почти наверняка)
  • Можно вставить свич и фактически замокировать thirdparty компоненту. Если это сделать аккуратно, то с точки зрения вашего приложения ничего не изменится. Правда тут есть риск выкатить не с тем свичом на продакшен, если деплой у вас идет ручками (в простанородье - "handjob")
  • Можно забраться в базу скриптом и там сделать нужные переключения
У всех этих решений будет пара общих свойств:
  1. Ни одно решение не ставит вас в зависимость от погоды в Ирландии.
  2. Все решения могут сильно ускорить выполнение автоматических проверок.
И это даже не все возможные решения. Можно придумать еще.



На этом с первым грешком автоматизатора все.

Не убивайте котят - пишите хорошие тесты.

26 комментариев:

  1. Смерти пушистых котят и бесполезная работа, как-то связаны?

    А если компания, в которой есть такие бессердечные котобойцы, покупает Gmail, ещё не купила, но в процессе покупки. Котята останутся живы, при написании тестов под 3-rdparty (до завершения сделки) компонент?

    ОтветитьУдалить
  2. Бесполезная работа приближает тепловую смерть вселенной. Так что в любом случае связаны.

    В приведенном частном случае котята умрут, т.к. будет перенасыщение автоматической проверки куска функциональности одного приложения не просто лишними действиями, а лишними действиями по проверке функциональности совершенно левого приложения. Т.е. фактически анти-паттерн Abstraction inversion в действии.

    ОтветитьУдалить
  3. Почему приобретаемое приложение будет совершенно левым?

    ОтветитьУдалить
  4. Потому что это не то приложение для которого пишутся автоматические проверки.

    ОтветитьУдалить
  5. >Нет, ну серьезно, зачем писать автоматические тесты проверку получения почты через GMail-морду?
    >Можно проверить почту через POP/IMAP напрямую

    нет, ну серьезно, зачем проверять корректность работы POP/IMAP на серверах gmail?

    Не стоит смешивать тестирование стороннего приложения А и проверку результата действия, которое наше приложение Б сделало в стороннем.

    Результат проверять надо, и автотесты тут не помеха. А какие влияния допустимы - погода в Ирландии или вкус зубной пасты - это уж от контекста приложений зависит. Если автотест это сделает дешевле, чем живой тестировщик - пусть будет автотест.

    ОтветитьУдалить
  6. Не нужно.

    Тем более не нужно делать это на серверах Gmail.

    А вот общаться со своим приложением через POP/IMAP можно, к тому же будет сильно дешевле (в поддержке теста, в написании теста и т.д. и т.п.) чем прикручивать тестирование морды Gmail. К тому же в рамках CI тесты общающиеся с Gmail прямо с билд агента это нонсенс.

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

    А про "дешевле" отдельная история. "Дешевле чем живой тестировщик" это недостаточное требование. Надо понимать что именно делает и зачем. Более того - ничего нового он не сделает. Это накладывает определенные ограничения на дизайн. Определенные ограничения на область применимости. Иначе мы грохнемся в пучину Automation Bias.

    ОтветитьУдалить
  7. А мой комментарий куда пропал? :(

    ОтветитьУдалить
  8. Придется еще раз написать. :( Так вот я не соглашусь с категоричностью автора статьи. У этой медали есть две стороны.

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

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

    Надо искать баланс между различными видами тестов и не отвергать полезную информацию.

    ОтветитьУдалить
  9. Не знаю куда пропадал. В почте был, а в интерфейсе нигде и сдела нет. Видимо опять гугль данные профукивает.

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

    ОтветитьУдалить
  10. Мониторинг это полдела. Вторая половина - это реальное взаимодействие вашего приложения. Как оно обрабатывает разные реальные ответы от стороннего сервиса. На каждый вариант поведения заглушки нужно добавлять один тест на реальный сервис на это же поведение. Это может быть вызов API напрямую или отдельный функциональный тест. Их можно складывать и запускать отдельным набором тестов по отдельному расписанию.

    И мониторинг никто не отменял. Его тоже лучше добавить. :)

    ОтветитьУдалить
  11. Просто мух лучше отдельно, а котлеты отдельно.

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

    С другой стороны состояние стороннего сервиса и изменения API достаточно просто мониторить.

    Давайте рассмотрим пример - на продакшене есть версия, протестированная под заданное API, например. Но тут кусок API отвалился или стал работать некорректно с нашей точки зрения. Что дальше?

    Дальше мы хотим:
    1. Узнать об этом как можно быстрее (мониторинг)
    2. Чтобы наше приложение не сложилось как карточный домик (хорошая заглушка переточенная под нужды продакшшена)

    А автоматические проверки тут не спасут. Придется все равно выяснять что там поменялось/сломалось в API и перепиливать их все.

    Свичи в конфигах на различные компоненты системы это нормальная практика в DevOps. Говорят помогает очень всякие катастрофы разгребать.

    ОтветитьУдалить
  12. Серёга, не хочешь к нам, написать хорошую заглушку :)

    ОтветитьУдалить
  13. А вам зачем? У вас коробочный продукт, вы по идее сами уже давно должны были годные конфиги сделать.

    ОтветитьУдалить
  14. Добрый день.

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

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

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

    ОтветитьУдалить
  15. Увы пишут. Вы только что описали, например.

    Если вам надо gmail - есть способы работать с gmail не затрагивая GUI, т.е. чисто почтовыми протоколами.
    Более того - чем принципиально гугловский почтовый сервер отличается от любого другого? Да ничем.

    Я не вижу чем этот тест может быть полезен. Я вдвойне не вижу пользу если мы будем привязываться к GUI.

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

    Если гугл нарушает RFC почтовых протоколов, то это проблемы гугла. Мы можем зарепортить им баг, но к нашей системе это никакого отношения не имеет.

    Если наша система нарушает RFC почтовых протоколов, то зачем нам собственно гуглопочта для этого?

    При любом сценарии тест избыточен, содержит лишние, ничем не ценные для нас points of failure, т.е. в целом плохой. Более того - предпосылка для этого теста тоже плохая, т.к. тест дополнительно проверяет множество вещей кроме заявленных. Это верный путь в Automation Bias.

    ОтветитьУдалить
  16. Не понимаю, как тут цитировать. Я очень не согласен с двумя вещами:

    > Если гугл нарушает RFC почтовых протоколов, то это проблемы гугла. Мы можем зарепортить им баг, но к нашей системе это никакого отношения не имеет.

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

    > тест дополнительно проверяет множество вещей кроме заявленных.

    Тест проверяет ровно одно - что письмо, отправленное пользователем, попадет к нам. Где же тут избыточность?

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

    Проверка работы гугла это уже скорее мониторинг, а не автоматические тесты. И требования к нему лучше предъявлять как к мониторингу, а не как к автоматическим тестам. И уж точно не стоит такое добавлять в CI.

    > Тест проверяет ровно одно - что письмо, отправленное пользователем, попадет к нам. Где же тут избыточность?

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

    Более того - все это отличается от формулировки "письмо, отправленное пользователем, попадет к нам" как минимум большей детализацией. Т.к. реально тест проверяет, что "письмо, отправленное пользователем через вебморду _гуглопочты_, попадет к нам". Разницу чувствуете?



    Ну и обратно к самому тестовому случаю:
    Если гуглопочта начнет отклоняться от стандартов, то это по многим аукнется. Если это не вредительство со стороны гугла, то в ряде случаев гугл пострадает очень сильно. А вот ряд (не все, согласен) кампаний вполне переживет, если почта от гугла к ним не ходит или ходит не так. Но это уже вопрос управления рисками.

    ОтветитьУдалить
  18. "письмо, отправленное пользователем через вебморду _гуглопочты_, попадет к нам"

    "письмо, отправленное пользователем, указанным нами способом через вебморду _гуглопочты_, попадет к нам"

    "письмо, отправленное нашим конкретным пользователем, указанным нами способом через вебморду _гуглопочты_, попадет к нам"

    Там можно еще долго продолжать). Вопрос рисков неконтролируемой среды. Мы можем словить минорный баг гугла, навроде того, когда он дропнул почту 0,04% своих пользователей. Ложное срабатывание и мы заколебемся разбираться почему именно или станем причиной ложной тревоги.

    ОтветитьУдалить
  19. > Если нам так важно что гугл отклоняется от стандартов, то надо тестировать именно это, а не накручивать лишнюю логику на имеющиеся тесты. KISS хороший принцип, особенно для автоматизации.

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

    Про избыточность спорить не буду, будем считать, что я просто плохо сформулировал задание.

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

    ОтветитьУдалить
  20. Полностью поддерживаю автора.

    Не понимаю, зачем люди так извращаются, когда для отсылки почту достаточно использовать какую-нибудь утилиту типа mailx или sendmail или написать что-нибудь свое используя javamail или другие библиотеки (думаю почти для каждого ЯП есть). Если охота проверить именно гугль - ставьте SMTP сервер smtp.gmail.com и проверяйте. Но лучше свой сервак поднять и от него спамить внутри локалки.

    ОтветитьУдалить
  21. > Но как это тестировать? Какие отклонения от стандартов нам критичны, а какие нет? Полностью тестировать чужую почту - это как-то совсем чересчур. К тому же бывают чужие важные сервисы куда сложнее почтовых и с менее четко описанной функциональностью.

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

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

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

    > Про управление рисками - ну да, я примерно это и хотел сказать с самого начала. По сути, мне не понравилась категоричность исходного поста "так делать нельзя", я и пытался описать ситуацию, когда так делать все-таки приходится.

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

    ОтветитьУдалить
  22. > Т.е. мы написали приложение, которое работает с этими сервисами, но не знаем каким волшебным способом наше приложение работает с этими самыми сервисами? Простите, но это абсурд.

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

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

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

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

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

    ОтветитьУдалить
  23. > Однако, мы можем не знать точных условий на входные данные и то, какие отклонения важны, а какие нет.

    Да-да. Именно в таких условиях и реверсилось. Главное в данной ситуации было не абсолютно корректно работать (это невозможно было в принципе), а вовремя обнаружить проблемы, минимизировать потери и быстро устранить проблему.
    Оказалось не сильно сложно в основном потому, что одну половину системы моделировать было легко, т.к. это в любом случае SUT, а не третья сторона.

    Так что проблема заглушки она не в сложности данных, а в сложности моделироватья этих данных (это зачастую никак не зависящие друг от друга вещи).
    А с мониторингом еще проще. Там фактически матмоды и еще по мелочи. Сначала делим на "хорошие" данные, которые мы умеем принимать, и "плохие" данные, которые по какой-то причине не скушались. Дальше пытаемся что-то систематизировать в "плохих".
    Частично обе проблемы решаются на стадии работ над отказоустойчивостью SUT, когда мы стараемся корректно обрабатывать ошибки, например.

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

    Я понимаю, что иногда формат может оказаться слишком сложным для моделирования, но я такое практически не встречал. По большей части сервисы работающие как Thirdparty как правило стараются не сильно усложнять жизнь себе и сторонним разработчикам. И gmail уж точно не тот пример, который стоит приводить в данном случае. Пока в голову приходят только случаи, когда thirdparty сервис изначально вообще таковым не собирался быть, но такой пример еще надо постараться найти. А уж найти такой, чтобы еще и сложно решалось - вдвойне.

    Когда я работал над BI продуктами у нас была в свое время проблемма с базами данных. Предполагалось, что наш продукт будет способен скушать схемы заданного числа СУБД и выстроить над ними семантическую модель с которой бы дальше работал. Сначала мы работали на примерах от вендоров СУБД и там проблем витоге небыло. Потому мы начали моделировать схемы более разнообразные схемы, нашли ряд дефектов у нас и у вендоров. Насколько знаю сейчас пользователи проблем в этой части инструмента не испытывают.

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

    Ага, конечно, я это и имел в виду.

    > А с мониторингом еще проще. Там фактически матмоды и еще по мелочи. Сначала делим на "хорошие" данные, которые мы умеем принимать, и "плохие" данные, которые по какой-то причине не скушались. Дальше пытаемся что-то систематизировать в "плохих".

    Да, все так. Только я бы не назвал это "еще проще". Не все данные можно даже обработать простыми средствами и приходится писать специальный софт для обработки и выделения закономерностей.

    > но такой пример еще надо постараться найти. А уж найти такой, чтобы еще и сложно решалось - вдвойне.

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

    ОтветитьУдалить
  25. В примере с социальной сетью я не сомневаюсь, что сделать это (смоделировать данные) в принципе возможно. Вопрос только в ресурсах, которые у нас на это есть.

    ОтветитьУдалить
  26. Про примеры верю. Сам, увы, хорошие привести не могу по тем же причинам. Но там все зачастую бывает настолько сложно, что со стороны thirdparty вообще дергать ничего нельзя.

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

    Про ресурсы в принципе очевидно. В этом плане в рамках дизайна тестов нас скорее интересует вот это: http://goblingame.blogspot.com/2011/10/blog-post_17.html

    ОтветитьУдалить