Методология: Написание юнит-тестов для другого разработчика

28

Я думал о разработке программного обеспечения и написании юнит-тестов. Я получил следующую идею:

Предположим, у нас есть пары разработчиков. Каждая пара отвечает за часть кода. Один из пары реализует функцию (написание кода), а второй пишет для нее модульные тесты. Тесты написаны после кода. По моей идее они помогают друг другу, но работают скорее по отдельности. В идеале они должны работать над двумя функциями одинакового размера, а затем обмениваться на подготовку к тесту.

Я думаю, что эта идея имеет некоторые преимущества:

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

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

Каковы недостатки этой идеи? Это уже описано как некоторая неизвестная мне методология и используется в разработке программного обеспечения?

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

franiis
источник
17
Вы просто описываете нижестоящий контроль качества на уровне подразделений. Если у вас есть пары людей, которые работают над чем-то, пробовали ли вы на самом деле программирование пар с помощью TDD?
Джоншарп
9
Это сработало бы лучше, если бы тестирующий сначала выполнял тесты (записывал скелетный код), а другой реализовывал функциональность. Первый будет контролировать дизайн, а другой будет выполнять тяжелую работу. Это может сработать, если первый знает, что делает, а второй не возражает следовать его примеру. Я не знаю названия этого способа сотрудничества. Я бы сказал .. заявить это! Начни называть это развитием Franiis.
Мартин Маат
14
Эта критика не имеет смысла, и ваше предложение не решает эту проблему.
Джоншарп
5
@franiis Я видел, как коллеги писали assert trueкак тесты и называли это днем, потому что каждый тест проходил. Один важный шаг был пропущен: сначала тесты должны были провалиться, и их нужно было пройти, изменив код, а не тесты.
Эрик Думинил
6
@franiis TDD построен на итерации. Напишите провальный тест. Напишите код, который делает тест зеленым. Рефакторинг. Напишите провальный тест. Напишите код, который делает тест зеленым. Рефакторинг. Кажется, вам не хватает части «повторяйте, пока у вас не появятся тесты, удовлетворяющие всем вашим требованиям». Но самая большая проблема, с которой вы, похоже, столкнулись, заключается в том, что «тесты» рассматриваются как нечто, что вы должны иметь, потому что кто-то так сказал, а не тесты, являющиеся полезным инструментом для разработчиков . Если вы не можете заставить людей позаботиться о качестве (и правильности) своего кода, это ваша проблема, и с этого вам следует начать.
Луаан

Ответы:

30

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

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

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

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

Томас Оуэнс
источник
Спасибо, моя идея предполагает, что обе функции разрабатываются одинаково (но разработчики обмениваются ролями) - просто чтобы прояснить, а не защитить смысл этой концепции. Мне нравится ваш ответ и ваше внимание к скорости против качества.
Фрэнсис
По моему опыту, затраты на переделки перевешивают преимущества этого подхода. Я бы предпочел, чтобы пара обменивала эти пошлины, используя «пинг-понг» или другой метод.
Неонтапир
3
Практика парного программирования - это не скорость, а качество. Пара TDD - это качество, которое обеспечивает скорость завершения, что снижает затраты на разработку. Наша отрасль узнает, что масоны знали тысячелетиями: ваша стена будет построена лучше за меньшее время, с меньшими усилиями и меньшими затратами, если вы потратите некоторое время на то, чтобы сначала установить строку и правило каменщика, а затем сложить кирпичи, чем если бы Вы кладете свой кирпич и пытаетесь потом отрегулировать с помощью спиртового уровня и молотка. И получить помощь с вещами.
Лоран LA RIZZA
@LaurentLARIZZA Это кажется правильным. Я полагаю, лучше сказать: «Практика парного программирования - это не скорость сейчас, а качество и скорость в будущем». Это определенно перспективная практика, чтобы раньше находить проблемы, повышать надежность работы и делиться знаниями, чтобы разрушать бункеры. Все они имеют стоимость сейчас, которая часто будет приносить вознаграждение в будущем.
Томас Оуэнс
@ThomasOwens: Ну, цена качества только воспринимается, а не реально. После того, как ваш тест пройден (и вы привели в порядок свой код), сценарий, описанный в вашем тесте, завершен и защищен, и вы получаете уверенность, что он работает, как ожидалось. Это сделано, и вы можете двигаться дальше. Если вы идете дальше без уверенности в том, что код работает, вы просто приняли долг, который вам придется выполнить позже. Долги стоили, а не отсутствие долгов. Я имею в виду, «будущее», о котором вы говорите, - это как только ваш первый тест пройден.
Лоран LA RIZZA
37

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

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

