В чем основные различия между фреймворками JUnit и TestNG для тестирования Java?

«В чем основные различия между фреймворками JUnit и TestNG для тестирования Java?» — вопрос из категории Инструменты тестирования, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

JUnit (сейчас актуальна версия 5) и TestNG — два популярных фреймворка для модульного и интеграционного тестирования в Java. JUnit является де-факто стандартом, а TestNG предлагает дополнительные возможности.

Ключевые различия:

Функция JUnit 5 TestNG
Архитектура Состоит из нескольких модулей (JUnit Jupiter, Vintage, Platform). Единый, монолитный фреймворк.
Группировка тестов Использует аннотацию @Tag. Группы определяются на уровне класса или метода. Использует параметр groups в аннотации @Test. Более гибкая система именования и включения/исключения групп.
Зависимости между тестами Не поддерживает явные зависимости. Тесты должны быть изолированы. Поддерживает через dependsOnMethods или dependsOnGroups в @Test. Позволяет задавать порядок выполнения.
Параллельное выполнение Поддерживается через конфигурацию движка (настройки в junit-platform.properties). Имеет встроенную и простую настройку параллелизма (в testng.xml или аннотациях).
Аннотации @Before / @After @BeforeAll, @AfterAll (статические), @BeforeEach, @AfterEach. Более богатый набор: @Before/AfterSuite, @Before/AfterTest, @Before/AfterClass, @Before/AfterMethod, @Before/AfterGroup.
Параметризованные тесты Через @ParameterizedTest с различными источниками данных (@ValueSource, @CsvSource и др.). Через @Test(dataProvider = "...") и метод, помеченный @DataProvider.
Пропуск тестов (отключение) @Disabled. @Test(enabled = false).

Примеры кода:

JUnit 5:

import org.junit.jupiter.api.*;

@Tag("integration")
class UserServiceTest {
    @BeforeEach
    void setUp() { /* инициализация */ }

    @Test
    @DisplayName("Успешный логин пользователя")
    void loginSuccess() {
        // assertion
    }

    @ParameterizedTest
    @ValueSource(strings = {"user1", "user2"})
    void testWithParameters(String user) {
        // assertion
    }
}

TestNG:

import org.testng.annotations.*;

public class UserServiceTest {
    @BeforeMethod
    public void setUp() { /* инициализация */ }

    @Test(groups = {"integration", "fast"})
    public void loginSuccess() {
        // assertion
    }

    @Test(dependsOnMethods = {"loginSuccess"}, groups = "slow")
    public void updateProfile() {
        // Этот тест запустится только после успешного выполнения loginSuccess
    }

    @Test(dataProvider = "userData")
    public void testWithParameters(String user, String pass) {
        // assertion
    }

    @DataProvider
    public Object[][] userData() {
        return new Object[][] { {"user1", "pass1"}, {"user2", "pass2"} };
    }
}

Выбор фреймворка:

  • JUnit 5 — лучший выбор для большинства проектов, особенно для чистых модульных тестов. Это современный, активно развивающийся стандарт с мощной экосистемой.
  • TestNG — может быть предпочтительнее для сложных интеграционных тестовых наборов, где критически важны гибкие зависимости между тестами, расширенная группировка и конфигурация через XML.