Что такое статический анализ?
Статический анализ — это автоматизированная проверка исходного кода без его выполнения. Инструменты сканируют код, выявляя паттерны, указывающие на баги, уязвимости безопасности, нарушения стиля и проблемы сложности.
Если ручные ревью (из Урока 2.29) опираются на человеческое суждение, инструменты статического анализа применяют тысячи правил единообразно к каждой строке кода за секунды. Они не устают, не пропускают известные паттерны и работают одинаково каждый раз.
Думайте о статическом анализе как о проверке орфографии для кода. Проверка орфографии не скажет, хорош ли аргумент вашего эссе (для этого нужен человек), но она мгновенно находит опечатки и грамматические ошибки.
Статический анализ vs. Ручное ревью
| Аспект | Статический анализ (инструменты) | Ручное ревью (люди) |
|---|---|---|
| Скорость | Секунды — минуты | Часы — дни |
| Согласованность | 100% | Зависит от рецензента |
| Покрытие | Каждый файл, каждая строка | Фокус на изменённом коде |
| Что находит | Известные паттерны, нарушения правил | Дефекты дизайна, ошибки логики |
| Что пропускает | Новые баги, ошибки бизнес-логики | Известные паттерны (если рецензент устал) |
| Стоимость | Лицензия + время CI | Время разработчика |
Лучшая практика: используйте оба. Статический анализ ловит рутинные проблемы, освобождая людей для анализа дизайна и логики.
Популярные инструменты статического анализа
| Инструмент | Языки | Фокус |
|---|---|---|
| SonarQube/SonarCloud | 30+ языков | Комплексный: баги, уязвимости, smells, покрытие |
| ESLint | JavaScript/TypeScript | Стиль, паттерны, потенциальные ошибки |
| Pylint / Ruff | Python | Качество, стиль, ошибки |
| PMD | Java, Apex и др. | Паттерны, сложность |
| SpotBugs | Java | Паттерны багов в байткоде |
| RuboCop | Ruby | Стиль, паттерны, сложность |
| golangci-lint | Go | Мета-линтер, объединяющий несколько инструментов |
| Semgrep | Мульти-язычный | Поиск паттернов с фокусом на безопасность |
Обзор SonarQube
SonarQube — отраслевой стандарт непрерывной инспекции качества кода. Предоставляет централизованный дашборд для мониторинга качества кода по проектам, отслеживания технического долга и применения стандартов.
Типы Issues
Bugs — Код, который доказуемо неверен или может вызвать неожиданное поведение при выполнении. Примеры: разыменование null, выход за границы массива, утечки ресурсов.
Vulnerabilities — Код, который может быть эксплуатирован атакующими. Примеры: SQL injection, XSS, захардкоженные учётные данные.
Code Smells — Код, который не является неверным, но затрудняет поддержку кодовой базы. Примеры: дублирование кода, чрезмерно сложные методы, неиспользуемые переменные.
Уровни серьёзности
| Серьёзность | Описание | Пример |
|---|---|---|
| Blocker | Вызовет краш или потерю данных | Разыменование null в продакшн-пути |
| Critical | Вероятно вызовет серьёзную проблему | Уязвимость SQL injection |
| Major | Может вызвать незначительную проблему или существенную деградацию | Метод с цикломатической сложностью 50 |
| Minor | Проблема качества с низким влиянием | Неиспользуемый import |
| Info | Не проблема, лишь предложение | Рассмотрите использование StringBuilder |
Quality Gates
Quality Gate — набор условий, которым новый код должен соответствовать. Это барьер между разработкой и деплоем.
Quality Gate по умолчанию («Sonar Way»):
- Нет новых багов
- Нет новых уязвимостей
- Покрытие нового кода ≥ 80%
- Дублирование нового кода ≤ 3%
Команды настраивают Quality Gates под свои стандарты.
Технический долг
SonarQube измеряет технический долг как оценочное время для исправления всех code smells. Отображается как временная оценка: «5 дней технического долга.»
Ratio технического долга = (стоимость исправления smells) / (стоимость переписывания с нуля). Ratio ниже 5% считается управляемым.
Настройка SonarQube
Локальная установка (Docker)
# Запуск SonarQube
docker run -d --name sonarqube -p 9000:9000 sonarqube:community
# Доступ по http://localhost:9000 (логин: admin/admin)
Сканирование проекта
sonar-scanner \
-Dsonar.projectKey=my-project \
-Dsonar.sources=src \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=ваш-токен
Интеграция с CI/CD
# Пример GitHub Actions
- name: SonarQube Scan
uses: sonarqube/sonarcloud-github-action@v2
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
Pipeline падает, если Quality Gate не пройден, предотвращая интеграцию некачественного кода.
Интерпретация отчётов SonarQube
При просмотре отчёта следуйте порядку приоритетов:
- Статус Quality Gate — Пройден или нет?
- Новые баги и уязвимости — Высший приоритет. Исправить все blockers и criticals.
- Security hotspots — Код, отмеченный как потенциально уязвимый, требующий человеческой проверки.
- Покрытие нового кода — Адекватно ли протестирован? Ниже 80% указывает на пробелы.
- Code smells в новом коде — Низкий приоритет, но отслеживайте тренд.
- Общие метрики — Проект улучшается или ухудшается со временем?
Упражнение: Интерпретируйте отчёт SonarQube
Вы — QA Lead, проверяющий отчёт SonarQube для PR с новой функцией регистрации пользователей:
Анализ нового кода:
- Bugs: 2 (1 Critical, 1 Major)
- Уязвимости: 1 (Critical)
- Code Smells: 8 (2 Major, 6 Minor)
- Покрытие: 65%
- Дублирование: 1.2%
Детали багов:
- CRITICAL: Разыменование null в
UserService.register() - MAJOR:
UserController.handleRegistration()ловит общий Exception
Детали уязвимости:
- CRITICAL: SQL injection в
UserRepository.findByEmail()— email конкатенируется прямо в SQL-запрос
Quality Gate: НЕ ПРОЙДЕН (покрытие < 80%, критическая уязвимость)
Часть 1: Приоритизируйте находки. Что нужно исправить до merge?
Часть 2: Для уязвимости SQL injection опишите исправление и тест-кейсы.
Часть 3: Разработчик утверждает, что 65% покрытия «достаточно». Напишите ваш ответ.
Часть 4: Какие улучшения процесса вы бы рекомендовали?
Подсказка
Для Части 1 учитывайте серьёзность и тип issue. Уязвимости, особенно SQL injection, всегда должны исправляться до merge. Для Части 3 подумайте, чего должны достигать цели покрытия.Решение
Часть 1: Приоритизация
Обязательно исправить до merge:
- CRITICAL уязвимость: SQL injection — риск утечки данных.
- CRITICAL баг: Разыменование null — вызовет краши в продакшне.
Настоятельно рекомендуется исправить: 3. MAJOR баг: Перехват общего Exception. 4. Покрытие: 65% → нужно больше тестов.
Можно отложить: 5. 8 code smells — создать тикет на следующий спринт.
Часть 2: Исправление SQL Injection
Уязвимый код:
String query = "SELECT * FROM users WHERE email = '" + email + "'";
Исправленный код:
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email);
Тест-кейсы: обычный email, попытка SQL injection (admin'; DROP TABLE users;--), спецсимволы, пустой email, null email.
Часть 3: Сохранить порог 80%, потому что: 65% покрытия на потоке регистрации рискованно, порог применяется только к новому коду, снижение планки создаёт прецедент, а настоящий вопрос — почему покрытие низкое.
Часть 4: Интеграция SonarLint в IDE, pre-commit hooks с правилами безопасности, обучение по OWASP Top 10, чеклист в шаблоне PR, интеграционные тесты для dependency injection.
Ключевые выводы
- Статический анализ автоматизирует инспекцию кода, находя баги, уязвимости и code smells без выполнения кода
- SonarQube классифицирует issues на bugs (надёжность), vulnerabilities (безопасность) и code smells (поддерживаемость)
- Quality Gates устанавливают пороговые условия для нового кода
- Технический долг измеряется как оценочное время для исправления всех code smells
- Статический анализ дополняет ручные ревью — инструменты ловят паттерны, люди — логику и дизайн
- Интеграция с CI/CD обеспечивает анализ каждого изменения
- Наибольшую ценность даёт исправление issues в новом коде (shift-left), а не ремедиация legacy-кода