← Назад к вопросам

Как проверить, что программа работает

1.0 Junior🔥 221 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ответ

Это самый важный вопрос в разработке. Как проверить что программа действительно работает — это основа качества. Рассмотрю систематичный подход.

1. Локальное тестирование

Unit тесты

Тестирую каждую функцию отдельно:

public class UserServiceTest {
    
    private UserService userService;
    private UserRepository repository;
    
    @BeforeEach
    void setup() {
        repository = mock(UserRepository.class);
        userService = new UserService(repository);
    }
    
    @Test
    void shouldReturnUserById() {
        // Arrange
        User expected = new User(1L, "John", "john@example.com");
        when(repository.findById(1L)).thenReturn(Optional.of(expected));
        
        // Act
        User actual = userService.getUser(1L);
        
        // Assert
        assertEquals(expected, actual);
        verify(repository).findById(1L);
    }
    
    @Test
    void shouldThrowExceptionWhenUserNotFound() {
        // Arrange
        when(repository.findById(999L)).thenReturn(Optional.empty());
        
        // Act & Assert
        assertThrows(UserNotFoundException.class, 
            () -> userService.getUser(999L)
        );
    }
}

Запуск:

mvn test
mvn test -Dtest=UserServiceTest

Integration тесты

Тестирую взаимодействие компонентов:

@SpringBootTest
@Transactional
public class UserRepositoryIntegrationTest {
    
    @Autowired
    private UserRepository repository;
    
    @Autowired
    private TestEntityManager em;
    
    @Test
    void shouldSaveAndRetrieveUser() {
        // Arrange
        User user = new User(null, "Jane", "jane@example.com");
        
        // Act
        User saved = repository.save(user);
        em.flush();
        em.clear();
        User retrieved = repository.findById(saved.getId()).orElse(null);
        
        // Assert
        assertNotNull(retrieved);
        assertEquals("Jane", retrieved.getName());
    }
}

Запуск:

mvn integration-test
mvn test -Dgroups=integration

2. Code Coverage — проверка покрытия

Конфигурация:

<!-- pom.xml -->
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.10</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <rules>
            <rule>
                <element>PACKAGE</element>
                <excludes>
                    <exclude>*Test</exclude>
                </excludes>
                <limits>
                    <limit>
                        <counter>LINE</counter>
                        <value>COVEREDRATIO</value>
                        <minimum>0.80</minimum>
                    </limit>
                </limits>
            </rule>
        </rules>
    </configuration>
</plugin>

Запуск:

mvn test jacoco:report
# Отчёт в target/site/jacoco/index.html

3. Static Code Analysis

Проверка кода на ошибки без запуска:

SonarQube:

mvn clean verify sonar:sonar \
  -Dsonar.projectKey=my-app \
  -Dsonar.sources=src \
  -Dsonar.host.url=http://localhost:9000

SpotBugs:

<plugin>
    <groupId>com.github.spotbugs</groupId>
    <artifactId>spotbugs-maven-plugin</artifactId>
    <version>4.7.3.6</version>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Lint (Checkstyle):

mvn checkstyle:check

4. Ручное тестирование

Локально

# Собрать
mvn clean package

# Запустить
java -jar target/myapp-1.0.0.jar

# Или для Spring Boot
mvn spring-boot:run

# Или запустить тесты в IDE
# IntelliJ IDEA: Right-click → Run

Функциональное тестирование

# Если это REST API
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name": "John", "email": "john@example.com"}'

# Или использовать Postman/Insomnia

# Или писать скрипты
bash test_api.sh

Пример bash скрипта:

#!/bin/bash

BASE_URL="http://localhost:8080"

# Тест 1: GET /users
echo "Test 1: Getting users..."
RESPONSE=$(curl -s "$BASE_URL/api/users")
echo $RESPONSE | jq .

# Тест 2: POST /users
echo "Test 2: Creating user..."
curl -s -X POST "$BASE_URL/api/users" \
  -H "Content-Type: application/json" \
  -d '{"name": "Jane"}' | jq .

# Проверка результата
echo "Tests completed"

5. E2E тесты (Playwright)

Тестирую UI полностью:

// tests/auth.spec.ts
import { test, expect } from '@playwright/test';

test('User login flow', async ({ page }) => {
  // Arrange
  await page.goto('http://localhost:3000/login');
  
  // Act
  await page.fill('input[name="email"]', 'user@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');
  
  // Assert
  await expect(page).toHaveURL('http://localhost:3000/dashboard');
  await expect(page.locator('h1')).toContainText('Welcome');
});

Запуск:

npm run test:e2e
npx playwright show-report

6. Performance тестирование

JMH (Java Microbenchmark Harness)

public class StringConcatenationBenchmark {
    
    @Benchmark
    public String testStringConcat() {
        String result = "";
        for (int i = 0; i < 100; i++) {
            result += "value";
        }
        return result;
    }
    
    @Benchmark
    public String testStringBuilder() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 100; i++) {
            sb.append("value");
        }
        return sb.toString();
    }
}

Запуск:

mvn exec:java -Dexec.mainClass="org.openjdk.jmh.Main"

Load тесты (Apache JMeter)

# Скачать JMeter и создать test plan
jmeter -n -t test_plan.jmx -l results.jtl -j jmeter.log

7. Security проверки

OWASP Dependency Check

<plugin>
    <groupId>org.owasp</groupId>
    <artifactId>dependency-check-maven</artifactId>
    <version>8.0.0</version>
    <executions>
        <execution>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
    </executions>
</plugin>
mvn dependency-check:check

8. Логирование и мониторинг

public class UserService {
    private static final Logger log = LoggerFactory.getLogger(UserService.class);
    
    public User getUser(Long id) {
        log.info("Fetching user with id: {}", id);
        try {
            User user = repository.findById(id)
                .orElseThrow(() -> new UserNotFoundException(id));
            log.info("User found: {}", user.getName());
            return user;
        } catch (Exception e) {
            log.error("Error fetching user: {}", id, e);
            throw e;
        }
    }
}

Проверка логов:

tail -f /var/logs/app.log | grep ERROR

9. Чеклист перед production

✓ Все юнит тесты проходят (mvn test)
✓ Integration тесты проходят
✓ Code coverage > 80%
✓ SonarQube issues исправлены
✓ Нет security vulnerabilities
✓ Performance acceptable
✓ E2E тесты пройдены
✓ Логирование работает
✓ Error handling везде
✓ Database migrations работают
✓ API документация актуальна
✓ Code review пройден
✓ Deployment процесс протестирован

10. Мониторинг в production

# Health check endpoint
curl http://production-server:8080/actuator/health

# Metrics
curl http://production-server:8080/actuator/metrics

# Logs
docker logs -f myapp

# Uptime
uptime

# Resource usage
htop

Мой процесс

  1. Локально: Юнит + интеграционные тесты
  2. CI/CD: Code coverage + static analysis + build
  3. Dev сервер: E2E тесты + manual smoke test
  4. Stage: Full smoke test + performance check
  5. Production: Health checks + monitoring

Аксиома

Программа, которая не протестирована, не работает.

Даже если она выглядит как работает, это просто потому что вы не нашли баг. Тестирование это не burden, это инвестиция в качество.

Как проверить, что программа работает | PrepBro