Если вам не повезет или вы не напишете тест сначала, шансы написать тест - значит немного переписать код. Что, если вы не тот человек, который пишет код в первую очередь, будет означать задержку, встречи, рефакторинг и т. Д.

Ewan
источник
Спасибо. но общая критика TDD заключается в том, что код иногда / часто пишется, чтобы сделать тесты «зелеными» - нет, чтобы быть хорошим Если тесты не проверяют какой-либо аспект кода, его можно пропустить в коде. Написание теста позже может помочь в этом (я согласен, что после написания кода могут потребоваться некоторые изменения, но разработчики должны научиться писать более тестируемый код в будущем).
Фрэнсис
1
@franiis уверен, что главная проблема не в том, что вы пишете тесты после, а в том, что вы делаете то же самое, а не в том же человеке, который написал код.
Эван
но если использовать, например, парное программирование, это займет меньше времени. Если два разработчика работают на одном терминале, то они никак не могут одновременно работать над двумя функциями, и моя идея должна допустить это (даже в ограниченном объеме). Встречи для микро-команды из двух человек не должны быть реальным бременем.
Фрэнсис
25
@franiis: «Если тесты не проверяют какой-либо аспект кода, его можно пропустить в коде». - В этом весь смысл. Тесты представляют собой кодирование требований в форме исполняемых примеров. Если для него нет теста, то к нему нет требований, и для него не должно быть кода .
Йорг Миттаг
3
Другая сторона того, что сказал @ JörgWMittag: если ваши тесты «не тестируют какой-то важный код», вам нужно исправить свои тесты. Это будет так же верно в вашей системе, как и в традиционных TDD.
ВТ
15

Основная проблема, которую я вижу здесь, на уровне модуля, когда я пишу код, я хочу скомпилировать его, запустить его и немедленно удалить наиболее очевидные ошибки - даже когда код неполон, и я знаю, что блок, функция или функция только частично реализовано. А для запуска кода модуля мне нужен какой-то фрагмент программы, вызывающий реализацию, обычно это модульный тест или хотя бы частичный модульный тест. Это не обязательно «стиль TDD по книге», такой тест может быть написан после или перед тестируемым кодом.

Когда одна версия моего модуля является «полнофункциональной» и свободной от всех ошибок, я могу найти этот путь самостоятельно, тогда имеет смысл передать ее другому человеку и позволить ей / ему написать дополнительные модульные тесты или просмотреть мой код , Но для меня нет смысла передавать его, как только компилятор не показывает предупреждений, что, безусловно, слишком рано, если я знаю, что мне пришлось подробно объяснить тестеру вещи, которые не работают "пока" или будут работать иначе через два часа, так как я все еще работаю над этим фрагментом кода. Необходимые затраты на связь для этого на этом уровне детализации ИМХО не будут уравновешены преимуществами.

Так что да, имея второй Dev написание дополнительных модульных тестов имеет смысл, но не для написания модульных тестов исключительно .

Док Браун
источник
7

Казалось бы, возможна любая из следующих ситуаций - все из которых нежелательны:

неразбериха

Как отметил Эван, CUT, возможно, потребуется изменить, чтобы сделать его тестируемым. Причина изменения не всегда очевидна для разработчика (и может вызвать разногласия), именно поэтому тесты пишутся первыми.

раздор

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

Переключение контекста

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


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

Робби Ди
источник
4

Когда используется в сочетании с парным программированием и TDD, это называется Ping Pong Pattern :

  • A пишет новый тест и видит, что он не проходит.
  • В реализует код, необходимый для прохождения теста.
  • B пишет следующий тест и видит, что он не проходит.
  • A реализует код, необходимый для прохождения теста.

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

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

В любом случае: вы можете многому научиться, тестируя новые способы ведения дел, даже если они не эффективны на 100%. Вы можете проверить это и поделиться своим реальным опытом

Borjab
источник
3

