Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Положительный тест-кейс (Happy Path Test)
Положительный тест-кейс — это тест, который проверяет, работает ли функционал корректно при нормальных, ожидаемых условиях и с валидными входными данными. Это основной сценарий использования, когда всё идёт по плану.
Определение
Положительный тест-кейс:
- Использует валидные и корректные данные
- Проверяет ожидаемое поведение системы
- Тестирует успешный путь выполнения (happy path)
- Должен завершиться успехом
- Проверяет, что система работает как ожидается в нормальных условиях
Противоположность: Отрицательный тест-кейс
Отрицательный тест-кейс проверяет поведение при:
- Невалидных данных
- Граничных условиях
- Исключительных ситуациях
- Ошибочных сценариях
Пример: Сервис регистрации пользователя
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User registerUser(String email, String password, String fullName)
throws UserAlreadyExistsException, InvalidEmailException {
// Валидация email
if (!isValidEmail(email)) {
throw new InvalidEmailException("Invalid email format");
}
// Проверка, что пользователь не существует
if (userRepository.existsByEmail(email)) {
throw new UserAlreadyExistsException("User with this email already exists");
}
// Хеширование пароля
String hashedPassword = hashPassword(password);
// Создание пользователя
User user = new User();
user.setEmail(email);
user.setPassword(hashedPassword);
user.setFullName(fullName);
user.setCreatedAt(new Date());
user.setActive(true);
// Сохранение в БД
return userRepository.save(user);
}
private boolean isValidEmail(String email) {
return email != null && email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
private String hashPassword(String password) {
return BCrypt.hashpw(password, BCrypt.gensalt());
}
}
ПОЛОЖИТЕЛЬНЫЕ тест-кейсы
public class UserServiceTest {
private UserService userService;
private UserRepository userRepository;
@Before
public void setUp() {
userRepository = mock(UserRepository.class);
userService = new UserService(userRepository);
}
// ПОЛОЖИТЕЛЬНЫЙ ТЕСТ 1: Успешная регистрация
@Test
public void testRegisterUser_Success() throws Exception {
// Arrange — подготовка данных
String email = "john@example.com";
String password = "securePassword123";
String fullName = "John Doe";
when(userRepository.existsByEmail(email)).thenReturn(false);
when(userRepository.save(any(User.class))).thenAnswer(invocation -> {
User user = invocation.getArgument(0);
user.setId(1L);
return user;
});
// Act — выполнение операции
User result = userService.registerUser(email, password, fullName);
// Assert — проверка результата
assertNotNull(result);
assertEquals(email, result.getEmail());
assertEquals(fullName, result.getFullName());
assertTrue(result.isActive());
assertNotNull(result.getCreatedAt());
// Проверяем, что save был вызван ровно один раз
verify(userRepository, times(1)).save(any(User.class));
}
// ПОЛОЖИТЕЛЬНЫЙ ТЕСТ 2: Успешная регистрация с разными валидными данными
@Test
public void testRegisterUser_SuccessWithValidData() throws Exception {
// Arrange
String email = "jane.smith+tag@company.co.uk";
String password = "ComplexPassword!@#123";
String fullName = "Jane Smith";
when(userRepository.existsByEmail(email)).thenReturn(false);
when(userRepository.save(any(User.class))).thenAnswer(invocation -> {
User user = invocation.getArgument(0);
user.setId(2L);
return user;
});
// Act
User result = userService.registerUser(email, password, fullName);
// Assert
assertNotNull(result);
assertEquals(email, result.getEmail());
assertEquals(fullName, result.getFullName());
assertFalse(result.getPassword().equals(password)); // пароль захеширован
assertTrue(result.isActive());
}
// ПОЛОЖИТЕЛЬНЫЙ ТЕСТ 3: Проверка хеширования пароля
@Test
public void testRegisterUser_PasswordIsHashed() throws Exception {
// Arrange
String email = "user@example.com";
String password = "plainPassword";
String fullName = "Test User";
when(userRepository.existsByEmail(email)).thenReturn(false);
when(userRepository.save(any(User.class))).thenAnswer(invocation -> {
User user = invocation.getArgument(0);
user.setId(3L);
return user;
});
// Act
User result = userService.registerUser(email, password, fullName);
// Assert
assertNotNull(result.getPassword());
assertNotEquals(password, result.getPassword());
// Пароль должен быть захеширован, поэтому не совпадает с исходным
}
}
ОТРИЦАТЕЛЬНЫЕ тест-кейсы (для сравнения)
public class UserServiceNegativeTest {
private UserService userService;
private UserRepository userRepository;
@Before
public void setUp() {
userRepository = mock(UserRepository.class);
userService = new UserService(userRepository);
}
// ОТРИЦАТЕЛЬНЫЙ ТЕСТ 1: Невалидный email
@Test
public void testRegisterUser_InvalidEmail() {
// Arrange
String invalidEmail = "invalid-email";
String password = "password123";
String fullName = "User";
// Act & Assert
assertThrows(InvalidEmailException.class, () ->
userService.registerUser(invalidEmail, password, fullName)
);
}
// ОТРИЦАТЕЛЬНЫЙ ТЕСТ 2: Email уже существует
@Test
public void testRegisterUser_EmailAlreadyExists() {
// Arrange
String email = "existing@example.com";
String password = "password123";
String fullName = "User";
when(userRepository.existsByEmail(email)).thenReturn(true);
// Act & Assert
assertThrows(UserAlreadyExistsException.class, () ->
userService.registerUser(email, password, fullName)
);
}
// ОТРИЦАТЕЛЬНЫЙ ТЕСТ 3: Null email
@Test
public void testRegisterUser_NullEmail() {
// Act & Assert
assertThrows(InvalidEmailException.class, () ->
userService.registerUser(null, "password", "User")
);
}
}
Сравнение
| Аспект | Положительный тест | Отрицательный тест |
|---|---|---|
| Входные данные | Валидные | Невалидные |
| Ожидаемый результат | Успех | Ошибка/Exception |
| Цель | Проверить успешный путь | Проверить обработку ошибок |
| Сценарий | Нормальное использование | Граничные/исключительные случаи |
| Примеры | Создание пользователя с корректными данными | Email с недопустимым форматом |
Типология тестов
// Положительные тесты (должны проходить)
@Test public void registerUser_ValidEmail_Success() { }
@Test public void registerUser_ValidPassword_Success() { }
@Test public void registerUser_ValidFullName_Success() { }
// Отрицательные тесты (должны выбросить исключение)
@Test public void registerUser_InvalidEmail_ThrowsException() { }
@Test public void registerUser_EmptyPassword_ThrowsException() { }
@Test public void registerUser_DuplicateEmail_ThrowsException() { }
// Граничные тесты
@Test public void registerUser_VeryLongEmail_Success() { }
@Test public void registerUser_MinimalValidPassword_Success() { }
Лучшие практики
✓ Начинай с положительных тестов — это базис ✓ Используй реалистичные валидные данные ✓ Проверяй все аспекты успешного выполнения ✓ Убедись, что положительные тесты проходят перед написанием отрицательных ✓ Используй выразительные имена тестов ✓ Группируй положительные и отрицательные тесты отдельно ✓ Примерное соотношение: 60% положительных, 40% отрицательных
Важность положительных тестов
Положительные тесты критичны, потому что:
- Они проверяют основной функционал
- Подтверждают, что система работает в нормальных условиях
- Являются базисом для регрессионного тестирования
- Легче писать и понимать
- Обеспечивают высокий уровень доверия к системе