Ответ
Модульное тестирование — это метод проверки корректности работы отдельных, изолированных единиц кода (юнитов), таких как функции, методы или классы.
Основные принципы:
- Изоляция: Тестируемый юнит изолируется от зависимостей (баз данных, сетевых вызовов, других модулей) с помощью заглушек (mocks/stubs).
- Детерминированность: Тест всегда должен давать одинаковый результат при одинаковых входных данных.
- Скорость: Модульные тесты выполняются быстро, что позволяет запускать их часто.
- Автоматизация: Тесты являются частью кодовой базы и запускаются автоматически (в CI/CD).
Цель: Раннее обнаружение дефектов, упрощение рефакторинга и создание живой документации к коду.
Пример на Java с JUnit и Mockito:
// Класс для тестирования (сервис)
public class PaymentService {
private final TaxCalculator taxCalculator;
public PaymentService(TaxCalculator taxCalculator) {
this.taxCalculator = taxCalculator;
}
public double calculateTotal(double amount) {
double tax = taxCalculator.calculateTax(amount);
return amount + tax;
}
}
// Модульный тест
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class PaymentServiceTest {
@Test
void calculateTotal_ShouldReturnSumOfAmountAndTax() {
// 1. ARRANGE: Подготовка данных и заглушек
double amount = 100.0;
double mockTax = 20.0;
TaxCalculator mockCalculator = mock(TaxCalculator.class);
when(mockCalculator.calculateTax(amount)).thenReturn(mockTax);
PaymentService service = new PaymentService(mockCalculator);
// 2. ACT: Вызов тестируемого метода
double result = service.calculateTotal(amount);
// 3. ASSERT: Проверка результата
double expectedTotal = 120.0; // 100 + 20
assertEquals(expectedTotal, result);
// Проверка, что зависимость была вызвана с правильным аргументом
verify(mockCalculator).calculateTax(amount);
}
}
Популярные фреймворки: JUnit, TestNG (Java), pytest (Python), Jest (JavaScript). Модульные тесты — фундамент методологий TDD (Test-Driven Development) и CI/CD.
Ответ 18+ 🔞
А, ну модульное тестирование, блядь! Это ж когда ты каждую свою функцию, как псину дворовую, на поводок берёшь и проверяешь, не сбежит ли она с мозгами и не наложит ли в кодовую базу.
Основные принципы, ёпта:
- Изоляция: Это святое! Отделяешь свой кусок кода от всей этой ебалы: баз данных, других сервисов, интернета — хуй его знает чего. Подсовываешь ему заглушки (эти ваши моки-стабы), будто он в вакууме работает.
- Детерминированность: Чтоб как в аптеке, сука. Дал одни цифры — получил один ответ. Дал те же цифры через год — получил тот же самый ответ, а не "ой, а сегодня сервер полдня бухал".
- Скорость: Они должны бегать, как ошпаренные! Чтобы ты их по сто раз на дню гонять мог, и тебе не было влом.
- Автоматизация: Это не рукоблудие, блядь. Написал раз — и они сами в пайплайне бегают, как мартышки, и кричат, если что-то пошло не так.
Цель-то какая? Чтобы не получилось, как в том анекдоте: "работает? не трогай!". А тут ты трогаешь, рефакторишь, а эти тесты, как цепные псы, тебе сразу: "Э, куда пошёл? Сюда иди, ошибку нашёл, пидрила!". И ещё они как живая памятка — глянул на тест и понял, что эта функция вообще должна делать, а не гадать, как шаман.
Смотри, как это выглядит на Java, если не выёбываться:
// Вот наш сервис, который считает, сколько с тебя сдерут денег
public class PaymentService {
private final TaxCalculator taxCalculator; // А это хуйня, которая налог насчитывает
public PaymentService(TaxCalculator taxCalculator) {
this.taxCalculator = taxCalculator;
}
public double calculateTotal(double amount) {
double tax = taxCalculator.calculateTax(amount); // Спрашиваем у калькулятора
return amount + tax; // И прибавляем
}
}
// А вот наш тест, который всё это проверяет
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class PaymentServiceTest {
@Test
void calculateTotal_ShouldReturnSumOfAmountAndTax() {
// 1. ПОДГОТОВКА (ARRANGE): Расставляем все фигурки по полочкам
double amount = 100.0; // Сто рублей
double mockTax = 20.0; // Двадцать рублей налога (с потолка взял)
// Вот тут магия: делаем ПОДДЕЛЬНЫЙ калькулятор (mock), который не лезет в реальную систему
TaxCalculator mockCalculator = mock(TaxCalculator.class);
// Говорим ему: "Слушай сюда, мудила. Когда тебя спросят про налог для 100 рублей, отвечай — 20".
when(mockCalculator.calculateTax(amount)).thenReturn(mockTax);
// И пихаем эту заглушку в наш сервис
PaymentService service = new PaymentService(mockCalculator);
// 2. ДЕЙСТВИЕ (ACT): Нажимаем на кнопку
double result = service.calculateTotal(amount);
// 3. ПРОВЕРКА (ASSERT): Сверяем с ожиданием
double expectedTotal = 120.0; // 100 + 20
assertEquals(expectedTotal, result); // Сошлось? Красава.
// И дополнительно тычем пальцем в заглушку: "А ты точно вызвался с аргументом 100?"
verify(mockCalculator).calculateTax(amount);
}
}
Инструменты, которые все используют: JUnit, TestNG (для явы), pytest (для питона), Jest (для жс). Это, блядь, фундамент, на котором TDD и CI/CD стоят. Без этого — как без штанов на людях, вроде идёшь, но все на жопу смотрят.