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

Что такое SonarQube?

2.0 Middle🔥 141 комментариев
#Тестирование

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

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

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

Что такое SonarQube

SonarQube — это открытая платформа для статического анализа кода (Code Quality and Security), которая автоматически проверяет исходный код на ошибки, уязвимости, дублирование кода, нарушения стиля и помогает измерить техдолг проекта. Это стандартный инструмент в CI/CD пайплайнах крупных Java проектов.

Что проверяет SonarQube

1. Bugs (Ошибки) — потенциальные баги

// SonarQube обнаружит:

// Ошибка 1: Проверка null после использования
String name = getName();
if (name.length() > 0) { // Может быть NullPointerException
    System.out.println(name);
}

// Ошибка 2: Сравнение объектов по ==
String a = new String("hello");
String b = new String("hello");
if (a == b) { // Неправильно! Используй .equals()
    System.out.println("Same");
}

// Ошибка 3: Нечитаемый код
public int calculate(int a, int b) {
    return a+=b; // Опасный compound assignment в return
}

// Ошибка 4: Пустой catch
try {
    doSomething();
} catch (Exception e) {
    // Пустой блок — ошибка!  Нужно логировать или обрабатывать
}

2. Vulnerabilities (Уязвимости) — проблемы безопасности

// SonarQube обнаружит:

// Уязвимость 1: SQL Injection
String query = "SELECT * FROM users WHERE id = " + userId; // ОПАСНО!
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);

// Исправление:
String query = "SELECT * FROM users WHERE id = ?";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setInt(1, userId); // Параметризованный запрос

// Уязвимость 2: Hardcoded пароли
public class Database {
    private String password = "admin123"; // ОПАСНО!
}

// Уязвимость 3: Использование слабого шифрования
MessageDigest md = MessageDigest.getInstance("MD5"); // Слабое! Используй SHA-256

// Уязвимость 4: Небезопасная randomization
Random random = new Random(); // Не криптографически безопасно!
int token = random.nextInt();

// Исправление:
SecureRandom secureRandom = new SecureRandom();
byte[] token = new byte[32];
secureRandom.nextBytes(token);

3. Code Smells (Неприятные запахи кода) — плохой дизайн

// Code Smell 1: Слишком большой класс
public class UserService { // 5000 строк кода в одном классе!
    public void createUser() { }
    public void updateUser() { }
    public void deleteUser() { }
    public void sendEmail() { } // Email логика в UserService?
    public void processPayment() { } // Payment логика здесь?
    // ... 100 методов...
}

// Code Smell 2: Слишком длинный метод
public void processOrder(Order order) { // 500 строк!
    // Много кода
    // Нужно разбить на подметоды
}

// Code Smell 3: Дублирование кода
public String getFullNameUser1() {
    return user1.getFirstName() + " " + user1.getLastName();
}

public String getFullNameUser2() {
    return user2.getFirstName() + " " + user2.getLastName(); // Дублирование!
}

// Исправление:
public String getFullName(User user) {
    return user.getFirstName() + " " + user.getLastName();
}

// Code Smell 4: Использование Magic Numbers
public double calculateDiscount(int loyaltyPoints) {
    return loyaltyPoints * 0.01; // Что означает 0.01? Не очевидно
}

// Исправление:
private static final double LOYALTY_POINT_VALUE = 0.01;
public double calculateDiscount(int loyaltyPoints) {
    return loyaltyPoints * LOYALTY_POINT_VALUE;
}

4. Code Duplication (Дублирование) — повторяющийся код

// SonarQube обнаружит дублированные блоки кода:

public class DataProcessor {
    public List<Integer> processOddNumbers(List<Integer> numbers) {
        List<Integer> result = new ArrayList<>();
        for (Integer num : numbers) {
            if (num % 2 != 0) {
                result.add(num);
            }
        }
        return result;
    }
    
    public List<Integer> processEvenNumbers(List<Integer> numbers) {
        List<Integer> result = new ArrayList<>();
        for (Integer num : numbers) {
            if (num % 2 == 0) { // Дублирование логики фильтрации
                result.add(num);
            }
        }
        return result;
    }
}

// Исправление: используй Stream API
List<Integer> oddNumbers = numbers.stream()
    .filter(n -> n % 2 != 0)
    .collect(Collectors.toList());

Установка и использование SonarQube

Вариант 1: Docker (быстро)

# Запуск SonarQube в Docker
docker run -d --name sonarqube \
  -p 9000:9000 \
  sonarqube:latest

# После запуска, доступен на http://localhost:9000
# Логин: admin / admin

Вариант 2: Docker Compose

version: '3.8'
services:
  sonarqube:
    image: sonarqube:latest
    ports:
      - "9000:9000"
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonarqube
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    depends_on:
      - db
  
  db:
    image: postgres:13
    environment:
      POSTGRES_DB: sonarqube
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
    volumes:
      - postgresql_data:/var/lib/postgresql/data

volumes:
  postgresql_data:

Анализ проекта Maven

Способ 1: Через Maven плагин

# pom.xml
<plugin>
    <groupId>org.sonarsource.scanner.maven</groupId>
    <artifactId>sonar-maven-plugin</artifactId>
    <version>3.9.1.2184</version>
</plugin>

# Команда для анализа
mvn clean verify sonar:sonar \
  -Dsonar.projectKey=my-java-project \
  -Dsonar.sources=src \
  -Dsonar.host.url=http://localhost:9000 \
  -Dsonar.login=your_token_here

Способ 2: Через SonarScanner (универсально)

