junit vs testng what are differences
Komplexné porovnanie medzi rámcami JUnit Vs TestNG. Zahŕňa porovnanie anotácií a porovnanie funkcií s príkladmi:
V predchádzajúcom tutoriáli sme sa naučili anotáciu DisplayName a podmienené vykonávanie testu na základe rôznych kritérií, ako je verzia JRE, premenné prostredia atď. Venovali sme sa tiež dôležitým otázkam týkajúcich sa tejto témy.
Keďže sme sa o JUnite neustále učili v predchádzajúcich tutoriáloch, tento bude pôsobiť ako oddych pre naše publikum, pretože na chvíľu posunieme naše zameranie z JUnit ako jedinej agendy na porovnanie JUnit vs TestNG.
=> Vyskúšajte tu Sprievodcu výcvikom Perfect JUnit.
Čo sa dozviete:
- JUnit Vs TestNG: Porovnanie
- Záver
JUnit Vs TestNG: Porovnanie
Vlastnosti | JUnit | TestNG |
---|---|---|
Časový limit pre testy | Áno | Áno |
Rámec opensource | Áno JUnit je rámec opensource | Áno TestNG je rámec opensource |
Užívatelsky prívetivý | JUnit je distribuovaný do rôznych modulov, napríklad: ? Pre parametrizáciu budete možno potrebovať JUnit Jupiter. ? Vďaka tomu je JUnit mierne ťažkopádny na použitie v porovnaní s TestNG | Všetky funkcie TestNG sa dodávajú v jednom module. Vďaka tomu je TestNG užívateľsky príjemnejší. |
Hlavná podpora IDE ( Príklad: Eclipse, IntelliJ) | Áno Oba podporujú väčšinu IDE rovnako | Áno Oba podporujú väčšinu IDE rovnako |
Implementácia anotácií | Áno JUnit pracuje na anotáciách s malými obmenami pre rôzne funkcie | Áno TestNG pracuje na anotáciách s malými obmenami pre rôzne funkcie |
Implementácia tvrdení | Áno JUnit poskytuje dostatok tvrdení na overenie očakávaných a skutočných výsledkov s určitými variáciami tvrdení v TestNG | Áno TestNG tiež podporuje obrovský zoznam tvrdení pre porovnanie očakávaných a skutočných výsledkov. Okrem toho TestNG poskytuje dva mechanizmy pre tvrdenia - mäkké tvrdenie a tvrdé tvrdenie |
Výnimky | Áno JUnit poskytuje funkciu pre test výnimiek s miernou variáciou na TestNG | Áno TestNG tiež poskytuje funkciu pre test výnimiek |
Parametrizované skúšky | Áno JUnit podporuje parametrizované testy | Áno TestNG podporuje aj parametrizované testy |
Testovacia sada | Áno JUnit podporuje použitie testovacích balíkov | Áno TestNG podporuje aj Test Suite. |
Test závislosti | Nie JUnit nepodporuje funkciu testu závislosti | Áno Toto je pokročilá funkcia v TestNG cez JUnit. Vďaka tejto funkcii je možné určiť jednu metódu ako závislú od druhej, takže metóda bude fungovať až po spustení závislej metódy a potom prejde, inak závislý test nebude fungovať. |
Paralelné vykonávanie testu | Nie Paralelné vykonávanie nie je v JUnit k dispozícii | Áno TestNG podporuje paralelné vykonávanie testov, ale JUnit nie. Existuje TestNG xml, kde je možné nastaviť paralelné vykonávanie |
Integrácia Maven | Áno Oba nástroje podporujú integráciu Maven | Áno Oba nástroje podporujú integráciu Maven |
Implementácia predpokladov | Áno Predpoklady sa používajú na preskočenie testov založených na určitých predpokladoch alebo podmienkach a toto platí iba pre JUnit. | Nie TestNG nepodporuje predpoklady |
Poradie vykonania testu | Áno Junit podporuje poradie vykonania testu. | Áno TestNG podporuje poradie vykonania testu |
Implementácia poslucháčov | Áno JUnit podporuje poslucháčov nie prostredníctvom anotácií, ale prostredníctvom rozhrania Listeners API. | Áno TestNG podporuje poslucháčov prostredníctvom anotácií. |
Ignorovať testy | Áno Oba podporujú deaktiváciu testov, ale JUnit podporuje deaktiváciu testov na vykonanie na základe rôznych podmienok | Áno Oboje podporuje deaktiváciu testov |
Podávanie správ | Áno JUnit musí byť integrovaný do maven na generovanie správ HTML | Áno TestNG má zabudované správy HTML. Môže byť integrovaný aj s maven alebo externými knižnicami správ, ako sú správy ATU alebo Extent |
Porovnanie anotácií
TestNG a JUnit sú rámce na testovanie jednotiek zo sveta Javy. Obe implementujú veľmi bližšie a podobné funkcie. V tejto časti sa pozrieme na niektoré podobnosti pri implementácii niekoľkých funkcií, pričom by sme si pozreli aj niekoľko ďalších funkcií, ktoré sú implementované odlišne v JUnit a TestNG.
# 1) Anotácia skúšobnej metódy
Neexistuje žiadny rozdiel v spôsobe, akým špecifikujeme metódu ako testovaciu metódu v JUnit aj TestNG.
JUnit 5 | TestNG |
---|---|
@Test | @Test |
# 2) Anotácia súvisiaca s balíkom
- Metóda s anotáciou @BeforeSuite sa vykoná jedenkrát pred spustením aktuálnej testovacej sady.
- Táto anotácia je použiteľná iba v TestNG.
JUnit 5 | TestNG |
---|---|
Nepoužiteľné | @BeforeSuite |
# 3) Anotácia metódy pred triedou
Toto je anotácia pre metódu, ktorá sa má vykonať raz pred spustením prvej testovacej metódy v triede.
JUnit 5 | TestNG |
---|---|
@BeforeAll | @BeforeClass |
# 4) Anotácia metódy pred testom
- Táto anotácia sa vykoná raz pred metódami deklarovanými v značke testng.xml.
- Táto anotácia je k dispozícii iba pre TestNG.
JUnit 5 | TestNG |
---|---|
Nepoužiteľné | @BeforeTest |
# 5) Anotácia metódy, ktorá sa má vykonať pred každou metódou s vyvolaním @Test
JUnit 5 | TestNG |
---|---|
@ Predtým každý | @BeforeMethod |
# 6) Anotácia metódy, ktorá sa má vykonať po každej metóde s vyvolaním @Test
JUnit 5 | TestNG |
---|---|
@AfterEach | @AfterMethod |
# 7) Anotácia metódy po teste
- Táto anotácia sa vykoná raz po metódach deklarovaných v značke testng.xml.
- Táto anotácia je k dispozícii iba pre TestNG.
JUnit 5 | TestNG |
---|---|
Nepoužiteľné | @ AfterTest |
# 8) Anotácia metódy po triede
Toto je anotácia pre metódu, ktorá sa má vykonať raz po spustení poslednej testovacej metódy v triede.
JUnit 5 | TestNG |
---|---|
@Po všetkom | @Po hodine |
# 9) Anotácia zakazujúca vykonávanie testovacej metódy.
- JUnit 5 poskytuje anotáciu na zakázanie konkrétneho vykonania testu.
- TestNG poskytuje atribút @Test, t. J. „Povolený“ s boolovskou hodnotou, ktorá rozhoduje o tom, či by bolo vykonávanie metódy zakázané alebo povolené.
JUnit 5 | TestNG |
---|---|
@ignorovať | @Test (povolené = nepravdivé) |
Odkazujú na Výukový program 7 Preskočenie vykonania pochopiť, ako zakázať testy v JUnit4 vs JUnit 5
# 10) Časový limit anotácie
Anotácia je rovnaká pre JUnit 5 a TestNG
JUnit 5 | TestNG |
---|---|
@Test (časový limit = 2 000) | @Test (časový limit = 2 000) |
# 11) Atribút Očakávaná výnimka
- Trieda výnimiek uvádza, že keď sa test vykoná, vyvolá sa výnimka danej triedy.
- Toto je podporované v JUnit aj TestNG so zmenami v spôsobe deklarovania oboch.
JUnit 5 | TestNG | |
---|---|---|
@Test (očakáva sa = NullPointerException.class) | @Test (expectException = NullPointerException.class) |
# 12) Anotácia súvisiaca s balíkom
- Metóda s anotáciou @AfterSuite sa vykoná raz po spustení aktuálnej testovacej sady.
- Táto anotácia je použiteľná iba v TestNG.
JUnit 5 | TestNG |
---|---|
Nepoužiteľné | @AfterSuite |
# 13) Skupinová anotácia
- Anotácia je k dispozícii iba v TestNG.
- Metóda s anotáciou @BeforeGroups sa spustí pred spustením testovacích metód patriacich do konkrétnej skupiny.
JUnit 5 | TestNG | |
---|---|---|
Nepoužiteľné | @BeforeGroups |
- Anotácia je k dispozícii iba v TestNG.
- Metóda s anotáciou @BeforeGroups sa spustí po spustení testovacích metód patriacich do konkrétnej skupiny.
JUnit 5 | TestNG |
---|---|
Nepoužiteľné | @AfterGroups |
# 14) Poznámky týkajúce sa poradia vykonania
JUnit aj TestNG podporujú explicitné nastavenie poradia testov na vykonávanie. Inými slovami, nastavenie priority pre testovacie prípady.
- JUnit 5 má ako vstupný parameter pre anotáciu @TestMethodOrder () so zabudovanou triedou balíka MethodOrderer - Alphanumeric.class alebo OrderAnnotation.class alebo Random.class.
Odkazujú na Výukový program 9 - Príkaz na vykonanie testu Junit ďalšie informácie o nastavení poradia vykonania testu v JUnit.
- TestNG obsahuje atribút ‘priorita’ pre anotáciu @Test, ktorý akceptuje číselnú hodnotu.
JUnit 5 | TestNG |
---|---|
@TestMethodOrder (Alphanumeric.class) | @Test (priorita = 1) |
Základný program pre TestNG a JUnit 4
# 1) TestNG kód
package newtest.com; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.BeforeClass; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.AfterSuite; public class NewTestng { @Test(dataProvider = 'dp') public void f(Integer n, String s) { System.out.println(' * * * * * * *Parameterized method * * * * * * * * * '); System.out.println('Integer '+n+' String '+s); System.out.println(' * * * * * * * * * * * * * * * * '); } @BeforeMethod public void beforeMethod() { System.out.println('Before Method'); } @AfterMethod public void afterMethod() { System.out.println('After Method'); } @DataProvider public Object()() dp() { return new Object()() { new Object() { 1, 'a' }, new Object() { 2, 'b'}, }; } @BeforeClass public void beforeClass() { System.out.println('Before Class'); } @AfterClass public void afterClass() { System.out.println('After Class'); } @BeforeTest public void beforeTest() { System.out.println('Before Test'); } @AfterTest public void afterTest() { System.out.println('After Test'); } @BeforeSuite public void beforeSuite() { System.out.println('Before Suite'); } @AfterSuite public void afterSuite() { System.out.println('After Suite'); } }
Očakávaný výstup:
# 2) Kód JUnit 4
package demo.tests; import static org.junit.Assert.*; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.BeforeClass; import org.junit.AfterClass; public class JunitTest { @Parameterized.Parameters public static Object()() data() { return new Object(3)(0); } @BeforeClass public static void beforeClass() { System.out.println('Before Class'; } @Before public void beforeMethod() { System.out.println('Before Method'); } @Test public void f() { System.out.println(' * * * * * * *test * * * * * * * * * '); int n=10; System.out.println('Integer '+n); System.out.println(' * * * * * * * * * * * * * * * * '); } @After public void afterMethod() { System.out.println('After Method'); } @AfterClass public static void afterClass() { System.out.println('After Class'); } }
Očakávaný výstup:
JUnit 5 vs TestNG: Rozdiel funkcií s príkladmi
# 1) Testovacia sada
- Sada testov je kolekcia testov, čo znamená, že zhŕňame viac testovacích prípadov z viacerých tried.
- Prístup, ktorý TestNG používa, je v porovnaní s prístupom JUnit odlišný a výkonný.
Testovacia sada v JUnit 5
Poďme sa rýchlo pozrieť na to, ako JUnit 5 uplatňuje testovaciu sadu.
Odkazujú na Výukový program 8 - Testovacie sady a filtrovanie jednotiek Testovacie skrinky na lepšie pochopenie implementácie testovacej sady v JUnit 4 a JUnit 5.
@RunWith(JUnitPlatform.class) @SelectClasses({JUnit5TestCase1.class, JUnit5TestCase2.class }) public class JUnitTestSuite { }
Testovacia sada v TestNG
TestNG používa XML ako nasledujúcu šablónu na zabalenie všetkých logicky spojených testovacích tried
# 2) Parametrizovaný test
TestNG aj JUnit umožňujú parametrizáciu testov, čo nie je nič iné ako spustenie rovnakých testov s variáciami údajov.
Parametrizovaný test v JUnit 4
@RunWith(value=Parameterized.class) public class JUnitclass{ int n; public JUnitclass (int num){ this.n=num; } @Parameters public static Iterable data(){ Object()() objectArray =new Object()() {{1},{2},{3}}; returnArrays.asList(objectArray); } @Test public void Junittst(){ System.out.println(“Multiples of 2 are :”+ 2*n); } }
Parametrizovaný test v TestNG
Existujú dva spôsoby, ako môžete použiť parametrizáciu v TestNG
- @Parametre a prechod cez TestNG XML
- Anotácia @DataProvider
a) @Parametre a prechod cez TestNG XML
public class testins{ @Test @Parameters(value=”env_pd”) public void paramEnv(str env_pd){ If(env_pd=”QA”){ url=”definetest.com” } else if(env_pd=”accpt”){ url=”defineacc.com” }}}
XML pre to isté
b) Poskytovateľ údajov
Anotácia DataProvider vždy vráti Object () (), čo je pole objektov.
@DataProvider(name='state') public Object()() getDataFromDataprovider(){ return new Object()() { { 'Maharashtra', 'Pune' }, { 'Karnataka', 'Bangalore' }, { 'Kerala', 'Trivandrum' } }; @Test(dataProvider=”state”) public void paramMethd(str stateName, str cityName){ System.out.println(stateName+” ”+cityName); }
# 3) Časový limit
Ak sa konkrétny test nedokončí v stanovenom čase, získa časový limit. V iných prípadoch sa vlákno preruší.
šablóna matice sledovateľnosti požiadaviek s príkladom
Časový limit v JUnit
Existujú rôzne prístupy k implementácii Timeout v JUnit. Sú to:
- Používa sa zvyčajný časový limit s konkrétnymi milisekundami
- Použitie časového limitu s tvrdením
- Používa sa globálny časový limit
Budeme mať podrobný návod zameraný na časový limit pre JUnit 4 a JUnit 5.
Ďalej je uvedený útržok ukazujúci použitie obvyklého časového limitu v JUnit 5:
@Test(timeout = 5000) public void testTimeout() throws InterruptedException { while (true) { } }
Vyššie uvedený časový limit testu po 5 sekundách.
Časový limit v TestNG
TestNG tiež používa jednoduchý spôsob implementácie Timeout:
@Test(timeout = 5000) public void testTimeout() throws InterruptedException { while (true) { } }
# 4) Výnimkový test
Test výnimiek zaisťuje, že keď dôjde k tejto preddefinovanej výnimke, bude elegantne zachytená a upozornená na protokoly.
Test výnimiek v JUnit 4
@Test (expected = NumberFormatException.class) public void converttoint() { Int j=Integer.parseInt(“Four”); }
Pre JUnit 4 a 5 bude existovať samostatný tutoriál, ktorý bude podrobne obsahovať Výnimky.
Výnimočný test v TestNG
Vo vyhlásení o teste výnimiek v TestNG je mierna zmena:
@Test (expectedExceptions = NumberFormatException.class) public void converttoint() { Int j=Integer.parseInt(“Four”); }
# 5) Zakázať test
TestNG aj JUnit umožňujú zakázanie vykonania testu.
Test zakázaný v JUnit 5
@ Zakázaná anotácia, ak sa použije v hornej časti triedy, všetky testy v rámci triedy sa pri vykonaní preskočia. Ak sa použije anotácia nad konkrétnou metódou @Test, daný konkrétny testovací prípad sa pre vykonávanie deaktivuje.
import org.junit.AfterClass; @Disabled('the testcase is under development') public class JUnitProgram {
Zakázaný test v TestNG
TestNG umožňuje testu zakázať vykonávanie testu, keď je atribút „enabled“ anotácie @Test nastavený na hodnotu false a je povolený, ak je atribút nastavený na hodnotu true. Ak musia byť povolené všetky testy v rámci triedy, potom pre každú metódu @Test výslovne označte enabled = true.
Ďalej je uvedený útržok kódu, ktorý demonštruje preskočenie testu.
@Test(enabled=false) public void f_validate(){ // let us skip this function}
# 6) Skupinové testy
Na viacerých stránkach a fórach sa vyskytli protichodné vyhlásenia, kde sa ľudia zmienili o tom, že JUnit nikdy nepodporoval zoskupovanie testov s konkrétnym názvom skupiny.
ktorá vrstva modelu osi pracuje s rámami?
Anotácie @BeforeGroups a @AfterGroups prichádzajú iba s TestNG, avšak zoskupenie je povolené v JUnit 4 aj v JUnit 5. Tu si rýchlo ukážeme použitie skupinových testov v JUnit 5. Skupinové testy sa v JUnit 4 a tagy označujú ako Kategórie. v JUnit 5.
Môžete sa odvolať na Výukový program 8 - Testovacie balíčky JUnit a testy filtrovania pre podrobnosti o použití v JUnit.
Skupinové testy v JUnit 5
@Tag(“Regression”) @Test public void junitMethod1(){} @Tag(“SmokeTest”) @Test public void junitMethod2(){
Fragment kódu z JUnit5TestSuite.java:
Nasledujúci kód obsahuje skupinu s názvom „Regresia“ a vylučuje skupinu „SmokeTest“, ktorá odvodzuje, že program junitMethod1 () bude spustený, avšak junitMethod2 () je vylúčený.
@RunWith(JUnitPlatform.class) @SelectPackages({“demo.tests“}) @IncludeTags(“Regression”) @ExcludeTags(“SmokeTest”) public class JUnit5TestSuite { }
Skupinové testy v TestNG
Ak sa vyššie uvedený úryvok musí interpretovať v TestNG, nižšie je uvedený jeho kód:
@Test(groups={“Regression” }) public void junitMethod1(){} @Test(groups={“SmokeTest” }) public void junitMethod2(){}
TestNG XML je nasledujúci:
Metódy regresnej skupiny sú tu zahrnuté do bežca, zatiaľ čo zvyšok skupín vrátane SmokeTestu je vylúčený.
# 7) Paralelné testy
Toto je funkcia, ktorá je k dispozícii iba s TestNG. Testovacie prípady sú zvyčajne druhom vlákien, ktoré sa vyvolávajú jeden za druhým. Ak si však prajete ušetriť čas vykonania, môžete to v TestNG ovládať nastavením paralelného spustenia testov a zadaním počtu vlákien, ktoré je potrebné spustiť naraz.
V krátkosti si ukážeme použitie závisí od metód a nebudeme diskutovať o závislosti od skupín.
Závislý test na inej metóde sa nastavuje prostredníctvom TestNG XML nasledovne:
# 8) Závislé testy
Závislé testy sú pokročilé funkcie dostupné iba s TestNG. Závislosti môžu byť na teste alebo na skupine.
@Test mytest1(){ System.out.println(“My test : mytest1”); } @Test (dependensOnMethods={“mytest1”}) public void mytest2(){ System.out.println(“My test : mytest2”); }
Pretože vo vyššie uvedenom programe závisí mytest2 od mytest1, najskôr sa spustí mytest1 a potom sa spustí mytest2. Ak test mytest1 zlyhá, test mytest2 nebude vyvolaný. Takto je možné preddefinovať závislé testovacie prípady na riadenie konkrétneho pracovného toku, ktorý chcete vykonať.
# 9) Poslucháči
Poslucháči počúvajú každú udalosť, ktorá sa vyskytne v rámci testov. Poslucháči sú podporovaní v JUnit aj TestNG. Takže ak chcete vykonať určité úlohy alebo zobraziť konkrétnu správu v denníku pred začiatkom testu, po jeho ukončení, preskočení testu, absolvovaní alebo neúspešnosti testu, máme tieto funkcie poslucháča, ktoré nám umožňujú to urobiť
JUnit používa triedu Listener a TestNG používa rozhranie Listener. TestNG napíše triedu poslucháča definujúcu metódy rozhrania poslucháča a druhým krokom je zavolať tento názov triedy poslucháča pomocou anotácie @Listeners v hlavnej triede.
JUnit tiež dedí metódy z rodičovskej triedy poslucháča, po ktorej je definovaná trieda bežca poslucháča na použitie funkcií poslucháča na jednu alebo viac hlavných tried.
Poslucháč v TestNG
Existuje rozhranie ITestListener, z ktorého je implementovaný TestNG.
Ďalej uvádzame metódy, ktoré je potrebné definovať pri implementácii ITestListener -
- OnTestStart ()
- OnTestFailure ()
- OnTestSuccess ()
- OnTestSkipped ()
- OnStart ()
- OnFinish ()
Ďalej je uvedený útržok kódu demonštrujúci metódy onTestStart () a onTestSuccess ().
import org.testng.ITestListener; import org.testng.ITestResult; public class TestListener implements ITestListener { @Override public void onTestStart(ITestResult result) { System.out.println('Execution started: '+result.getName()); } @Override public void onTestSuccess(ITestResult result) { System.out.println('Test Passed '+result.getName()); }
Zavolajte túto triedu poslucháča vo svojej hlavnej triede, ako je zobrazené nižšie, pomocou anotácie @Listener:
import org.testng.annotations.Listeners; import org.testng.annotations.Test; @Listeners(com.javatpoint.Listener.class) public class MymainClass { @Test public void sum() {
Poslucháč v JUnit 5
RunListener je trieda, ktorú je potrebné rozšíriť o vašu triedu poslucháčov, aby ste mohli definovať funkcie poslucháča.
Pre JUnit máme nasledujúce metódy:
- testRunStarted
- testRunFinished
- testFailure
- tesIgnorované
import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; public class Mylistenerclass extends RunListener { public void testRunStarted(Description desc) throws java.lang.Exception { System.out.println('Execution started' + desc.getMethodName()); } public void testRunFinished(Description desc) throws java.lang.Exception { System.out.println('Execution finished' + desc.getMethodName()); }
Na vyvolanie vyššie uvedenej triedy poslucháčov musí byť vytvorená trieda spustenia poslucháča.
Triedu poslucháča Mylistener môžete použiť na viac tried pomocou testovacích metód.
public class ListenerRunner { public static void main(String() args) { JUnitCore runme = new JUnitCore(); runme.addListener(new ListenerRunner()); runner.run(FirstClass.class, SecondClass.class); }
Záver
V tomto výučbe JUnit Vs TestNG sme porovnali rámce TestNG a JUnit. Naučili sme sa spoločné funkcie podporované v oboch rámcoch, ako aj ďalšie funkcie podporované iba v TestNG. Zdá sa, že v TestNG existuje niekoľko ďalších funkcií, napríklad paralelné vykonávanie a testy závislostí. Väčšina funkcií podporovaných TestNG je k dispozícii aj v JUnit.
Existujú mierne odchýlky, pokiaľ ide o syntax, terminológie v jazykoch JUnit vs TestNG týkajúce sa spoločných funkcií. Tí, ktorí podkopali silu JUnit nad TestNG, by si doteraz uvedomili, tj. JUnit je tiež jedným z výkonných automatizačných rámcov.
Vrátime sa s mnohými ďalšími zaujímavými aspektmi JUnit. Držte sa pripravovaných návodov !!!
Odporúčané čítanie
- Výukový program JUnit pre začiatočníkov - Čo je to Testovanie JUnit
- Zoznam anotácií JUnit: JUnit 4 Vs JUnit 5
- Ako používať anotáciu JUnit 5 @RepeatedTest s príkladmi
- Testovací prípad JUnit Ignore: JUnit 4 @Ignore Vs JUnit 5 @Disabled
- Inštalácia TestNG, základný program a správy
- TestNG anotácie a poslucháči
- Výukový program TestNG: Úvod do rámca TestNG
- Tvrdenia v seléne pomocou rámcov Junit a TestNG