Une comparaison rapide de JUnit et TestNG

Salut, Habr. Pour les futurs étudiants du cours «Java QA Automation Engineer» et tous ceux intéressés par le thème des tests, nous avons préparé une traduction du matériel.



Nous vous invitons également à visiter le webinaire ouvert
"PageObject Pattern" . Pour éviter d'avoir à relire et à refactoriser les autotests, vous devez immédiatement réfléchir à leur architecture. C'est là que les modèles viennent à la rescousse. Les participants au webinaire, accompagnés d'un expert, se familiariseront avec les plus populaires d'entre eux.






1. Vue d'ensemble

JUnit et TestNG sont sans aucun doute les deux frameworks de tests unitaires les plus populaires de l'écosystème Java. Alors que JUnit a servi d'inspiration pour TestNG, ce dernier présente un certain nombre de différences et, contrairement à JUnit, fonctionne pour des niveaux de test fonctionnels et plus élevés.





, .





2.

- , . .





JUnit , . @BeforeEach, @AfterEach @BeforeAll @AfterAll :





public class SummationServiceTest {

    private static List<Integer> numbers;

    @BeforeAll
    public static void initialize() {
        numbers = new ArrayList<>();
    }

    @AfterAll
    public static void tearDown() {
        numbers = null;
    }

    @BeforeEach
    public void runBeforeEachTest() {
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
    }

    @AfterEach
    public void runAfterEachTest() {
        numbers.clear();
    }

    @Test
    public void givenNumbers_sumEquals_thenCorrect() {
        int sum = numbers.stream().reduce(0, Integer::sum);
        assertEquals(6, sum);
    }
}
      
      



, JUnit 5. JUnit 4 @Before @After, @BeforeEach @AfterEach. , @BeforeAll @AfterAll @BeforeClass @AfterClass JUnit 4.





JUnit, TestNG . @BeforeClass @AfterClass , @BeforeMethod @AfterMethod:





@BeforeClass
public void initialize() {
    numbers = new ArrayList<>();
}

@AfterClass
public void tearDown() {
    numbers = null;
}

@BeforeMethod
public void runBeforeEachTest() {
    numbers.add(1);
    numbers.add(2);
    numbers.add(3);
}

@AfterMethod
public void runAfterEachTest() {
    numbers.clear();
}
      
      



TestNG @BeforeSuite, @AfterSuite, @BeforeGroup @AfterGroup (suite) :





@BeforeGroups("positive_tests")
public void runBeforeEachGroup() {
    numbers.add(1);
    numbers.add(2);
    numbers.add(3);
}

@AfterGroups("negative_tests")
public void runAfterEachGroup() {
    numbers.clear(); 
}
      
      



, @BeforeTest @AfterTest, - -, XML- TestNG:





<test name="test setup">
    <classes>
        <class name="SummationServiceTest">
            <methods>
                <include name="givenNumbers_sumEquals_thenCorrect" />
            </methods>
        </class>
    </classes>
</test>
      
      



, @BeforeClass @AfterClass JUnit . , TestNG .





3.

-, -. JUnit @Ignore:





@Ignore
@Test
public void givenNumbers_sumEquals_thenCorrect() {
    int sum = numbers.stream().reduce(0, Integer::sum);
    Assert.assertEquals(6, sum);
}
      
      



TestNG @Test «enabled» true



false



:





@Test(enabled=false)
public void givenNumbers_sumEquals_thenCorrect() {
    int sum = numbers.stream.reduce(0, Integer::sum);
    Assert.assertEquals(6, sum);
}
      
      



4.  

JUnit, TestNG, -.





JUnit 5 @RunWith, @SelectPackages @SelectClasses - . — -, .





- Suite @SelectPackages



:





@RunWith(JUnitPlatform.class)
@SelectPackages({ "org.baeldung.java.suite.childpackage1", "org.baeldung.java.suite.childpackage2" })
public class SelectPackagesSuiteUnitTest {

}
      
      



, , JUnit 5 @SelectClasses:





@RunWith(JUnitPlatform.class)
@SelectClasses({Class1UnitTest.class, Class2UnitTest.class})
public class SelectClassesSuiteUnitTest {

}
      
      



, JUnit 4 @Suite:





@RunWith(Suite.class)
@Suite.SuiteClasses({ RegistrationTest.class, SignInTest.class })
public class SuiteTest {

}
      
      



TestNG XML:





<suite name="suite">
    <test name="test suite">
        <classes>
            <class name="com.baeldung.RegistrationTest" />
            <class name="com.baeldung.SignInTest" />
        </classes>
    </test>
</suite>
      
      



, RegistrationTest



SignInTest



.





, TestNG @Test (groups = "groupName")



:





@Test(groups = "regression")
public void givenNegativeNumber_sumLessthanZero_thenCorrect() {
    int sum = numbers.stream().reduce(0, Integer::sum);
    Assert.assertTrue(sum < 0);
}
      
      



XML :





<test name="test groups">
    <groups>
        <run>
            <include name="regression" />
        </run>
    </groups>
    <classes>
        <class 
          name="com.baeldung.SummationServiceTest" />
    </classes>
</test>
      
      



regression.





5.

JUnit, TestNG.





, :





public class Calculator {
    public double divide(double a, double b) {
        if (b == 0) {
            throw new DivideByZeroException("Divider cannot be equal to zero!");
        }
        return a/b;
    }
}
      
      



JUnit 5 API assertThrows



:





@Test
public void whenDividerIsZero_thenDivideByZeroExceptionIsThrown() {
    Calculator calculator = new Calculator();
    assertThrows(DivideByZeroException.class, () -> calculator.divide(10, 0));
}
      
      



JUnit 4 , @Test (expected = DivideByZeroException.class



) API.