Я опаздываю на эту вечеринку, но думаю, мне есть что добавить.

Это уже описано как некоторая неизвестная мне методология и используется в разработке программного обеспечения?

Вы описываете Peer Testing .

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

Ах, доброе старое парное программирование .

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

Это не парное программирование.

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

Это определенно Peer Testing. Вот статья ACM об этом . Я сделал это Я работал там, где это было формальной частью процесса экспертной оценки . Это полезно, но, конечно, это не первая линия тестирования, и, конечно, это не классическое парное программирование.

Другое название для этого - Тестирование Whitebox . Хотя это определение касается не того, кто проводит тестирование, а того, что тестер видит внутреннюю работу тестируемого объекта, а не тестирование черного ящика, когда они видят только то, что входит, и что выходит. Чёрный ящик - это обычно то, что делает QA.

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

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

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

candied_orange
источник
Спасибо за ответ и за указание на Peer Testing (я прочитаю об этом).
Фрэнсис
1

Я занимался DDT (тестирование на основе разработки, или тесты после кода), парным программированием и красно-зеленым рефактором TDD по несколько лет каждый. Чтобы ответить на ваши утверждения точка за точкой:

тесты написаны кем-то, кто может увидеть больше о реализации

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

работа должна быть выполнена немного быстрее, чем парное программирование (две функции одновременно)

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

и тесты, и код несут ответственность за это

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

код проверяется как минимум двумя людьми

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

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

Разработчики (даже старшие) имеют совершенно разные представления о том, что составляет «хороший» код. Сокращение угла одного человека - совершенно правильный способ получения рабочего кода как можно скорее. Это рецепт обвинения и игровой системы.

Red-green-refactor TDD ( фактически пишет один тест перед написанием производственного кода, запускает его, видит его сбой, изменяет только производственный код , снова запускает тест, видит его успешным, а затем реорганизует, а не пропускает или заменяет любой из эти шаги) и обзоры кода работают.

l0b0
источник
Это было бы быстрее (предположительно), потому что у вас нет двух человек, выполняющих «одну и ту же работу» - каждый из них делает свое дело, а затем переставляет на полпути.
Джейкоб Райле
@JacobRaihle Pairing - это не два человека, которые развиваются бок о бок без общения. Это были бы два человека, делающие ту же самую работу. Спаривание действительно эффективно, потому что два человека сотрудничают в работе. По моему опыту, разработка идет примерно так же быстро, как и для отдельных программистов (т. Е. Пары выполняют работу вдвое быстрее), получающееся в результате программное обеспечение гораздо более высокого качества, и знания передаются.
10
Я пытаюсь объяснить причину, по которой «работа должна выполняться немного быстрее», которая, кажется, смутила вас. В моем опыте сопряжение обычно происходит медленнее, хотя я все еще думаю, что оно того стоит (предпочтительно как для индивидуальной работы, так и для тестирования ОП). Если это быстрее для вас, тем лучше.
Джейкоб Райл
1

Я думаю, что эта идея имеет некоторые преимущества:

Давайте пройдемся по ним один за другим.

тесты написаны кем-то, кто может увидеть больше о реализации,

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

работа должна быть выполнена немного быстрее, чем парное программирование (две функции одновременно)

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

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

и тесты, и код ответственны за это,

Посмотрите на коллективное владение кодом, как предложено XP. У вас будет еще больше людей, ответственных за код. Если ваша цель - поделиться знаниями между разработчиками, почему вы пытаетесь разделить их?

код проверяется как минимум двумя людьми

С парой TDD тоже. При сопряжении оба человека должны согласиться с тем, что написанный код является адекватным или нет его написания. Если это приводит к драке, у некоторых людей в команде есть неуместная проблема эго.

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

Поиск ошибок подразумевает, что в какой-то момент вы допустили, что они попали. Если они попали, они остались незамеченными. Отказ от написания тестов сначала дает лицензию на ошибки, чтобы войти.

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

ХР прямо говорит, что все практики ХР сделаны так, чтобы усиливать друг друга, покрывая недостатки друг друга Не стоит прислушиваться к критике любой практики XP, отделенной от других. Ни одна практика не идеальна, TDD не идеален, парное программирование не идеально, коллективное владение кодом не идеально, но все они покрывают друг друга.

Laurent LA RIZZA
источник