# Скачать SonarScanner
# https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/

# sonar-project.properties
sonar.projectKey=my-java-project
sonar.projectName=My Java Project
sonar.projectVersion=1.0
sonar.sources=src
sonar.java.binaries=target/classes

# Запуск анализа
sonar-scanner

Способ 3: Через Gradle

// build.gradle
plugins {
    id "org.sonarqube" version "4.0.0.2929"
}

sonarqube {
    properties {
        property "sonar.projectKey", "my-java-project"
        property "sonar.projectName", "My Java Project"
        property "sonar.sources", "src"
    }
}

// Команда
// ./gradlew sonarqube

Интеграция с CI/CD (GitHub Actions)

# .github/workflows/sonarqube.yml
name: SonarQube Analysis

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  sonarqube:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          java-version: '11'
      
      - name: Run SonarQube Analysis
        run: |
          mvn clean verify sonar:sonar \
            -Dsonar.projectKey=my-project \
            -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \
            -Dsonar.login=${{ secrets.SONAR_TOKEN }}
      
      - name: Check Quality Gate
        run: |
          # Убедиться, что качество прошло Quality Gate

Quality Gate (Ворота качества)

SonarQube позволяет установить критерии, при которых сборка считается passed/failed:

// Типичные критерии Quality Gate:

// 1. Coverage (покрытие тестами) >= 80%
if (coverage < 80) {
    qualityGate = "FAILED";
}

// 2. Bugs <= 10
if (bugs > 10) {
    qualityGate = "FAILED";
}

// 3. Vulnerabilities = 0
if (vulnerabilities > 0) {
    qualityGate = "FAILED";
}

// 4. Code Smells (A rating = хорошо)
if (maintenanceRating != 'A') {
    qualityGate = "FAILED";
}

// 5. Duplication < 3%
if (duplication >= 3.0) {
    qualityGate = "FAILED";
}

Примеры отчётов SonarQube

Проект: my-java-project

ОБЩАЯ СТАТИСТИКА:
- Lines of Code: 25,347
- Duplication: 2.3%
- Coverage: 87%
- Bugs: 5 (👎 5 критических)
- Vulnerabilities: 2 (🔴 2 SONAR Security Hotspots)
- Code Smells: 34

RATINGS:
- Reliability: B (есть bugs)
- Security: C (есть уязвимости)
- Maintainability: A (хороший код)
- Security Hotspot Review: 50% (половина проверена)

RECENT ISSUES:
1. CWE-89 (SQL Injection) — Line 345 в UserRepository.java
2. NullPointerException Risk — Line 567 в OrderService.java
3. Duplicate Code Block — 12 lines in UserValidator.java и AdminValidator.java
4. Too Many Parameters — processOrder() method has 8 parameters
5. Magic Number 0.01 — should be replaced with constant

Правила в SonarQube

SonarQube поставляется с сотнями встроенных правил, но можно кастомизировать:

// Примеры встроенных правил

// S1104: Classes should not have public mutable fields
public class BadClass {
    public String name; // VIOLATION: должно быть private с getter/setter
}

// S3457: Number and string arguments should be used in when giving messages
try {
    doSomething();
} catch (Exception e) {
    logger.error("Error occurred", e); // OK
    logger.error(e.toString()); // VIOLATION: не подходящее сообщение
}

// S1602: Nested ternary operators should not be used
int level = (age < 13) ? 0 : (age < 18) ? 1 : 2; // VIOLATION: слишком сложно

// S1125: Boolean expressions should not be gratuitously complex
if (value == true) { // VIOLATION: just use (value)
    // do something
}

Метрики SonarQube

Maintainability Rating (Оценка поддерживаемости):
A = 0-5% технического долга
B = 5-10% технического долга
C = 10-20% технического долга
D = 20-50% технического долга
E = > 50% технического долга

Reliability Rating (Надёжность):
A = 0 bugs
B = 1-3 bugs на 1000 LOC
C = 4-10 bugs на 1000 LOC
D = 11-25 bugs на 1000 LOC
E = > 25 bugs на 1000 LOC

Security Rating (Безопасность):
A = 0 уязвимостей
B = 1-3 уязвимостей
C = 4-10 уязвимостей
D = 11-25 уязвимостей
E = > 25 уязвимостей

Практический пример в CI/CD

#!/bin/bash
# build.sh — скрипт сборки проекта с анализом качества

set -e

echo "1. Compile and test"
mvn clean test -q

echo "2. Run SonarQube analysis"
mvn sonar:sonar \
  -Dsonar.projectKey=backend \
  -Dsonar.host.url=http://sonarqube:9000 \
  -Dsonar.login=$SONAR_TOKEN

echo "3. Build application"
mvn package -DskipTests -q

echo "4. Build Docker image"
docker build -t my-app:latest .

echo "✅ Build successful!"

Заключение

SonarQube — это essential tool для любого serious Java проекта:

  1. Находит баги — потенциальные NullPointerException, логические ошибки
  2. Обнаруживает уязвимости — SQL Injection, hardcoded пароли, слабое шифрование
  3. Улучшает дизайн — предупреждает о дублировании, big methods, code smells
  4. Измеряет качество — техдолг, покрытие, дублирование
  5. Встраивается в CI/CD — автоматическая проверка при каждом push
  6. Quality Gates — блокирует merge в main если качество упало

Для Java разработчика это значит, что почти любой production проект требует интеграции SonarQube в пайплайн. Это становится стандартом в enterprise разработке.

Что такое SonarQube? | PrepBro