Для чего нужно регрессионное тестирование?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Регрессионное тестирование
Определение
Регрессионное тестирование — это проверка того, что новые изменения в коде не сломали существующий функционал. Это повторное выполнение ранее пройденных тестов после внесения изменений.
Почему это важно
1. Защита от неожиданных побочных эффектов
Когда разработчик вносит изменения в один модуль, это может повлиять на другие части системы, которые от него зависят:
// Был класс PaymentValidator
public class PaymentValidator {
public static boolean isValidAmount(BigDecimal amount) {
return amount.compareTo(BigDecimal.ZERO) > 0;
}
}
// Разработчик добавил валидацию максимальной суммы
public class PaymentValidator {
public static boolean isValidAmount(BigDecimal amount) {
return amount.compareTo(BigDecimal.ZERO) > 0
&& amount.compareTo(new BigDecimal("10000")) <= 0;
}
}
// Но это может сломать старый функционал, который предполагал платежи свыше 10000!
Регрессионное тестирование поймает эту проблему.
2. Уверенность при рефакторинге
Если код покрыт тестами, можно безопасно рефакторить:
// Исходный код
public class OrderService {
public BigDecimal calculateTotal(List<Item> items) {
BigDecimal total = BigDecimal.ZERO;
for (Item item : items) {
total = total.add(item.getPrice().multiply(new BigDecimal(item.getQuantity())));
}
return total;
}
}
// Рефакторим — используем stream API
public class OrderService {
public BigDecimal calculateTotal(List<Item> items) {
return items.stream()
.map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
// Регрессионные тесты гарантируют, что поведение не изменилось
3. Поймать bugs на ранней стадии
Чем раньше обнаружена ошибка, тем дешевле её исправить:
Цена исправления bug:
- На локальной машине: $1
- После commit: $10
- В staging: $100
- В production: $1000+
Регрессионное тестирование (CI/CD) ловит bugs до попадания в production.
4. Документация кода
Тесты служат живой документацией — показывают, как должен работать код:
@Test
public void testDiscountCalculation() {
// Это документирует поведение: скидка 10% для заказов > 1000
OrderService service = new OrderService();
BigDecimal total = service.calculateTotalWithDiscount(new BigDecimal("1500"));
assertEquals(new BigDecimal("1350"), total); // 1500 * 0.9
}
5. Снижение затрат на ручное тестирование
Автоматические тесты дешевле и быстрее, чем ручные:
Ручное тестирование:
- 50 test cases × 5 минут = 250 минут ≈ 4 часа на каждый релиз
Автоматизированное тестирование:
- 50 unit tests = 5 секунд
- 20 integration tests = 30 секунд
- Итого ≈ 1 минута на каждый релиз
Типы регрессионного тестирования
1. Unit Regression Testing
Проверка того, что отдельные методы работают как раньше:
@Test
public void testUserValidation() {
User user = new User("john@example.com");
assertTrue(user.isValid());
}
2. Integration Regression Testing
Проверка взаимодействия компонентов:
@SpringBootTest
public class OrderRepositoryTest {
@Test
public void testOrderPersistence() {
Order order = new Order("USER123", new BigDecimal("100"));
orderRepository.save(order);
Order retrieved = orderRepository.findById(order.getId()).orElse(null);
assertNotNull(retrieved);
assertEquals("USER123", retrieved.getUserId());
}
}
3. System Regression Testing
Проверка всей системы через API:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class OrderControllerTest {
@Test
public void testOrderCreationEndpoint() {
given()
.contentType("application/json")
.body(new CreateOrderRequest("item1", 2))
.when()
.post("/api/orders")
.then()
.statusCode(201)
.body("id", notNullValue());
}
}
Лучшие практики
1. Тесты должны быть быстрыми
// ПЛОХО — тест медленный, делает реальный DB запрос
@Test
public void testOrderCreation() {
Order order = orderRepository.save(new Order("USER1", new BigDecimal("100")));
assertTrue(order.getId() > 0);
}
// ХОРОШО — тест быстрый, использует моки
@Test
public void testOrderCreation() {
OrderRepository mockRepo = mock(OrderRepository.class);
Order order = new Order("USER1", new BigDecimal("100"));
when(mockRepo.save(order)).thenReturn(order);
assertTrue(order.isValid());
}
2. Поддерживай тесты актуальными
Когда меняется требование, обнови тест:
// Требование изменилось: скидка теперь 15%, не 10%
@Test
public void testDiscountCalculation() {
OrderService service = new OrderService();
BigDecimal total = service.calculateTotalWithDiscount(new BigDecimal("1000"));
assertEquals(new BigDecimal("850"), total); // 1000 * 0.85, не 900
}
3. CI/CD должна запускать тесты автоматически
# GitHub Actions
name: Regression Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: mvn test
- run: mvn integration-test
Выводы
Регрессионное тестирование нужно для:
- ✅ Защиты от побочных эффектов новых изменений
- ✅ Безопасного рефакторинга кода
- ✅ Раннего обнаружения ошибок
- ✅ Документирования поведения
- ✅ Снижения затрат на тестирование
- ✅ Уверенности в качестве кода
Без регрессионного тестирования каждый новый feature рискует сломать старый функционал. Это критически важно для поддерживаемости проекта на long-term basis.