The Code and Its Tests in Different Pull Requests

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

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

На первый взгляд это может показаться противоречием принципам TDD. Однако для меня этот подход выглядит как крайняя применение TDD, а не нарушение его. Сначала мы сливаем тесты, которые, скорее всего, сломают сборку, так как функциональность, которую они тестируют, еще не реализована. Чтобы избежать сломанного состояния сборки, мы отключаем новые тесты, которые мы добавили, и тесты, которые мы изменили. В JUnit 5 мы делаем это с помощью @Disabled аннотации.

Рецензенты проверяют ваши изменения, задавая себе вопросы: “Действительно ли нам нужна эта новая функциональность? Конфликтует ли она с существующей функциональностью? Есть ли смысл тестировать новую функциональность именно таким образом?” Они не думают о как функциональность будет реализована, им важны только требования, которые вы накладываете в своих тестах на продукт. На этом этапе рецензенты действуют примерно как инженеры по требованиям. Они проверяют намерение, а не реализацию.

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

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

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

Что теперь вы думаете? Все это имеет смысл?

Translated by ChatGPT gpt-3.5-turbo/42 on 2024-01-09 at 18:10

sixnines availability badge   GitHub stars