Поскольку мы создаем программное обеспечение, мы всегда хотим, чтобы оно работало по-разному с другим набором данных. Когда дело доходит до тестирования одного и того же программного обеспечения, мы не можем быть несправедливыми, если протестируем его только одним набором данных. Здесь мы снова должны убедиться, что наша система принимает весь набор комбинаций, которые она должна поддерживать.
Здесь идет Параметризация на картинке. Чтобы передать несколько данных приложению во время выполнения, нам необходимо параметризовать наши тестовые сценарии.
Эта концепция, которую мы достигаем путем параметризации, называется Data Driven Testing.
В этом уроке вы узнаете
- Тип параметризации в TestNG-
- Аннотация параметров с Testng.xml
- Поиск проблемы
- Параметры с использованием Dataprovider
- Вызвать DataProvider из другого класса
- Типы параметров в Dataprovider
Тип параметризации в TestNG-
Чтобы сделать параметризацию более понятной, мы рассмотрим параметры параметризации в одной из самых популярных платформ для Selenium Webdriver — TestNG .
Есть два способа достижения параметризации в TestNG
Параметры из Testng.xml могут быть комплектом или уровнем тестирования
Параметр из DataProvider может принимать Method и ITestContext в качестве параметра.
Давайте изучим их подробно —
Аннотация параметров с Testng.xml
Выберите параметризацию, используя аннотации, если вы хотите справиться со сложностью, а количество входных комбинаций меньше.
Давайте посмотрим, как это работает
Тестовый сценарий
Шаг 1) Запустите браузер и перейдите на Google.com
Шаг 2) Введите ключевое слово для поиска
Шаг 3) Убедитесь, что введенное значение совпадает с приведенным в наших тестовых данных.
Шаг 4) Повторяйте 2 и 3, пока все значения не будут введены
Автор теста | SearchKey |
Guru99 | Индия |
Кришна | Соединенные Штаты Америки |
Bhupesh | Китай |
Вот пример того, как это сделать БЕЗ параметров
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)); } }
Исследование, приведенный выше пример. Только представьте, насколько сложным станет код, когда мы сделаем это для 3 входных комбинаций.
Теперь давайте параметризуем это с помощью TestNG
Для этого вам нужно будет
- Создайте файл XML, в котором будут храниться параметры
-
В тесте добавьте аннотацию @Parameters
Вот полный код
Тестовый уровень 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>
ParameterWithTestNGXML.java File
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)); } }
Instructions to run the script, select the XML file and Run as Test NG Suite
Right Click on .xml file -> Run as -> Testng Suite (Note : Suite)
Now, parameters can be defined at 2 levels
- Suite level – The parameters inside the <suite> tag of TestNG XML file will be a suite level parameter.
- Test Level — The parameters inside the <Test> tag of testing XML file will be a Test level parameter.
Here is the same test with suite level parameters
ПРИМЕЧАНИЕ. В случае, если имя параметра на уровне набора и на уровне теста совпадает, параметр уровня тестирования будет иметь преимущество перед уровнем набора. Таким образом, в этом случае все классы внутри этого уровня теста будут иметь общий переопределенный параметр, а другие классы, находящиеся за пределами уровня теста, будут иметь общий параметр уровня набора.
Поиск проблемы
Ошибка # 1 Значение параметра в testng.xml нельзя типизировать с соответствующим параметром метода тестирования, это вызовет ошибку.
Рассмотрим следующий пример
Здесь атрибут ‘author’ равен ‘Guru99’, который является строкой, и в соответствующем методе теста он ожидает целочисленное значение, поэтому здесь мы получим исключение.
Проблема №2 Ваши @Parameters не имеют соответствующего значения в testing.xml.
Вы можете решить эту ситуацию, добавив аннотацию @option в соответствующем параметре в методе теста.
Проблема № 3 : Вы хотите проверить несколько значений одного и того же параметра, используя Testng.xml
Простой ответ: это невозможно! Вы можете иметь несколько разных параметров, но каждый параметр может иметь только одно значение. Это помогает предотвратить жесткое кодирование значений в сценарии. Это делает код многоразовым. Думайте об этом как о конфигурационных файлах для вашего скрипта. Если вы хотите использовать несколько значений для параметра, используйте DataProviders
Параметры с использованием Dataprovider
Аннотация @Parameters проста, но для тестирования с несколькими наборами данных нам нужно использовать поставщик данных.
Чтобы заполнить тысячи веб-форм с помощью нашей среды тестирования, нам нужна другая методология, которая может дать нам очень большой набор данных в одном потоке выполнения.
Эта управляемая данными концепция достигается аннотацией @DataProvider в TestNG.
У него только один атрибут «имя» . Если вы не укажете атрибут name, тогда имя DataProvider будет таким же, как имя соответствующего метода.
Поставщик данных возвращает двумерный объект JAVA в метод test, и метод test будет вызывать M раз в массиве объектов типа M * N. Например, если DataProvider возвращает массив из 2 * 3 объектов, соответствующий тестовый сценарий будет вызываться 2 раза с 3 параметрами каждый раз.
Полный пример
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" } }; } }
Вызвать DataProvider из другого класса
По умолчанию DataProvider находится в том же классе, где находится метод test, или его базовый класс. Чтобы поместить его в какой-то другой класс, нам нужно сделать метод провайдера данных статическим, а в тестовом методе нам нужно добавить атрибут dataProviderClass в аннотации @Test .
Пример кода
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" } }; }}
Типы параметров в Dataprovider
Существует два типа параметров, поддерживаемых методом DataProvider.
Метод. Если один и тот же DataProvider должен вести себя по-разному при использовании другого метода тестирования, используйте параметр Method.
В следующем примере
- Мы проверяем, если имя метода testMethodA.
- Если да, верните один набор значений
- В противном случае верните другой набор значений.
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" } };} } }
Вот вывод
ITestContext — может использоваться для создания различных параметров для тестовых случаев на основе групп.
В реальной жизни вы можете использовать ITestContext для изменения значений параметров в зависимости от методов тестирования, хостов, конфигураций теста.
В следующем примере кода
- У нас есть 2 группы A & B
- Каждый метод испытаний назначается группе
- Если значение группы равно A, возвращается определенный набор данных
- Если значение группы B, возвращается другой набор данных
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; } }
Примечание. Если вы напрямую запустите свой класс testng, он сначала вызовет поставщик данных, который не может получить информацию о группах, поскольку группы недоступны. Но вместо этого, если вы вызовете этот класс через testng.xml, у него будет информация о группах, доступная с помощью ITestContext. Используйте следующий XML для вызова теста
<!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>
Резюме :
- Параметризация требуется для создания Data Driven Testing .
- TestNG поддерживает два вида параметризации, используя @ Parameter + TestNG.xml и используя @DataProvider
-
В @ Parameter + TestNG.xml параметры могут быть размещены на уровне набора и уровня тестирования. Если
Одно и то же имя параметра объявляется в обоих местах; Параметр уровня теста получит преимущество над параметром уровня костюма.
- используя @ Parameter + TestNG.xml, можно установить только одно значение за раз, но @DataProvider возвращает 2d массив Object .
- Если DataProvider присутствует в другом классе, чем в классе, в котором находится тестовый метод, DataProvider должен быть статическим методом .
- DataProvider поддерживает два параметра : Method и ITestContext.