Data provider & TestNG XML: Parametrering in Selenium(Voorbeeld)
Parametrering in Selenium
Parametrering in Selenium is een proces om de testscripts te parametriseren om tijdens runtime meerdere gegevens door te geven aan de applicatie. Het is een uitvoeringsstrategie waarbij testgevallen automatisch meerdere keren worden uitgevoerd met verschillende waarden. Het concept dat wordt bereikt door het parametriseren van de testscripts wordt genoemd Datagedreven testen.
Type parametrering in TestNG-
Om parametrisatie duidelijker te maken, zullen we de parametrisatie-opties doornemen in een van de meest populaire raamwerken Selenium Webdriver – TestNG.
Er zijn twee manieren waarmee we parametrisering kunnen bereiken TestNG
Parameters van Testng.xml kunnen suite- of testniveau zijn
Parameter van DataProvider kan Method en ITestContext als parameter gebruiken.
Laten we ze in detail bestuderen –
Parameters Annotatie in TestNG
Parameters Annotatie in TestNG is een methode die wordt gebruikt om waarden door te geven aan de testmethoden als argumenten met behulp van een .xml-bestand. Mogelijk wordt van gebruikers gevraagd de waarden tijdens de uitvoering aan de testmethoden door te geven. De annotatiemethode @Parameters kan worden gebruikt in elke methode met de annotatie @Test, @Before, @After of @Factory.
Parameterannotatie met Testng.xml
Selecteer parameterisering met behulp van annotaties wanneer u met complexiteit te maken wilt krijgen en het aantal invoercombinaties beperkt is.
Laten we eens kijken hoe dit werkt
Testscenario
Stap 1) Start de browser en ga naar Google.com
Stap 2) Voer een zoekwoord in
Stap 3) Controleer of de ingevoerde waarde dezelfde is als die uit onze testgegevens
Stap 4) Herhaal 2 en 3 totdat alle waarden zijn ingevoerd
Auteur testen | Zoeksleutel |
---|---|
Guru99 | India |
Krishna | USA |
Bhupesh | China |
Hier is een voorbeeld van hoe u dit kunt doen ZONDER parameters
package parameters; import org.testng.annotations.Test; import org.testng.AssertJUnit; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; public class NoParameterWithTestNGXML { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; @Test public void testNoParameter() throws InterruptedException{ String author = "guru99"; String searchKey = "india"; System.setProperty("webdriver.gecko.driver", driverPath); driver= new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://google.com"); WebElement searchText = driver.findElement(By.name("q")); //Searching text in google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->"+author+" Your search key is->"+searchKey); System.out.println("Thread will sleep now"); Thread.sleep(3000); System.out.println("Value in Google Search Box = "+searchText.getAttribute("value") +" ::: Value given by input = "+searchKey); //verifying the value in google search box AssertJUnit.assertTrue(searchText.getAttribute("value").equalsIgnoreCase(searchKey)); } }
Een studie, het bovenstaande voorbeeld. Stel je eens voor hoe complex de code wordt als we dit doen voor 3 invoercombinaties
Laten we dit nu parametriseren met behulp van TestNG
Om dit te doen, zul je dit moeten doen
- Maak een XML-bestand waarin de parameters worden opgeslagen
-
Voeg in de test de annotatie @Parameters toe
Hier is de volledige code
Test niveau TestNG. Xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="TestSuite" thread-count="3" > <parameter name="author" value="Guru99" /> <parameter name="searchKey" value="India" /> <test name="testGuru"> <parameter name="searchKey" value="UK" /> <classes> <class name="parameters.ParameterWithTestNGXML"> </class> </classes> </test> </suite>
ParameterMetTestNGXML.java-bestand
package parameters; import org.testng.AssertJUnit; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.annotations.Optional; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class ParameterWithTestNGXML { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; @Test @Parameters({"author","searchKey"}) public void testParameterWithXML( @Optional("Abc") String author,String searchKey) throws InterruptedException{ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://google.com"); WebElement searchText = driver.findElement(By.name("q")); //Searching text in google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->"+author+" Your search key is->"+searchKey); System.out.println("Thread will sleep now"); Thread.sleep(3000); System.out.println("Value in Google Search Box = "+searchText.getAttribute("value") +" ::: Value given by input = "+searchKey); //verifying the value in google search box AssertJUnit.assertTrue(searchText.getAttribute("value").equalsIgnoreCase(searchKey)); } }
Instructies om het script uit te voeren, selecteer het XML-bestand en Uitvoeren als Test NG Suite
Klik met de rechtermuisknop op het XML-bestand -> Uitvoeren als -> Testen Suite (Opmerking: Suite)
Nu kunnen parameters op 2 niveaus worden gedefinieerd
- Suiteniveau – De parameters binnen het label van TestNG XML-bestand zal een parameter op suiteniveau zijn.
- Testniveau — De parameters binnen het tag van het testen van het XML-bestand zal een testniveauparameter zijn.
Hier is dezelfde test met parameters op suiteniveau
NOTITIE: Als de parameternaam hetzelfde is op suiteniveau en op testniveau, krijgt de testniveauparameter voorrang op suiteniveau. Dus in dat geval zullen alle klassen binnen dat testniveau de overschreven parameter delen, en zullen andere klassen die zich buiten het testniveau bevinden de parameter op suiteniveau delen.
Troubleshooting
Nummer # 1 De parameterwaarde in testng.xml kan niet worden omgezet naar de parameter van de overeenkomstige testmethode. Dit zal een fout opleveren.
Beschouw het volgende voorbeeld
Hier is het attribuut 'auteur' gelijk aan 'Guru99', wat een string is en in de corresponderende testmethode wordt een geheel getal verwacht, dus we krijgen hier een uitzondering.
Nummer # 2 Uw @Parameters hebben geen overeenkomstige waarde in testen.xml.
U kunt deze situatie oplossen door toe te voegen @optioneel aantekening in de overeenkomstige parameter in de testmethode.
Probleem nr. 3: U wilt meerdere waarden van dezelfde parameter testen met behulp van Testng.xml
Het simpele antwoord is: dit kan niet! U kunt meerdere verschillende parameters hebben, maar elke parameter kan slechts één waarde hebben. Dit helpt bij het voorkomen van hardcoding-waarden in het script. Dit maakt code herbruikbaar. Zie het als configuratiebestanden voor uw script. Als u meerdere waarden voor een parameter wilt gebruiken, gebruikt u DataProviders
Gegevensprovider in TestNG
Gegevensprovider in TestNG is een methode die wordt gebruikt wanneer een gebruiker complexe parameters moet doorgeven. Complexe parameters moeten worden gemaakt van Java zoals complexe objecten, objecten uit property files of uit een database kunnen worden doorgegeven door de data provider methode. De methode is geannoteerd door @DataProvider en retourneert een array van objecten.
Parameters met behulp van Dataprovider
@Parameters-annotatie is eenvoudig, maar om te testen met meerdere gegevenssets moeten we Data Provider gebruiken.
Om duizenden webformulieren te kunnen invullen met ons testframework hebben we een andere methodologie nodig die ons in één enkele uitvoeringsstroom een zeer grote dataset kan opleveren.
Dit datagedreven concept wordt gerealiseerd door @Data provider annotatie in TestNG.
Er is er maar één attribuut naam'. Als u het name-attribuut niet opgeeft, zal de naam van de DataProvider hetzelfde zijn als de corresponderende methodenaam.
Gegevensprovider retourneert een tweedimensionaal JAVA-object aan de testmethode en de testmethode, zal M keer aanroepen in een objectarray van het M*N-type. Als de DataProvider bijvoorbeeld een array van 2*3 objecten retourneert, wordt de bijbehorende testcase 2 keer aangeroepen met telkens 3 parameters.
Compleet voorbeeld
package parameters; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParameterByDataprovider { WebDriver driver; String driverPath = "C:\\geckodriver.exe"; @BeforeTest public void setup(){ //Create firefox driver object System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://google.com"); } /** Test case to verify google search box * @param author * @param searchKey * @throws InterruptedException */ @Test(dataProvider="SearchProvider") public void testMethod(String author,String searchKey) throws InterruptedException{ { WebElement searchText = driver.findElement(By.name("q")); //search value in google searchbox searchText.sendKeys(searchKey); System.out.println("Welcome ->"+author+" Your search key is->"+searchKey); Thread.sleep(3000); String testValue = searchText.getAttribute("value"); System.out.println(testValue +"::::"+searchKey); searchText.clear(); //Verify if the value in google search box is correct Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } } /** * @return Object[][] where first column contains 'author' * and second column contains 'searchKey' */ @DataProvider(name="SearchProvider") public Object[][] getDataFromDataprovider(){ return new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; } }
Roep DataProvider aan vanuit een andere klasse
Standaard bevindt DataProvider zich in dezelfde klasse als de testmethode of in de basisklasse ervan. Om het in een andere klasse te plaatsen, moeten we de dataprovidermethode statisch maken en in de testmethode moeten we een attribuut toevoegen dataProviderClass in @Toets annotatie.
Code Voorbeeld
TestClass-parameterDataproviderWithClassLevel.java
package parameters; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; public class ParameterDataproviderWithClassLevel { WebDriver driver; String driverPath = "C:\\geckodriver.exe"; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://google.com"); } @Test(dataProvider="SearchProvider",dataProviderClass=DataproviderClass.class) public void testMethod(String author,String searchKey) throws InterruptedException{ WebElement searchText = driver.findElement(By.name("q")); //Search text in google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->"+author+" Your search key is->"+searchKey); Thread.sleep(3000); //get text from search box String testValue = searchText.getAttribute("value"); System.out.println(testValue +"::::"+searchKey); searchText.clear(); //verify if search box has correct value Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } }
DataproviderClass.java
package parameters; import org.testng.annotations.DataProvider; public class DataproviderClass { @DataProvider(name="SearchProvider") public static Object[][] getDataFromDataprovider(){ return new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; }}
Soorten parameters in Dataprovider
Er worden twee soorten parameters ondersteund door de DataProvider-methode.
Methode- Als de DEZELFDE DataProvider zou zich anders moeten gedragen met verschillende testmethoden, gebruik de Method-parameter.
In het volgende voorbeeld,
- We controleren of de naam van de methode testMethodA is.
- Zo ja, retourneer één set waarden
- Anders retourneert u nog een set waarden
package parameters; import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParameterByMethodInDataprovider{ WebDriver driver; String driverPath = "C:\\geckodriver.exe"; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://google.com"); } @Test(dataProvider="SearchProvider") public void testMethodA(String author,String searchKey) throws InterruptedException{ WebElement searchText = driver.findElement(By.name("q")); //Search text in search box searchText.sendKeys(searchKey); //Print author and search string System.out.println("Welcome ->"+author+" Your search key is->"+searchKey); Thread.sleep(3000); String testValue = searchText.getAttribute("value"); System.out.println(testValue +"::::"+searchKey); searchText.clear(); //Verify if google text box is showing correct value Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } @Test(dataProvider="SearchProvider") public void testMethodB(String searchKey) throws InterruptedException{ { WebElement searchText = driver.findElement(By.name("q")); //Search text in search box searchText.sendKeys(searchKey); //Print only search string System.out.println("Welcome ->Unknown user Your search key is->"+searchKey); Thread.sleep(3000); String testValue = searchText.getAttribute("value"); System.out.println(testValue +"::::"+searchKey); searchText.clear(); //Verify if google text box is showing correct value Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } } /** * Here DataProvider returning value on the basis of test method name * @param m * @return **/ @DataProvider(name="SearchProvider") public Object[][] getDataFromDataprovider(Method m){ if(m.getName().equalsIgnoreCase("testMethodA")){ return new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } };} else{ return new Object[][] { { "Canada" }, { "Russia" }, { "Japan" } };} } }
Hier is de uitvoer
ITestContext– Het kan worden gebruikt om verschillende parameters voor testgevallen te creëren op basis van groepen.
In het echte leven kunt u ITestContext gebruiken om parameterwaarden te variëren op basis van testmethoden, hosts en configuraties van de test.
In het volgende codevoorbeeld
- We hebben 2 groepen A en B
- Elke testmethode wordt toegewezen aan een groep
- Als de waarde van de groep A is, wordt een bepaalde gegevensset geretourneerd
- Als de waarde van de groep B is, wordt een andere gegevensset geretourneerd
package parameters; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.ITestContext; import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class ParameterByITestContextInDataprovider { WebDriver driver; String driverPath = "C:\\geckodriver.exe"; @BeforeTest(groups={"A","B"}) public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://google.com"); } @Test(dataProvider="SearchProvider",groups="A") public void testMethodA(String author,String searchKey) throws InterruptedException{ { //search google textbox WebElement searchText = driver.findElement(By.name("q")); //search a value on it searchText.sendKeys(searchKey); System.out.println("Welcome ->"+author+" Your search key is->"+searchKey); Thread.sleep(3000); String testValue = searchText.getAttribute("value"); System.out.println(testValue +"::::"+searchKey); searchText.clear(); //verify correct value in searchbox Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } } @Test(dataProvider="SearchProvider",groups="B") public void testMethodB(String searchKey) throws InterruptedException{ { //find google search box WebElement searchText = driver.findElement(By.name("q")); //search a value on it searchText.sendKeys(searchKey); System.out.println("Welcome ->Unknown user Your search key is->"+searchKey); Thread.sleep(3000); String testValue = searchText.getAttribute("value"); System.out.println(testValue +"::::"+searchKey); searchText.clear(); //verify correct value in searchbox Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } } /** * Here the DAtaProvider will provide Object array on the basis on ITestContext * @param c * @return */ @DataProvider(name="SearchProvider") public Object[][] getDataFromDataprovider(ITestContext c){ Object[][] groupArray = null; for (String group : c.getIncludedGroups()) { if(group.equalsIgnoreCase("A")){ groupArray = new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; break; } else if(group.equalsIgnoreCase("B")) { groupArray = new Object[][] { { "Canada" }, { "Russia" }, { "Japan" } }; } break; } return groupArray; } }
Opmerking: Als u uw testng-klasse rechtstreeks uitvoert, zal deze eerst dataprovider aanroepen die geen groepsinformatie kan ophalen omdat groepen niet beschikbaar zijn. Maar als u deze klasse aanroept via testng.xml, zal deze groepsinformatie beschikbaar hebben met ITestContext. Gebruik de volgende XML om de test aan te roepen
<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" > <suite name="test-parameter"> <test name="example1"> <groups> <run> <include name="A" /> </run> </groups> <classes> <class name="parameters.ParameterByITestContextInDataprovider" /> </classes> </test> <test name="example2"> <groups> <run> <include name="B" /> </run> </groups> <classes> <class name="parameters.ParameterByITestContextInDataprovider" /> </classes> </test> </suite>
Samenvatting
- parametrering is nodig om te creëren Datagedreven testen.
- TestNG ondersteunen twee soorten parametrisering, met behulp van @Parameter+TestNG. Xml en gebruiken@Data provider
-
In @Parameter+TestNG. Xml parameters kunnen op suiteniveau en testniveau worden geplaatst. Als
Op beide plaatsen wordt dezelfde parameternaam gedeclareerd; De parameter op testniveau krijgt de voorkeur boven de parameter op pakniveau.
- met behulp van @Parameter+TestNG.xml Er kan slechts één waarde tegelijk worden ingesteld, maar @DataProvider retourneert een 2D-array van objecten.
- Als DataProvider aanwezig is in de andere klasse, dan is de klasse waar de testmethode zich bevindt,Data provider moet statische methode.
- Er worden twee parameters ondersteund door Data provider zijn Methode en ITestContext.