Въведение в TestNG

1. Общ преглед

В тази статия ще представим рамката за тестване на TestNG.

Ще се съсредоточим върху: настройка на рамката, писане на прост тестов случай и конфигурация, изпълнение на теста, генериране на отчети за тестове и едновременно изпълнение на теста.

2. Настройка

Нека започнем с добавяне на зависимостта Maven в нашия файл pom.xml :

 org.testng testng 7.1.0 test 

Най-новата версия може да бъде намерена в хранилището на Maven.

Когато използвате Eclipse, приставката TestNG може да бъде изтеглена и инсталирана от Eclipse Marketplace.

3. Писане на тестов случай

За да напишем тест с помощта на TestNG, просто трябва да анотираме метода на теста с org.testng.annotations .

@Test public void givenNumber_whenEven_thenTrue() { assertTrue(number % 2 == 0); }

4. Тестови конфигурации

Докато пишем тестови случаи, често трябва да изпълним някои инструкции за конфигуриране или инициализация преди тестовите изпълнения, а също и някои почиствания след завършване на тестовете. TestNG предоставя редица функции за инициализация и почистване на ниво метод, клас, група и пакет:

@BeforeClass public void setup() { number = 12; } @AfterClass public void tearDown() { number = 0; }

Методът setup () , коментиран с @BeforeClass анотации, ще бъде извикан преди изпълнението на каквито и да било методи от този тестов клас и tearDown () след изпълнението на всички методи от тестовия клас.

По същия начин можем да използваме анотациите @BeforeMethod, @AfterMethod, @ Before / AfterGroup, @ Before / AfterTest и @ Before / AfterSuite за всяка конфигурация на ниво метод, група, тест и пакет.

5. Изпълнение на теста

Можем да стартираме тестовите случаи с командата "test" на Maven, тя ще изпълни всички тестови случаи, коментирани с @Test, като ги постави в тестов пакет по подразбиране. Също така можем да стартираме тестови случаи от XML файловете на TestNG test suite, като използваме приставката maven-surefire-plugin:

 org.apache.maven.plugins maven-surefire-plugin 2.19.1    src\test\resources\test_suite.xml    

Имайте предвид, че ако имаме множество XML файлове, обхващащи всички тестови случаи, можем да добавим всички от тях в етикета suiteXmlFiles :

  src/test/resources/parametrized_test.xml   src/test/resources/registration_test.xml  

За да стартираме теста самостоятелно, трябва да разполагаме с библиотеката TestNG в пътя на класа и компилирания тест клас заедно с XML конфигурационния файл:

java org.testng.TestNG test_suite.xml

6. Групиране на тестове

Тестовете могат да се провеждат в групи, например от 50 тестови случая 15 могат да бъдат групирани заедно и изпълнени, оставяйки други такива, каквито са.

В TestNG тестовете за групиране в суитите се извършват с помощта на XML файл:

Забележете, че и двата тестови класа RegistrationTest, SignInTest вече принадлежат към един и същи пакет и след като пакетът бъде изпълнен, тестовите случаи в този клас ще бъдат изпълнени.

Освен тестови пакети, можем да създадем и тестови групи в TestNG, където вместо тестови класове методите са групирани заедно. За да направите това, добавете групи параметър в @Test анотация:

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

Нека използваме XML за изпълнение на групите:

Това ще изпълни тестовия метод, маркиран с групова регресия, в класа SummationServiceTest .

7. Параметризирани тестове

Параметризираните модулни тестове се използват за тестване на един и същ код при няколко условия. С помощта на параметризирани модулни тестове можем да настроим метод за тестване, който получава данни от някакъв източник на данни. Основната идея е да се направи методът за единично тестване многократно и да се тества с различен набор от входове.

В TestNG можем да параметризираме тестове, като използваме анотация @ Parameter или @DataProvider . Докато използвате XML файла, коментирайте тестовия метод с @ Параметър:

@Test @Parameters({"value", "isEven"}) public void givenNumberFromXML_ifEvenCheckOK_thenCorrect(int value, boolean isEven) { assertEquals(isEven, value % 2 == 0); }
И предоставете данните с помощта на XML файл:

Използването на данни от 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) { assertEquals(expected, number % 2 == 0); }

@DataProvider за обекти:

@Test(dataProvider = "numbersObject") public void givenNumberObjectFromDataProvider_ifEvenCheckOK_thenCorrect(EvenNumber number) { 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)}}; }

Използвайки това, всеки обект, който трябва да бъде тестван, може да бъде създаден и използван в теста. Това е най-полезно за тестови случаи на интеграция.

8. Пренебрегване на тестови случаи

Понякога искаме да не изпълняваме определен тест, временно по време на процеса на разработка. Това може да стане чрез добавяне на enabled = false в анотацията @ Test :

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

9. Зависими тестове

Нека разгледаме сценарий, при който ако първоначалният тест не успее, всички следващи тестови случаи трябва да бъдат изпълнени и по-скоро да бъдат маркирани като пропуснати. TestNG осигурява тази функция със dependsOnMethods параметър на @Test анотация:

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

Notice that, the login test case depends on the email validation test case. Thus, if email validation fails the login test will be skipped.

10. Concurrent Test Execution

TestNG allows tests to run in parallel or in multi-threaded mode, thus providing a way to test these multi-threaded pieces of code.

You can configure, for methods, classes, and suites to run in their own threads reducing the total execution time.

10.1. Classes and Methods in Parallel

To run test classes in parallel, mention the parallel attribute in the suite tag in XML configuration file, with value classes:

Note that, if we have multiple test tags in the XML file, these tests can also be run in parallel, by mentioning parallel =” tests”. Also to execute individual methods in parallel, mention parallel =” methods”.

10.2. Multi-Threaded Execution of Test Method

Let's say we need to test the behavior of a code when running in multiple threads. TestNG allows to run a test method in multiple threads:

public class MultiThreadedTests { @Test(threadPoolSize = 5, invocationCount = 10, timeOut = 1000) public void givenMethod_whenRunInThreads_thenCorrect() { int count = Thread.activeCount(); assertTrue(count > 1); } }

The threadPoolSize indicates that the method will run in n number of threads as mentioned. The invocationCount and timeOut indicate that the test will be executed multiple times and fail the test if it takes more time.

11. Functional Testing

TestNG се предлага с функции, които могат да се използват и за функционално тестване. Във връзка със Selenium той може да се използва или за тестване на функционалности на уеб приложение, или за тестване на уеб услуги с HttpClient.

Повече подробности за функционалните тестове със Selenium и TestNG можете да намерите тук. Също така още някои неща за интеграционното тестване в тази статия.

12. Заключение

В тази статия разгледахме бързо как да настроим TestNG и да изпълним прост тестов случай, да генерираме отчети, едновременно изпълнение на тестови случаи, а също и малко за функционалното програмиране. За повече функции като зависими тестове, игнориране на тестови случаи, тестови групи и пакети можете да прегледате статията ни за JUnit срещу TestNG тук.

Изпълнението на всички кодови фрагменти може да бъде намерено в Github.