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:

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

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

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

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

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

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

Что ты думаешь сейчас? Всё в этом имеет смысл?

Translated by ChatGPT gpt-3.5-turbo/35 on 2023-09-08 at 16:11

sixnines availability badge   GitHub stars