Tietojentarjoaja TestNG: Selenium Parametrisointiesimerkki
⚡ Älykäs yhteenveto
Parametrisointi sisään Selenium suorittaa yhden testimenetelmän toistuvasti eri tietojoukkoja vasten, muuttaen yhden skriptin datalähtöiseksi kattavuudeksi. TestNG tarjoaa tähän kaksi mekanismia: testng.xml-tiedostoon perustuvan @Parameters-annotaation ja kaksiulotteisen objektitaulukon palauttavan @DataProvider-annotaation.

Kun luomme ohjelmistoja, haluamme aina, että ne toimivat oikein erilaisten datajoukkojen kanssa. Kun on kyse testaus Kyseisessä ohjelmistossa yhden tietojoukon tarkistaminen ei riitä. Meidän on varmistettava, että järjestelmä hyväksyy kaikki yhdistelmät, joita sen odotetaan tukevan. Tätä varten meidän on parametroitava testiskriptimme. Tässä kohtaa parametrointi astuu kuvaan.
Parametrisointi sisään Selenium
Parametrisointi sisään Selenium on prosessi testiskriptien parametroimiseksi useiden tietojen välittämiseksi sovellukselle suorituksen aikana. Se on suoritusstrategia, joka suorittaa testitapaukset automaattisesti useita kertoja eri arvoilla. Konseptia, joka saavutetaan parametroimalla testiskriptit, kutsutaan Tietoihin perustuva testaus.
Parametrisoinnin tyyppi sisään TestNG
Parametrisoinnin selkeyttämiseksi käymme läpi parametrisointivaihtoehdot yhdessä suosituimmista viitekehyksistä, jotka on tarkoitettu Selenium WebDriver — TestNG.
On kaksi tapaa jolla voimme saavuttaa parametroinnin TestNG:
- Kanssa Parametrien merkinnät ja TestNG XML tiedosto.
- Kanssa DataProvider merkintä.
Yllä oleva kaavio tiivistää jaon: testng.xml-tiedoston parametrit voidaan määrittää paketti- tai testitasolla, kun taas DataProviderin parametri voi hyväksyä Method ja ITestContext omana argumenttinaan. Tutkitaanpa niitä yksityiskohtaisesti.
Parametrit Annotaatio sisään TestNG
Parametrit Annotaatio sisään TestNG on menetelmä, jota käytetään arvojen välittämiseen testimetodeille argumentteina .xml-tiedoston avulla. Käyttäjien on ehkä välitettävä arvot testimetodeille suorituksen aikana. @Parameters-annotaatiometodia voidaan käyttää missä tahansa metodissa, jossa on @Test-, @Before-, @After- tai @Factory-annotaatio.
Parametrien huomautus Testng.xml:llä
Valitse parametrointi annotaatioiden avulla, kun et halua käsitellä monimutkaisuutta ja syöteyhdistelmien määrä on pieni.
Katsotaanpa, miten tämä toimii.
Testiskenaario
Vaihe 1) Käynnistä selain ja siirry osoitteeseen Google.com
Vaihe 2) Kirjoita hakusana
Vaihe 3) Varmista, että syötetty arvo on sama kuin testidatan antama arvo
Vaihe 4) Toista vaiheet 2 ja 3, kunnes kaikki arvot on syötetty
| Testin kirjoittaja | Hakuavain |
|---|---|
| Guru99 | Intia |
| Krishna | Soumi |
| Bhupesh | Kiina |
Tässä on esimerkki siitä, miten se tehdään ilman parametrit:
package parameters; import org.testng.annotations.Test; import org.testng.AssertJUnit; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; public class NoParameterWithTestNGXML { WebDriver driver; @Test public void testNoParameter() throws InterruptedException { String author = "guru99"; String searchKey = "india"; driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); WebElement searchText = driver.findElement(By.name("q")); // Searching text in the Google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); System.out.println("Value in Google Search Box = " + searchText.getDomProperty("value") + " ::: Value given by input = " + searchKey); // Verifying the value in the Google search box AssertJUnit.assertTrue(searchText.getDomProperty("value").equalsIgnoreCase(searchKey)); } }
⚠️ Selenium Vuoden 4 huomautus: Kolme riviä tämän esimerkin alkuperäisessä versiossa ei enää käänny tai ne ovat vanhentuneita nykyisessä versiossa Selenium tiedotteet. System.setProperty("webdriver.gecko.driver", …) on tarpeetonta Selenium 4.6 eteenpäin, koska Selenium Manager selvittää ajuribinääritiedoston automaattisesti. implicitlyWait(10, TimeUnit.SECONDS) ylikuormitus poistettiin vuonna Selenium 4 ja korvattu implicitlyWait(Duration.ofSeconds(10)). getAttribute() oli vanhentunut vuonna Selenium 4.27, joten tekstilaatikon lukeminen käyttää getDomProperty("value")Jokainen alla oleva esimerkki soveltaa samoja kolmea korjausta.
Tutki yllä olevaa esimerkkiä ja kuvittele, kuinka monimutkaiseksi koodista tulee, kun tämä toistetaan kolmella syöteyhdistelmällä.
Parametrisoidaan se nyt käyttämällä TestNGVoit tehdä niin seuraavasti:
- Luo XML-tiedosto, joka tallentaa parametrit
- Lisää testiin annotaatio @Parameters
Tässä on täydellinen koodi.
Testitaso TestNG. Xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://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>
Parametri WithTestNGXML.java tiedosto
package parameters; import org.testng.AssertJUnit; import java.time.Duration; 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 { WebDriver driver; @Test @Parameters({"author", "searchKey"}) public void testParameterWithXML(@Optional("Abc") String author, String searchKey) throws InterruptedException { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); WebElement searchText = driver.findElement(By.name("q")); // Searching text in the Google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); System.out.println("Value in Google Search Box = " + searchText.getDomProperty("value") + " ::: Value given by input = " + searchKey); // Verifying the value in the Google search box AssertJUnit.assertTrue(searchText.getDomProperty("value").equalsIgnoreCase(searchKey)); } }
Suorittaaksesi komentosarjan, valitse XML-tiedosto ja suorita se TestNG sviitti.
Napsauta .xml-tiedostoa hiiren kakkospainikkeella -> Suorita nimellä -> TestNG Sviitti (Huomautus: Sviitti)
Parametrit voidaan määritellä kahdella tasolla:
- Suite-taso — parametrit sisällä
<suite>tagi TestNG XML-tiedostot ovat ohjelmistopaketin tason parametreja. - Testitaso — parametrit sisällä
<test>tagi TestNG XML-tiedostot ovat testitason parametreja.
Tässä on sama testi sviittitason parametreilla:
HUOMAUTUS: Jos parametrin nimi on sama sekä paketin tasolla että testitasolla, testitason parametrilla on etusija paketin ykköstason parametriin nähden. Tässä tapauksessa kaikki kyseisen testitason sisällä olevat luokat jakavat ohitetun parametrin, ja kyseisen testitason ulkopuoliset luokat käyttävät edelleen paketin tasoparametria.
Ongelmien karttoittaminen
Ongelma 1: Testing.xml-tiedoston parametriarvo, jota ei voida tyypittää vastaavan testimetodin parametriksi, aiheuttaa virheen.
Harkitse seuraavaa esimerkkiä:
Tässä 'tekijä'-attribuutti on yhtä kuin 'Guru99', joka on merkkijono, kun taas vastaava testimetodi odottaa kokonaislukuarvoa, joten syntyy poikkeus.
Ongelma 2: @Parameters-parametreillasi ei ole vastaavaa arvoa testng.xml-tiedostossa.
Voit ratkaista tämän lisäämällä @Valinnainen merkintä testimenetelmän vastaavaan parametriin.
Ongelma 3: Haluat testata useita saman parametrin arvoja käyttämällä testng.xml-tiedostoa.
Yksinkertainen vastaus on, että tätä ei voida tehdä. Sinulla voi olla useita eri parametreja, mutta jokainen parametri voi sisältää vain yhden arvon. Tämä estää arvojen kovakoodaamisen skriptiin ja pitää koodin uudelleenkäytettävänä – ajattele sitä skriptisi asetustiedostona. Jos tarvitset useita arvoja yhdelle parametrille, käytä sen sijaan DataProvideria.
Tietojen toimittaja sisään TestNG
Tietojen toimittaja sisään TestNG on menetelmä, jota käytetään, kun käyttäjän on annettava monimutkaisia parametreja. Monimutkaiset parametrit on luotava Java — Tiedon tarjoaja -metodi voi välittää monimutkaisia objekteja, ominaisuustiedostojen objekteja tai tietokannan objekteja. Metodi annotoidaan @DataProvider-tunnisteella ja se palauttaa objektitaulukon.
Parametrit Dataproviderilla
@Parameters-annotaatio on helppo, mutta useiden tietojoukkojen testaamiseen meidän on käytettävä tiedontarjoajaa.
Täyttääksemme tuhansia verkkolomakkeita testauskehyksemme avulla tarvitsemme erilaisen menetelmän, joka pystyy tuottamaan erittäin suuren tietojoukon yhdessä suoritusvirrassa.
Tämä datalähtöinen konsepti saavutetaan siten, että @DataProvider huomautus sisään TestNG.
Siinä on vain yksi attribuutti, 'nimi'Jos et määritä name-attribuuttia, DataProviderin nimi on sama kuin vastaavan metodin nimi.
Tiedontoimittaja palauttaa kaksiulotteinen Java objekti testimetodiin, ja testimetodia kutsutaan M kertaa M×N-objektitaulukolle. Esimerkiksi, jos DataProvider palauttaa taulukon, jossa on 2×3 objektia, vastaava testitapaus kutsutaan kaksi kertaa kolmella parametrilla joka kerta.
Täydellinen esimerkki
package parameters; import java.time.Duration; 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; @BeforeTest public void setup() { // Create the Firefox driver object driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); } /** Test case to verify the Google search box */ @Test(dataProvider = "SearchProvider") public void testMethod(String author, String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); // Search value in the Google search box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); // Verify if the value in the Google search box is correct Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } /** * @return Object[][] where the first column contains 'author' * and the second column contains 'searchKey' */ @DataProvider(name = "SearchProvider") public Object[][] getDataFromDataprovider() { return new Object[][] { { "Guru99", "India" }, { "Krishna", "UK" }, { "Bhupesh", "USA" } }; } }
Kutsu DataProvider eri luokasta
Oletusarvoisesti DataProvider sijaitsee samassa luokassa kuin testimetodi tai sen perusluokassa. Jos haluat sijoittaa sen toiseen luokkaan, tee dataprovider-metodista staattinen ja lisää attribuutti dataProviderClass että @Testata merkintä.
Code esimerkki
TestClass ParameterDataproviderWithClassLevel.java
package parameters; import java.time.Duration; 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; @BeforeTest public void setup() { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); 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 the Google text box searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); // Get text from the search box String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); // Verify if the search box has the 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" } }; } }
Dataproviderin parametrityypit
DataProvider-metodi tukee kahdenlaisia parametreja.
Menetelmä — jos sama DataProviderin tulisi toimia eri tavoin eri testimetodeilla, käytä Method-parametria.
Seuraavassa esimerkissä:
- Tarkistamme, onko metodin nimi testMethodA
- Jos kyllä, palauta yksi arvojoukko
- Muussa tapauksessa palauta toinen arvojoukko
package parameters; import java.lang.reflect.Method; import java.time.Duration; 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; @BeforeTest public void setup() { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); } @Test(dataProvider = "SearchProvider") public void testMethodA(String author, String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); // Print author and search string System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } @Test(dataProvider = "SearchProvider") public void testMethodB(String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); // Print only the search string System.out.println("Welcome ->Unknown user Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } /** The DataProvider returns values based on the test method name */ @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" } }; } } }
Tässä on tuotos:
ITestContext — tätä voidaan käyttää luomaan erilaisia parametreja testitapauksille ryhmien perusteella.
Todellisessa elämässä voit käyttää ITestContextia parametrien arvojen muuttamiseen testimenetelmien, isäntien tai testimääritysten perusteella.
Seuraavassa koodiesimerkissä:
- Meillä on kaksi ryhmää, A ja B
- Jokainen testimenetelmä on määritetty ryhmään
- Jos ryhmän arvo on A, palautetaan yksi tietojoukko
- Jos ryhmän arvo on B, palautetaan toinen tietojoukko.
package parameters; import java.time.Duration; 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; @BeforeTest(groups = {"A", "B"}) public void setup() { driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); driver.get("https://google.com"); } @Test(dataProvider = "SearchProvider", groups = "A") public void testMethodA(String author, String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); System.out.println("Welcome ->" + author + " Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } @Test(dataProvider = "SearchProvider", groups = "B") public void testMethodB(String searchKey) throws InterruptedException { WebElement searchText = driver.findElement(By.name("q")); searchText.sendKeys(searchKey); System.out.println("Welcome ->Unknown user Your search key is->" + searchKey); Thread.sleep(3000); String testValue = searchText.getDomProperty("value"); System.out.println(testValue + "::::" + searchKey); searchText.clear(); Assert.assertTrue(testValue.equalsIgnoreCase(searchKey)); } /** The DataProvider supplies an Object array based on ITestContext */ @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; } }
Huomautus: Jos suoritat TestNG suoraan luokkaan, se kutsuu ensin tiedon tarjoajaa, eikä tarjoaja voi lukea ryhmätietoja, koska ryhmät eivät ole vielä saatavilla. Luokan kutsuminen testng.xml-tiedoston kautta tekee ryhmätiedot saataville ITestContext-tiedoston kautta. Käytä seuraavaa XML-tiedostoa testin suorittamiseen:
<!DOCTYPE suite SYSTEM "https://testng.org/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>
Molemmat mekanismit on nyt käsitelty, joten käytännön kysymys on, kumpaan kannattaa tarttua.
@Parameters vs. @DataProvider: Kumpaa käyttää
Nämä kaksi lähestymistapaa eivät ole keskenään vaihdettavissa. Päätös riippuu siitä, kuinka monta arvoyhdistelmää testi tarvitsee ja mistä nämä arvot ovat peräisin.
| Kriteeri | @Parametrit + testng.xml | @DataProvider |
|---|---|---|
| Arvot parametria kohden | Tasan yksi | Rajoittamaton määrä rivejä |
| Tietolähde | Staattinen teksti XML-tiedostossa | Java koodi, Excel, CSV, tietokanta, API |
| Tuetut tyypit | Merkkijonosta tyypitettyjen arvojen | mitään Java objekti |
| Testien kutsut | Kerran konfiguraatiota kohden | Kerran datariviä kohden |
| Tietojen muuttaminen vaatii | XML-tiedoston muokkaaminen | Lähdekoodin muokkaaminen, usein ei uudelleenkääntämistä |
| Soveltuu parhaiten | Ympäristö- ja määritysarvot, kuten selain, URL, valtakirjat | Datalähtöinen testaus useilla syöteyhdistelmillä |
Käytännössä useimmat paketit käyttävät molempia: @Parameters sisältää ympäristöasetukset, jotka pysyvät vakioina koko ajon ajan, ja @DataProvider toimittaa vaihtelevat liiketoimintatiedot. Kun tietojoukko kasvaa ulos kovakoodatusta taulukosta, seuraava vaihe on sen lukeminen laskentataulukosta.
Testidatan lukeminen Excel-tiedostosta DataProviderin avulla
Kovakoodatut taulukot lakkaavat skaalautumasta, kun testaajat, jotka eivät kirjoita, Java tarve ylläpitää tietoja. Rivien siirtäminen taulukkoon erottaa testidatan testilogiikasta, mikä on käytännöllinen muoto datalähtöinen testausApachen POI lukee työkirjan ja DataProvider muuntaa jokaisen rivin yhdeksi testikutsukseksi.
- Lisää riippuvuus. Sisältää
org.apache.poi:poi-ooxmlMavenissasi tai Gradle rakentaa.ooxmlartefakti käsittelee .xlsx-muotoa; tavallinenpoilukee vain vanhoja .xls-tiedostoja. - Luo työkirja. Sijoita otsikkorivi riville 0 ja yksi testitapaus riviä kohden sen alle, yksi sarake testimetodiargumenttia kohden.
- Lue taulukko taulukkoon. Muuta Object[][] -luokan kokoa rivi- ja solumäärien perusteella, jotta uudet rivit poimitaan ilman koodimuutoksia.
- Palauta se toimittajalta. Testimenetelmän allekirjoitus pysyy täsmälleen ennallaan.
import java.io.FileInputStream; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.testng.annotations.DataProvider; public class ExcelDataProvider { @DataProvider(name = "SearchProvider") public Object[][] readSearchData() throws Exception { FileInputStream file = new FileInputStream("src/test/resources/testdata.xlsx"); Workbook workbook = new XSSFWorkbook(file); Sheet sheet = workbook.getSheetAt(0); // Skip the header row, so subtract one from the physical row count int rows = sheet.getLastRowNum(); int cols = sheet.getRow(0).getPhysicalNumberOfCells(); Object[][] data = new Object[rows][cols]; for (int i = 1; i <= rows; i++) { for (int j = 0; j < cols; j++) { data[i - 1][j] = sheet.getRow(i).getCell(j).getStringCellValue(); } } workbook.close(); file.close(); return data; } }
💡 Vinkki: Puhelu getStringCellValue() vain tekstiksi muotoilluissa soluissa. Numeerinen solu heittää IllegalStateException, mikä on yleisin virhe, kun laskentataulukko sisältää tunnisteita tai summia. Käytä DataFormatter lukeaksesi jokaisen solutyypin merkkijonona tai kytkeäksesi päälle cell.getCellType() ja muuntaa eksplisiittisesti.
Kun data on ulkoistettu, sadan uuden testitapauksen lisäämisestä tuleekin taulukkolaskentaohjelman muokkaus koodinmuutoksen sijaan, ja sama tarjoaja voi syöttää useita testiluokkia palvelimen kautta. dataProviderClass aiemmin näytetty ominaisuus.
















