Зачем ревьюить тестовый код?
Тестовый код — это продакшн-код. Он запускается в CI/CD-пайплайнах, влияет на решения о деплое и поддерживается годами. Тем не менее, многие команды относятся к нему как к второсортному. Результат: хрупкий, неподдерживаемый набор тестов, которому никто не доверяет.
Чек-лист ревью
1. Тест проверяет то, что заявляет?
// ПЛОХО — имя говорит "создание" но тест проверяет только навигацию
@Test
void testUserCreation() {
loginPage.login("admin", "pass");
createUserPage.fillForm("Alice", "alice@test.com");
createUserPage.submit();
// Нет проверки, что пользователь действительно создан!
}
// ХОРОШО — проверка соответствует имени
@Test
void testUserCreation() {
loginPage.login("admin", "pass");
createUserPage.fillForm("Alice", "alice@test.com");
createUserPage.submit();
assertTrue(userService.exists("alice@test.com"));
}
2. Именование тестов
// ПЛОХО
@Test void test1() { ... }
// ХОРОШО
@Test void should_showDashboard_when_loginWithValidCredentials() { ... }
@Test void should_showError_when_loginWithExpiredPassword() { ... }
3. Структура Arrange-Act-Assert
@Test
void should_applyDiscount_when_couponIsValid() {
// Arrange
Order order = OrderFactory.createWithTotal(100.00);
Coupon coupon = CouponFactory.createValid("SAVE20", 20);
// Act
order.applyCoupon(coupon);
// Assert
assertEquals(80.00, order.getTotal(), 0.01);
}
4. Одна задача на тест
5. Без логики в тестах
// ПЛОХО — логика в тесте
@Test void testUserRoles() {
for (String role : List.of("admin", "user")) {
if (role.equals("admin")) assertTrue(user.canDelete());
}
}
// ХОРОШО — отдельные тесты
@Test void admin_canDelete() { ... }
@Test void regularUser_cannotDelete() { ... }
Типичные анти-паттерны
Mystery Guest
Тест зависит от невидимого внешнего состояния.
Eager Test
Тест проверяет слишком много за раз.
Гигант
Метод на 100+ строк, невозможный для понимания с первого взгляда.
Чувствительное равенство
// ПЛОХО
assertEquals(expectedUser.toString(), actualUser.toString());
// ХОРОШО
assertEquals("Alice", actualUser.getName());
Захардкоженные ожидания
// ПЛОХО
await page.waitForTimeout(5000);
// ХОРОШО
await expect(page.locator('.result')).toBeVisible();
Правила ревью для команд
Что проверять ревьюерам
- Корректность проверок
- Изоляция теста
- Ясность именования
- Независимость данных
- Отсутствие рисков нестабильности
- Надлежащая очистка
- Читаемость
Что НЕ придирать
- Мелкие предпочтения форматирования
- Выбор библиотеки проверок
- Значения тестовых данных, не влияющие на поведение
Упражнения
Упражнение 1: Обнаружение анти-паттернов
Ревьюируйте 5 примеров тестового кода, найдите все анти-паттерны, предложите исправления.
Упражнение 2: Рефакторинг именования
Переименуйте 10 плохо названных методов по конвенции should_outcome_when_condition.
Упражнение 3: Документ стандартов
Создайте документ стандартов ревью тестового кода с конвенциями, правилами, анти-паттернами и примерами.