Тестирование в стиле TSA

Original author: David Heinemeier Hansson
  • Translation


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

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

«Но что плохого в избыточном тестировании, Фил, разве ты не хочешь, чтобы твой код был безопасным? Если мы поймаем очередной баг до попадания в production, то разве оно того не стоит?» Да ни хрена оно того не стоит, и не зовите меня Фил. Из-за таких вот рассуждений мы и получили TSA и то как они сливают миллиарды на ощупывание яиц и конфискацию книпсеров.

Примечание переводчика: TSA — Transportation Security Administration — Управление транспортной безопасности США, которое люто ненавидят за феноменальную дотошность при досмотре (в частности в аэропортах).


Тесты не бесплатны


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

Подумайте об этом так: какова цена предотвращения бага? Если вам нужно написать 1000 строк теста, чтобы отловить случайное удаление Бобом строчки «validates_presence_of :name», то оно того стоит? Естественно нет (да, да, если вы работаете над системой контроля запуска ракет на Марс и ракета полетит в Белый Дом, если забыть указать ей имя, то можете это тестировать — но это ведь не ваш случай, так что забудьте).

Проблема выявления избыточного тестирования в том, что сложно придумать броский термин для этого. Нет ничего столь же компактного как test-first (тест первым), red-green (красный-зеленый) или других секси-терминов, которые помогают продвигать разработку через тестирование к ее заслуженному месту в центре сцены. Тестирование только того, что необходимо, требует тонкого подхода, опыта и немалой интуиции.

Семь «НЕ» тестирования


Все тонкости можно легко объяснить за 2 часа ужина с просвещенными собеседниками, однако в посте для этого не хватит места. Поэтому давайте подкинем дров в огонь дискуссии — я просто приведу список мнений без всяких тонкостей о том, как вам стоит тестировать ваше типичное Rails-приложение:
  1. не стремитесь к 100% покрытию тестами;
  2. соотношение кода к тестам выше 1:2 уже попахивает, выше 1:3 — воняет;
  3. если тестирование отнимает больше 1/3 вашего времени, то скорее всего вы делаете это неправильно; вы определенно делаете это неправильно, если тестирование отнимает больше половины вашего времени;
  4. не тестируйте стандартные ассоциации, валидации и скопы ActiveRecord;
  5. приберегите интеграционные тесты для проблем, возникающих при объединении отдельных элементов (т.е. не используйте интеграционное тестирование для вещей, для которых можно использовать юнит-тесты);
  6. не используйте Cucumber, если только вы не живете в волшебном королевстве не-программистов-писателей-тестов (или пришлите мне бутылочку волшебной пыли, если вы все-таки там!);
  7. не заставляйте себя писать тест первым для каждого контроллера, модели или шаблона (мое обычное соотношение — 20% тестов первыми и 80% тестов после).

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

Но вернемся к главному. Мы должны коллективно решить, что тестирование в стиле TSA (театральное качество покрытия тестами) полностью дискредитировало себя, прежде чем мы сможем двигаться дальше. Очень мало приложений являются настолько критически важными, что действительно требуют тестировать все.