TestNG :





@Test(expectedExceptions = ArithmeticException.class) 
public void givenNumber_whenThrowsException_thenCorrect() { 
    int i = 1 / 0;
}
      
      



, .





6.

. , . , .





JUnit 5 , . JUnit 5 source-, :





  • @ValueSource



    : Short



    , Byte



    , Int



    , Long



    , Float



    , Double



    , Char



    String



    :





@ParameterizedTest
@ValueSource(strings = { "Hello", "World" })
void givenString_TestNullOrNot(String word) {
    assertNotNull(word);
}
      
      



  • @EnumSource



    Enum- :





@ParameterizedTest
@EnumSource(value = PizzaDeliveryStrategy.class, names = {"EXPRESS", "NORMAL"})
void givenEnum_TestContainsOrNot(PizzaDeliveryStrategy timeUnit) {
    assertTrue(EnumSet.of(PizzaDeliveryStrategy.EXPRESS, PizzaDeliveryStrategy.NORMAL).contains(timeUnit));
}
      
      



  • @MethodSource



    — (passes) , :





static Stream<String> wordDataProvider() {
    return Stream.of("foo", "bar");
}

@ParameterizedTest
@MethodSource("wordDataProvider")
void givenMethodSource_TestInputStream(String argument) {
    assertNotNull(argument);
}
      
      



  • @CsvSource



    CSV :





@ParameterizedTest
@CsvSource({ "1, Car", "2, House", "3, Train" })
void givenCSVSource_TestContent(int id, String word) {
	assertNotNull(id);
	assertNotNull(word);
}
      
      



, @CsvFileSource



, CSV- classpath, @ArgumentSource



, ArgumentsProvider



.





JUnit 4 @RunWith



, , @Parameter



, .





TestNG @Parameter @DataProvider. XML- @Parameter



:





@Test
@Parameters({"value", "isEven"})
public void 
  givenNumberFromXML_ifEvenCheckOK_thenCorrect(int value, boolean isEven) {
    Assert.assertEquals(isEven, value % 2 == 0);
}
      
      



XML:





<suite name="My test suite">
    <test name="numbersXML">
        <parameter name="value" value="1"/>
        <parameter name="isEven" value="false"/>
        <classes>
            <class name="baeldung.com.ParametrizedTests"/>
        </classes>
    </test>
</suite>
      
      



XML , .





@DataProvider



, .





@DataProvider



:





@DataProvider(name = "numbers")
public static Object[][] evenNumbers() {
    return new Object[][]{{1, false}, {2, true}, {4, true}};
}

@Test(dataProvider = "numbers")
public void givenNumberFromDataProvider_ifEvenCheckOK_thenCorrect
  (Integer number, boolean expected) {
    Assert.assertEquals(expected, number % 2 == 0);
}
      
      



@DataProvider



:





@Test(dataProvider = "numbersObject")
public void givenNumberObjectFromDataProvider_ifEvenCheckOK_thenCorrect
  (EvenNumber number) {
    Assert.assertEquals(number.isEven(), number.getValue() % 2 == 0);
}

@DataProvider(name = "numbersObject")
public Object[][] parameterProvider() {
    return new Object[][]{{new EvenNumber(1, false)},
      {new EvenNumber(2, true)}, {new EvenNumber(4, true)}};
}
      
      



, , . , Spring.





, TestNG, @DataProvider



, .





7. -

- , , . JUnit, TestNG -. JUnit 5 - :





@Test
public void givenExecution_takeMoreTime_thenFail() throws InterruptedException {
    Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(10000));
}
      
      



JUnit 4 TestNG , @Test (timeout = 1000)





@Test(timeOut = 1000)
public void givenExecution_takeMoreTime_thenFail() {
    while (true);
}
      
      



8.

TestNG . , , , , , JUnit.





, , :





@Test
public void givenEmail_ifValid_thenTrue() {
    boolean valid = email.contains("@");
    Assert.assertEquals(valid, true);
}

@Test(dependsOnMethods = {"givenEmail_ifValid_thenTrue"})
public void givenValidEmail_whenLoggedIn_thenTrue() {
    LOGGER.info("Email {} valid >> logging in", email);
}
      
      



9.

JUnit 4 TestNG , . , Java Reflection API. JUnit 4, , .





, @FixMethodOrder



:





@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SortedTests {

    @Test
    public void a_givenString_whenChangedtoInt_thenTrue() {
        assertTrue(
          Integer.valueOf("10") instanceof Integer);
    }

    @Test
    public void b_givenInt_whenChangedtoString_thenTrue() {
        assertTrue(
          String.valueOf(10) instanceof String);
    }

}
      
      



MethodSorters.NAME_ASCENDING



. , MethodSorter.DEFAULT



MethodSorter.JVM



.





TestNG . priority



() @Test:





@Test(priority = 1)
public void givenString_whenChangedToInt_thenCorrect() {
    Assert.assertTrue(
      Integer.valueOf("10") instanceof Integer);
}

@Test(priority = 2)
public void givenInt_whenChangedToString_thenCorrect() {
    Assert.assertTrue(
      String.valueOf(23) instanceof String);
}
      
      



, priority



, , .





TestNG , . dependsOnMethods



@Test, .





10.

, , IDE. JUnit 5 , @DisplayName



.





, :





@ParameterizedTest
@ValueSource(strings = { "Hello", "World" })
@DisplayName("Test Method to check that the inputs are not nullable")
void givenString_TestNullOrNot(String word) {
    assertNotNull(word);
}
      
      



, , .





TestNG .





11.

JUnit, TestNG — Java.





.





TestNG junit-5 Github.






"Java QA Automation Engineer".





« PageObject».








All Articles