Найти в Дзене

Тесты до кода без TDD (твиттер-тред)


Я часто пишу тесты до кода, но при этом не работаю по TDD. Почему?

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

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

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

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

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

Из последнего примера. Последние три месяца мы разрабтывали систему приемки документов от студентов, в которой в итоге сотня роутов, 68 моделей и около 50 тысяч строк кода (laravel/php + react/ts). Понимание доменной области приходило в процессе кодинга, поэтому можно сказать что мы двигались немного в слепую, дорабатывая систему по ходу. И я сошел бы с ума делая все это без тестов, так как проект часто менялся, но сама модель нет, скорее происходило расширение и иногда расщепление сущностей. Мы написали около 300 интеграционных тестов, которые выглядят примерно так:

#[Test]
public function store(): void
{
// TODO: check for new college without templates
$uploadedFile = UploadedFile::fake()->create('file.txt');
$attrs = Arr::except(ContractTemplate::factory()->raw(), ['college_id']);
$body = [
'college_contract_template' => [
...$attrs,
'uploaded_file' => $uploadedFile,
],
];

$response = $this
->actingAs($this->owner)
->post($this->route('college.admin.contract_templates.store'), $body);

$response->assertSessionHasNoErrors();
$response->assertRedirect();

$template = $this->college->contractTemplates()->latest()->first();
$this->assertModelExists($template);

$this->assertFieldsEqual($attrs, $template);

$this->assertModelExists($template->file);
Storage::assertExists($template->file->path);
$this->assertEquals($uploadedFile->name, $template->file->file_name);
}

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

И вот что по этому поводу сказал Kent Beck (спойлер: мне платят не за тесты) https://gist.github.com/jordelver/3818839

p.s. Какое соотношение тестов к коду в вашем проекте?
2 минуты