Говоря мудрыми словами Kent'а Beck'а, человека, который больше всех способствовал популяризации разработки через тестирование:
Мне платят за код, который работает, а не за тесты, поэтому моя философия заключается в том, чтобы тестировать настолько мало, насколько это возможно для достижения нужного уровня уверенности (подозреваю, что мой уровень уверенности выше, чем стандарты индустрии, но возможно это просто мое эго). Если я обычно не допускаю ошибок определенного типа (как передача неверных аргументов в конструктор, например), то я не тестирую это.
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 32

    +1
    Да-да, хороший пост. Тот же Ryan Bates в своем твиттере написал, что 90% всех его багов ловят acceptance тесты. Пост очень добавляет рационализма в словечки типа TDD и BDD.
      0
      Можете скинуть ссылку на его твит этот? Очень нужно. Спасибо!
      –6
      Моё мнение — тесты должны писать ребята из отдела QA. Это их работа — четко знать что надо покрывать тестами, а что избыточно. И именно у этих ребят свежий взгляд на ваш код.
        0
        В некоторых конторах практикуется программирование на пару с QA, и последний сразу по ходу дела показывает, в каких местах код может сломаться и какие тесты написать надо.
          +7
          Не нужно путать функциональные/приемочные тесты и юнит-тесты, на которых строится TDD.
            –14
            TDD вообще глупость — больше работы, больше ошибок. Тестами должен быть занят отдел QA.
              +3
              О, сразу видно, кто тут вообще не знает, что такое TDD, да и вообще юнит-тестирование в целом.
            +3
            Видимо вы плохо знакомы с подходом TDD. Данный подход подразумевает круговой процесс:
            тест-код-рефакторинг — тест…
            И реализоваываться он должен одним человеком. Соответсвенно если отдать этот процесс ребятам из QA, это будет уже не TDD, а Unit tests.
              0
              Можно проще объяснить: программист может написать такой код, который протестировать невозможно или очень тяжело, тогда тестировщик хрен напишет тест к нему и вообще не часто встречаются QA и неплохой программист в одном лице.
            0
            Обычно имеет смысл писать тест, который проверяет базовую функциональность вновь добавляемой фичи — чтобы просто не поднимать весь сервер и не проверять ручками через браузер.

            А далее, при поддержке и развитии, основное правило — каждый обнаруженый баг должен быть покрыт новым тестом (по возможности).

            Поддержка самих тестов не отнимает много времени — они редко ломаются, и если ломаются, то по делу. Вот запуск всех тестов — это да… у нас уже минут 20 занимает полный прогон. Но их, собственно, должен билд-сервер автоматом гонять время от времени.
              +2
              «Запах медленных тестов». Разбейте тесты на несколько групп — типа «быстрые», «средние», «медленные». Разработчики будут запускать каждый раз у себя быстрые тесты. Средние могут запускать пару раз в день. Ну а группа медленных тестов пусть запускается при выкладке кода на тестовый сервак.
              Ну и совсем уже капитанство — отрефакторьте медленные тесты чтобы они были пошустрее.
                0
                да понятно все… так и делаем… конкретно на рефакторинг просто времени особо нет… а еще там есть ряд тестов, которые тупо в цикле бегут по базе и проверяют интерпретируемые сценарии — сложность там квадратичная, и тормоза из-за интерпретатора, и один такой тест легко минуту занимает, и как его оптимизировать, не совсем ясно… так что только деление на медленные и быстрые тесты, да…
              0
              А что, правда, что Cucumber так плох? Как раз собирались начать его использовать? У кого-нибудь есть опыт работы с ним?
                0
                DHH просто не любит ни RSpec ни Cucumber. Это его личное )
                Но я, например, тоже не люблю.
                Кто-то любит…
                На вкус и цвет…
                  0
                  Да, я тоже был весьма удивлен от его слов: «It makes me sad when I see people who are using Rspec and Cucumber»

                  Rspec очень мощный инструмент для тестирования. Cucumber все таки на любителя больше
                    0
                    Я вот так и не понял в чем принципиальное отличие RSpec от его любимого Test::Unit? То что текст иначе пишется? Если использовать чисто для тестирования, то две совершенно похожих тулзы.
                      0
                      Основное отличие в том, что Rspec это DSL, а Test:Unit скорее plain ruby
                        0
                        Ок. Это как раз не фича RSpec, в DSL труднее разобраться.
                        Ну а в чем принципиальное отличие assert от should?
                          0
                          Лично для меня, тесты на Rspec более читабельны. Много людей пользуются и больше документации.
                            0
                            Если вам действительно интересно, а не троллинга ради, то принципиальное отличие: писать в BDD стиле в РСпек очень просто, дело скорее в способе организации кода. Правильно написанный код RSpec вообще можно сразу же гнать в документацию, и читать такие тесты одно удовольствие, в отличии от простыни ассертов.

                            Посмотрите отличную презентацию kerryb.github.com/iprug-rspec-presentation/

                    –1
                    ничего в нем страшного нет
                    он просто медленнее и поэтому надо тестировать с умом
                      0
                      Писал как-то сценарии на cucumber, смысла в этом особо не нашел. Возможно, сказывается еще то, что английский хоть и на хорошем уровне, но все таки не родной
                        +2
                        Cucumber позволяет писать сценарии и на русском
                      +2
                      Тесты не бесплатны, но удешевляемы.

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

                      Если бы на момент начала написания логики имел бы набор инструментов (примитивов, библиотек и др. байды) помогающих писать тесты для конкретной области, вопрос писать или нет бы не стоял. Поэтому, по крайней мере, пробую писать. Что бы получить пищу для размышления, «почему сложно» и как по необходимости эту сложность решить.
                        –2
                        По видимому, маятник моды уже начинает свой ход в обратную сторону.
                          +1
                          TDD очень мощная вещь, но только при грамотном использовании. TDD это не просто «тестирование кода», а по сути — иной способой разработки программы (сайта).
                          В ruby вообще очень просто и приятно использовать TDD (в отличие от компилирумых языков). Есть отличные Gem'ы для TDD разработки:
                          RSpec, Factorial_Girl, Guard_RSPec
                            0
                            Я бы ещё добавил Timecop. Такого в других даже динамичных языках таки нет.
                              0
                              Спасибо
                              0
                              Еще Spork — форкинг процессов в guard перед запуском, очень ускоряет TDD.
                              DHH в этой статье будто мои мысли прочитал. Как раз себя сейчас приучаю к контрибьютингу и тестированию.
                              0
                              Потрясающая статья! Не понимаю почему так мало плюсов…
                                0
                                Стоимость написания тестов сильно уменьшается при использовании DSL (Domain Specific Language).
                                Правда написание самого DSL тоже не бесплатно :)
                                  0
                                  Забыли самое важное: не тестируйте функционал рельсы.

                                  Only users with full accounts can post comments. Log in, please.