Πλήρες πλαίσιο αντικειμένου σελίδας -2021

Σε αυτό το σεμινάριο, θα μάθουμε για το μοντέλο αντικειμένου σελίδας και επίσης θα σχεδιάσουμε και θα αναπτύξουμε το πλαίσιο του μοντέλου αντικειμένου σελίδας από την αρχή. 

Είχαμε συζητήσει όλα τα τύποι πλαισίων στο Σελήνιο, συμπεριλαμβανομένου του μοντέλου αντικειμένου σελίδας , εδώ θα περάσαμε σε βάθος.

Πλαίσιο μοντέλου αντικειμένου σελίδας
Ανάπτυξη πλαισίου μοντέλου αντικειμένου σελίδας

Θα σχεδιάσουμε και θα αναπτύξουμε τις παρακάτω δυνατότητες.

Τι είναι το σχέδιο πλαισίου αντικειμένου σελίδας στο Σελήνιο  

Το Μοντέλο Αντικειμένου Σελίδας είναι ένα Μοντέλο Σχεδιασμού για τη δημιουργία Αυτοματισμού δοκιμής Selenium, όπου διανέμουμε ολόκληρη την Εφαρμογή μας υπό δοκιμή σε μικρές σελίδες (μερικές φορές μια ιστοσελίδα θεωρείται ως σελίδα και μερικές φορές ένα τμήμα της Ιστοσελίδας θεωρείται επίσης ως Σελίδα). Κάθε μία από αυτές τις σελίδες αντιπροσωπεύεται ως κλάση Java και οι λειτουργίες των σελίδων γράφονται ως διαφορετικές μέθοδοι στην κλάση Java της αντίστοιχης σελίδας.

Ας υποθέσουμε ότι έχετε μια εφαρμογή Gmail την οποία θα αυτοματοποιήσετε. Ως εκ τούτου, η σελίδα σύνδεσης του Gmail είναι εκεί όπου έχετε λίγες σημαντικές λειτουργίες όπως σύνδεση, δημιουργία λογαριασμού κ.λπ.

Εδώ θα δημιουργήσουμε μια τάξη java ως GmailLoginPage και θα γράψουμε μεθόδους που ονομάζονται performLogin (), createUserAccount κ.λπ. 

Ας υποθέσουμε ότι μόλις συνδεθείτε στο λογαριασμό σας στο Gmail, έχετε πολλές δυνατότητες όπως εισερχόμενα, αντικείμενα αποστολής, κάδο απορριμμάτων κ.λπ. Τώρα εδώ, για κάθε ενότητα, δημιουργείτε μια τάξη Java και διατηρείτε τις λειτουργίες τους ως μεθόδους Java εντός των αντίστοιχων κλάσεων java. 

Γιατί μοντέλο αντικειμένου σελίδας

Το Page Object Model είναι ένα πολύ στιβαρό και προηγμένο μοντέλο σχεδιασμού πλαισίου όπου μπορείτε να φροντίσετε τις παρακάτω περιοχές: 

  • Ασφάλεια βάσης κώδικα αυτοματοποίησης ιστοσελίδων (κάθε λειτουργικότητα και κώδικας ιστοσελίδας δεν εκτίθεται σε άλλη ιστοσελίδα ή κλάση java)
  • Επαναχρησιμοποιήσιμο, δηλαδή μπορείτε να καλέσετε την αντίστοιχη μέθοδο σελίδας χωρίς να την γράψετε "N" αριθμός θέσεων στο πλαίσιο σας.
  • Ο εντοπιστής κάθε σελίδας βρίσκεται σε διαφορετικές τοποθεσίες (διεπαφές επιπέδου σελίδας ή χρησιμοποιώντας σελίδα εργοστασίου, οπότε σε περίπτωση που υπάρχουν νέοι εντοπιστές για αυτήν τη σελίδα ή αλλάξετε εντοπισμό, μπορείτε απλώς να μεταβείτε στην αντίστοιχη περιοχή εντοπιστών σελίδων και να την αλλάξετε, και αυτό θα αντικατοπτρίζεται στις μεθόδους κλήσης όπου καλούν πάντα οι εντοπιστές)
  • Εύκολο εντοπισμό σφαλμάτων λόγω των παραπάνω χαρακτηριστικών
  • Εύκολη συντήρηση.
  • Με δυνατότητα κλιμάκωσης: Μπορείτε να ενσωματώσετε ένα ευρύ φάσμα εργαλείων / πελατών μαζί με το πλαίσιο μοντέλου αντικειμένου σελίδας και να βελτιώσετε και να κλιμακώσετε το πλαίσιο μοντέλου αντικειμένου σελίδας σας για να αυτοματοποιήσετε περιπτώσεις υπερκρίσιμης χρήσης. 

Δομή πλαισίου υβριδικού αντικειμένου σελίδας

Στο προηγούμενο σεμινάριο, καταλάβαμε το υβριδικό μοντέλο αντικειμένου σελίδας, και τώρα θα σχεδιάσουμε και θα αναπτύξουμε ένα πλαίσιο.

Η αρχιτεκτονική του πλαισίου μοντέλου αντικειμένου σελίδας

Μπορούμε απλά να δημιουργήσουμε ένα έργο maven και να ενσωματώσουμε τις εξαρτήσεις στο αρχείο POM.xml που απαιτείται για το πλαίσιο αρχικά που μοιάζει με αυτό: 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>demo</groupId>
	<artifactId>DemoAutomation</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>DemoAutomation</name>
	<url>http://maven.apache.org</url>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.0</version>
				<configuration>
					<source>7</source>
					<target>7</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.4.2</version>
				<configuration>
					<suiteXmlFiles>
						<suiteXmlFile>testNg.xml</suiteXmlFile>
					</suiteXmlFiles>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<reporting>
		<plugins>
			<plugin>
				<groupId>org.reportyng</groupId>
				<artifactId>reporty-ng</artifactId>
				<version>1.2</version>
				<configuration>
				    <outputdir>/target/testng-xslt-report</outputdir>
				    <sorttestcaselinks>true</sorttestcaselinks>
			            <testdetailsfilter>FAIL,SKIP,PASS,CONF,BY_CLASS</testdetailsfilter>
				    <showruntimetotals>true</showruntimetotals>
				</configuration>
			</plugin>
		</plugins>
	</reporting>
	<dependencies>
		<dependency>
			<groupId>org.seleniumhq.selenium</groupId>
			<artifactId>selenium-server</artifactId>
			<version>2.53.0</version>
		</dependency>
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>6.8.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.8</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.8</version>
		</dependency>

		<dependency>
			<groupId>com.googlecode.json-simple</groupId>
			<artifactId>json-simple</artifactId>
			<version>1.1</version>
		</dependency>

		<dependency>
			<groupId>net.sourceforge.jexcelapi</groupId>
			<artifactId>jxl</artifactId>
			<version>2.6</version>
		</dependency>
	</dependencies>
</project>

Μετά από αυτό, θα δημιουργήσουμε μικρές ενότητες και βοηθητικά προγράμματα, όπου έχουμε επισυνάψει αυτό το στιγμιότυπο παρακάτω για να παρέχουμε υψηλού επιπέδου πληροφορίες / προβολή. Θα φτιάξουμε βοηθητικά προγράμματα ένα προς ένα. 

Δομή πλαισίου μοντέλου αντικειμένου σελίδας Selenium

Ακολουθούν οι παρακάτω ενότητες που θα αναπτύξουμε. παρέχουμε το απόσπασμα κώδικα για το ίδιο: 

DriverUtils - Πλαίσιο μοντέλου αντικειμένου σελίδας

Αυτή η ενότητα παρέχει όλα τα βοηθητικά προγράμματα και υποστήριξη για συνεργασία με τα διάφορα προγράμματα περιήγησης (Chrome, Firefox, κ.λπ.). Αυτό το βοηθητικό πρόγραμμα βασίζεται στο εργοστασιακό σχέδιο, όπως συζητήσαμε στο προηγούμενο σεμινάριο εδώ.

package com.base.driverUtils;

import org.openqa.selenium.WebDriver;

public interface IDriver {

  public WebDriver init(String browserName);
}

Εφαρμογή Localdriver, η οποία θα εκτελεστεί τοπικά με το Selenium Webdriver:

package com.base.driverUtils;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;

public class LocalDriver implements IDriver {

  public WebDriver init(String browserName) {
     switch (browserName) {
     case "firefox":
        return new FirefoxDriver();

     case "chrome":
        System.setProperty("webdriver.chrome.driver",
              "..\\DummyAutomation\\DriverExe\\chromedriver.exe");
        return new ChromeDriver();

     case "ie":
        System.setProperty("webdriver.ie.driver",
              "..\\DummyAutomation\\DriverExe\\IEDriverServer.exe");
        return new InternetExplorerDriver();
     default:
        return new FirefoxDriver();
     }
  }

}

Remote Webdriver: Για να εργαστείτε με ένα απομακρυσμένο πρόγραμμα οδήγησης ιστού (όπως το Selenium Grid), χρειάζεστε μια απομακρυσμένη αναφορά του προγράμματος οδήγησης προγράμματος περιήγησης, η οποία έχει ως εξής: 

package com.base.driverUtils;

import java.net.MalformedURLException;
import java.net.URL;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;

public class RemoteDriver implements IDriver {

  DesiredCapabilities caps;
  String remoteHuburl;

  @Override
  public WebDriver init(String browserName) {
     switch (browserName) {
     case "firefox":
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.firefox());
        } catch (MalformedURLException e2) {
           // TODO Auto-generated catch block
           e2.printStackTrace();
        }
     case "chrome":
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome());
        } catch (MalformedURLException e1) {
           // TODO Auto-generated catch block
           e1.printStackTrace();
        }
     case "ie":
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.internetExplorer());
        } catch (MalformedURLException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
     default:
        try {
           return new RemoteWebDriver(new URL(remoteHuburl), caps.firefox());
        } catch (MalformedURLException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
     }
     return null;
  }
 

}

Κατηγορία οδηγού εργοστασίου: Αυτό μας παρέχει αντικείμενο κλάσης προγράμματος οδήγησης (απομακρυσμένο / τοπικό) για να ξεκινήσουμε τα προγράμματα περιήγησης της επιλογής σας. Θα πάρουμε τον τύπο προγράμματος οδήγησης (τοπικό ή απομακρυσμένο) και το πρόγραμμα περιήγησης (chrome ή firefox κ.λπ.) μέσω του αρχείου διαμόρφωσης (έχουμε χρησιμοποιήσει ένα αρχείο ιδιοτήτων για να διατηρήσουμε τις διαμορφώσεις, τις οποίες θα κοινοποιήσουμε σύντομα)

package com.base.driverUtils;

public class DriverProvider {

  public IDriver getDriver(String typeOfDriverExecution){
     switch(typeOfDriverExecution){
     case "local":
        return new LocalDriver();
     case "remote":
        return new RemoteDriver();
     default :
        return new LocalDriver();
     }
  }
}

Τώρα όπου θέλετε την αναφορά προγράμματος οδήγησης, μπορείτε απλώς να δημιουργήσετε το αντικείμενο του αντικειμένου της εργοστασιακής κατηγορίας (DriverProvider σε αυτήν την περίπτωση) και να ξεκινήσετε την παρουσία προγράμματος περιήγησης προγράμματος οδήγησης.

Εδώ είναι το πολύ βασικό αρχείο ρυθμίσεων. μπορείτε να δημιουργήσετε ένα αρχείο ιδιοτήτων και να αποθηκεύσετε τις τιμές ως εξής: 

modeOfExecution=local
browser=chrome
url=http://www.applicationUrl.com/

DataUtils-Page Object Model Model Framework: 

Έχουμε σχεδιάσει τα βοηθητικά προγράμματα δεδομένων εδώ με το ίδιο πρότυπο εργοστασιακής σχεδίασης που κάναμε από την εφαρμογή των λειτουργικών μονάδων προγράμματος περιήγησης προγράμματος οδήγησης.

Ακολουθεί το παρακάτω απόσπασμα κώδικα για το ίδιο. στο πλαίσιο, δείξαμε εργαλεία Excel και εργαλεία ιδιοτήτων, μπορείτε να βελτιώσετε περισσότερο για να υποστηρίξετε άλλα βοηθητικά προγράμματα δεδομένων, όπως YAML, PDF κ.λπ. 

Η διεπαφή εδώ πηγαίνει έτσι: 

package com.base.dataUtils;

public interface IDataProvider {

  public Object[][] fetchDataSet(String... dataFileInfo);
  public String fetchData(String... dataFileInfo);
}

Εδώ είναι η εφαρμογή για Πάροχος δεδομένων Excel

package com.base.dataUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelDataProvider implements IDataProvider {

  FileInputStream fis = null;
  private static XSSFWorkbook workBook = null;
  private static XSSFCell Cell;
  private static XSSFSheet sheet;

  public static String[][] excelDataSet = null;

  @Override
  public Object[][] fetchDataSet(String... dataFileInfo) {
     String excelFilePath = dataFileInfo[0];
     String excelSheetName = dataFileInfo[1];
     File file = new File(excelFilePath);

     try {
        fis = new FileInputStream(file);
     } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }
     try {
        workBook = new XSSFWorkbook(fis);
     } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }
     sheet = workBook.getSheet(excelSheetName);
     int ci, cj;
     int rowCount = sheet.getLastRowNum();
     int totalCols = sheet.getRow(0).getPhysicalNumberOfCells();
     excelDataSet = new String[rowCount][totalCols - 1];
     ci = 0;
     for (int i = 1; i <= rowCount; i++, ci++) {
        cj = 0;
        for (int j = 1; j <= totalCols - 1; j++, cj++) {

           try {
              excelDataSet[ci][cj] = getCellData(i, j);
           } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
           }
        }
     }
     return excelDataSet;

  }

  public static String getCellData(int RowNum, int ColNum) throws Exception {

     try {

        Cell = sheet.getRow(RowNum).getCell(ColNum);

        int dataType = Cell.getCellType();

        if (dataType == 3) {

           return "";

        }

        else if (dataType == XSSFCell.CELL_TYPE_NUMERIC) {
           int i = (int) Cell.getNumericCellValue();
           return Integer.toString(i);
        }

        else {

           String CellData = Cell.getStringCellValue();

           return CellData;

        }
     } catch (Exception e) {

        throw (e);

     }

  }

  @Override
  public String fetchData(String... dataFileInfo) {
     // TODO Auto-generated method stub
     return null;
  }

}

Πάροχος δεδομένων ιδιοτήτων: 

package com.base.dataUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDataProvider implements IDataProvider {

  FileInputStream fis=null;

  @Override
  public Object[][] fetchDataSet(String... dataFileInfo) {
     // TODO Auto-generated method stub
     return null;
  }

  @Override
  public String fetchData(String... dataFileInfo) {

     String dataValue;
     String pathToFile = dataFileInfo[0];
     String key = dataFileInfo[1];
     Properties properties = new Properties();
     try {
        fis=new FileInputStream(pathToFile);
        properties.load(fis);
     } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }
     dataValue = properties.getProperty(key);
     return dataValue;
  }

}

Η εργοστασιακή κλάση για αυτό το βοηθητικό πρόγραμμα δεδομένων

package com.base.dataUtils;

public class DataHelperProvider {

  public IDataProvider getDataHelperProvider(String typeOfDataHandler) {
     switch (typeOfDataHandler) {
     case "excel":
        return new ExcelDataProvider();
     case "properties":
        return new PropertiesDataProvider();
     }
     return null;

  }
}

Βοηθητικά προγράμματα WebAction -Πλαίσιο μοντέλου αντικειμένου σελίδας

Στα βοηθητικά προγράμματα, γράφουμε όλα τα βοηθητικά προγράμματα που σχετίζονται με τις ενέργειές σας στο Web, όπως (κλικ, πλήκτρα αποστολής, στιγμιότυπα οθόνης κ.λπ.) και μπορούμε να το χρησιμοποιήσουμε στις Μέθοδοι σελίδας για την εκτέλεση ενεργειών ιστού για την επίτευξη των λειτουργιών της σελίδας, όπως συζητήθηκε νωρίτερα σε αυτό το σεμινάριο. 

Ακολουθεί το απόσπασμα κώδικα για τα WebAction Utilities: 

package com.base.webActionHelperUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;


public class WebActionsHelperUtils {

  protected WebDriver driver;

  public WebActionsHelperUtils(WebDriver driver) {

     this.driver = driver;
  }

  public void safeClick(By element) {

     waitForElementToBeClickAble(element, 30);
     driver.findElement(element).click();
  }

  public List<WebElement> getElements(By elements) {
     return driver.findElements(elements);
  }

  public void waitForWebElementsToBeDisplayed(By elements, int timeOuts) {
     WebDriverWait wait = new WebDriverWait(driver, timeOuts);
     wait.until(ExpectedConditions.visibilityOfAllElements(getElements(elements)));
  }

  public void waitForElementToBeClickAble(By element, int timeOutSeconds) {
     WebDriverWait waitForElement = new WebDriverWait(driver, timeOutSeconds);
     waitForElement.until(ExpectedConditions.elementToBeClickable(element));
  }

  public void waitForElementToBeDisplayed(By element, int timeOuts) {
     WebDriverWait wait = new WebDriverWait(driver, timeOuts);
     wait.until(ExpectedConditions.visibilityOfElementLocated(element));
  }

  public void enterTextIntoElement(By element, String textToBeEntered) {
     driver.findElement(element).sendKeys(textToBeEntered);
  }

  public String getText(By element) {
     return driver.findElement(element).getText();

  }

  public String getAttribute(By element, String attribute) {
     return driver.findElement(element).getAttribute(attribute);
  }

  public boolean isSelected(By element) {
     boolean isElementSelected = false;
     if (driver.findElement(element).isSelected() == true) {
        isElementSelected = true;
     }
     return isElementSelected;
  }

  public void clearField(By element) {
     driver.findElement(element).clear();
  }

  public void implicitlyWait(int timeOuts) {
     driver.manage().timeouts().implicitlyWait(timeOuts, TimeUnit.SECONDS);
  }

  public boolean isElementPresent(By element) {
     try {
        driver.findElement(element);
        return true;
     } catch (Exception e) {
        return false;
     }
  }

  public void switchToTab(int indexOfTab) {
     ArrayList<String> tabs = new ArrayList<String>(driver.getWindowHandles());
     driver.switchTo().window(tabs.get(indexOfTab));

  }
}

Utility Page Module-Page Object Model Framework

Όπως γνωρίζουμε, πρέπει να δημιουργήσουμε την κλάση σελίδας και να διατηρήσουμε τις λειτουργίες της σελίδας στις μεθόδους σελίδας, οπότε τώρα ας δημιουργήσουμε τη λειτουργική σελίδα σελίδας για το πλαίσιο σελίδας αντικειμένου σελίδας: 

Κάθε τάξη σελίδων ξανά επεκτείνει τα WebAction Utils που αναπτύξαμε μόλις τώρα και εφαρμόζει τις διεπαφές σελίδας, όπου οι διεπαφές σελίδας δεν είναι τίποτα άλλο από τις διεπαφές για τη διατήρηση των Στοιχείων / εντοπιστών Ιστού της αντίστοιχης σελίδας.

Τώρα γιατί χρειαζόμαστε διασυνδέσεις για την αποθήκευση των εντοπιστών: 

  • Θα μπορούσαμε να χρησιμοποιήσουμε οποιοδήποτε αρχείο ιδιοτήτων / excel για να κρατήσουμε τους εντοπιστές από εκεί, αλλά σε αυτήν την προσέγγιση, πρέπει να πάρουμε τους εντοπιστές κάθε φορά που σκοπεύουμε να το χρησιμοποιήσουμε στις μεθόδους σελίδων όπου η πολυπλοκότητα του χρόνου θα αυξηθεί, οπότε δεν αποθηκεύσαμε το εντοπιστές σε αρχεία. 
  • Θα μπορούσαμε να χρησιμοποιήσουμε την ίδια τάξη (pageclass με εργοστασιακή εφαρμογή σελίδας με σχολιασμό @findBy), αλλά δεν χρησιμοποιήσαμε αυτό το κλασικό μοντέλο αντικειμένου σελίδας επειδή αποθηκεύοντας αντίστοιχους εντοπιστές στις αντίστοιχες τάξεις σελίδων, ο κώδικας θα είναι δυσανάγνωστος και αδέξιος, θέλαμε να διαχωρίσουμε Οι εντοπιστές από τον κώδικα για να διατηρήσουν καθαρή βάση κώδικα και συντηρησιμότητας και εντοπισμού σφαλμάτων και επαναχρησιμοποίησης θα αυξηθούν επίσης σε αυτήν την προσέγγιση.
  • Θα μπορούσαμε να αποθηκεύσουμε τους εντοπιστές σε ξεχωριστές τάξεις, αλλά δεν το κάναμε επειδή καλούσαμε "N" σελίδες εντοπιστών σελίδων, έπρεπε να δημιουργήσουμε τον αριθμό "n" αντικειμένων των ταξινομητών που ταξινομήθηκαν. Ως εκ τούτου θα επηρεαστεί η πολυπλοκότητα του χώρου.

Ως εκ τούτου, χρησιμοποιήσαμε ξεχωριστές διεπαφές για ξεχωριστές εντοπιστές σελίδων για αποθήκευση όπως αυτή η προσέγγιση επιλύουμε όλες τις παραπάνω δηλώσεις προβλημάτων, που είναι η πολυπλοκότητα του χρόνου, η πολυπλοκότητα του χώρου και η καθαρή και διατηρήσιμη βάση κώδικα όπως στις διεπαφές, δεν χρειάζεται να δημιουργήσουμε αντικείμενα για πρόσβαση στους εντοπιστές.

package com.base.pageModules;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import com.base.commonUtils.JSonHandler;
import com.base.webActionHelperUtils.WebActionsHelperUtils;
import com.page.locatorModules.HomePageLocators;

public class HomePage extends WebActionsHelperUtils implements HomePageLocators {

  JSonHandler jsonHandler = new JSonHandler();

  public HomePage(WebDriver driver) {
     super(driver);
     this.driver = driver;
  }

  public void enterSearchdataToSearchField(String searchData) {

     waitForElementToBeClickAble(SEARCH_BOX, 10);
     enterTextIntoElement(SEARCH_BOX, searchData);

  }

  public void navigatToUrl() {
     driver.get(url);
  }

  public void captureSearchSuggestion(String pathToJsonDataStore, String searchData) {
     List<WebElement> elements = getElements(SUGGESTION_BOX);
     jsonHandler.captureAndWriteJsonData(elements, pathToJsonDataStore, searchData);
  }

  public void genericWait(int timeOuts) {
     implicitlyWait(timeOuts);
  }

  public void clikcOnSelectedElement(String option) {
     int optionSelection = Integer.parseInt(option);
     safeClick(By.xpath("//div[@id='s-separator']/following-sibling::div[" + optionSelection + "]"));
  }

}

Ομοίως, μπορείτε να συνεχίσετε να συμπεριλαμβάνετε τις δυνατότητες σελίδας στη σελίδα διαφορετικές μεθόδους σελίδας εντός των αντίστοιχων κατηγοριών σελίδων. 

Εδώ είναι πώς το Διεπαφές εντοπιστών σελίδων μοιάζει : 

package com.page.locatorModules;

import org.openqa.selenium.By;

public interface HomePageLocators {

 
  By SEARCH_BOX=By.id("twotabsearchtextbox");
  By SUGGESTION_BOX=By.xpath("//div[@id='suggestions']/div");
 
}

Τώρα το επόμενο τμήμα, μπορείτε να δημιουργήσετε ένα baseSetUp ή Basetest όπου θέλετε να εκτελέσετε τα μέρη προετοιμασίας / φόρτωσης δεδομένων. Επίσης, θα μπορούσατε να χρησιμοποιήσετε @beforeTest, @beoforeClass μεθόδους σε αυτήν την τάξη και χρησιμοποιήστε τις στις δοκιμαστικές σας τάξεις.

Βασική ρύθμιση Η τάξη μοιάζει με: 

package com.demo.testS;

import org.openqa.selenium.WebDriver;
import org.testng.annotations.DataProvider;

import com.base.dataUtils.DataHelperProvider;
import com.base.dataUtils.IDataProvider;
import com.base.driverUtils.DriverProvider;

public class BaseSetUp {

	public WebDriver driver;
	DriverProvider browserProvider = new DriverProvider();
	DataHelperProvider datahelperProvider = new DataHelperProvider();
	IDataProvider dataProvider = datahelperProvider.getDataHelperProvider("properties");
	IDataProvider dataProviderExcel = datahelperProvider.getDataHelperProvider("excel");
	public final String configProperties = "..\\DummyAutomation\\TestConfigsData\\config.properties";
	public String url = dataProvider.fetchData(configProperties, "url");
	String modeOfExecution = dataProvider.fetchData(configProperties, "modeOfExecution");
	String browserName = dataProvider.fetchData(configProperties, "browser");
	String pathToJasonDataStore = "..\\DummyAutomation\\ProductJsonData\\";
	String pathToExcelData = "..\\DummyAutomation\\TestConfigsData\\TestData.xlsx";

	public WebDriver getDriver() {
		return driver;
	}

	protected void setDriver() {
		driver = browserProvider.getDriver(modeOfExecution).init(browserName);
	}

	@DataProvider(name = "SearchFunctionality")
	public Object[][] getCityDetails() {
		Object[][] arrayObject = dataProviderExcel.fetchDataSet(pathToExcelData, "DataFeed");
		return arrayObject;
	}
}

Μαθήματα δοκιμής: Όπως θα χρησιμοποιούσαμε το TestNG εδώ, οπότε πρέπει να γράψετε τη μέθοδο @test για την ανάπτυξη του δοκιμαστικού σεναρίου, όπως: 

Ακολουθεί το απόσπασμα κώδικα για τις δοκιμαστικές τάξεις  

package com.demo.testS;

import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.base.pageModules.HomePage;
import com.base.pageModules.SearchPage;

public class DemoTest extends BaseSetUp {

  HomePage homePage;
  SearchPage searchPage;

  @BeforeMethod
  public void setUpTest() {
     setDriver();
     homePage = new HomePage(driver);
     searchPage = new SearchPage(driver);
     homePage.navigatToUrl();
  }

  @Test(dataProvider = "SearchFunctionality")
  public void search(String searchData, String selectOption) {
     homePage.enterSearchdataToSearchField(searchData);
     homePage.genericWait(5);
     homePage.captureSearchSuggestion(pathToJasonDataStore, searchData);
     homePage.clikcOnSelectedElement(selectOption);
     searchPage.clickOnFirstProduct();
     searchPage.switchToProductSpecificPage();
     searchPage.captureProductData(pathToJasonDataStore, searchData);

  }

  @AfterMethod
  public void tearDown() {
     if (driver != null) {
        driver.quit();
     }
  }

}

Αρχείο TestNgXML - Πλαίσιο μοντέλου αντικειμένου σελίδας

Θα χρειαστεί να ορίσετε μια κλάση XML για το testng.xml, το οποίο βασικά είναι ένα πλαίσιο δοκιμής μονάδας και ελέγχει τη ροή του αυτοματισμού σας. μπορείτε να αναφέρετε τα μαθήματα δοκιμών εκεί.

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="test-parameter" parallel="tests" thread-count="3">

<test name="DemoAutomation_TarGet">
<classes>
<class name="com.demo.testS.DemoTest"></class>

</classes>
</test>
</suite>

Έτσι, με αυτές τις δραστηριότητες, το βασικό σας Μοντέλο αντικειμένου σελίδας πλαίσιο πρέπει να είναι έτοιμο τώρα. Εάν θέλετε να επιτύχετε την προηγμένη έκδοση του πλαισίου σας, τότε θα μπορούσατε να ενσωματώσετε τις παρακάτω περιοχές: 

Πλαίσιο μοντέλου αντικειμένου αναφοράς σελίδας αναφοράς

Μπορείτε να χρησιμοποιήσετε οποιαδήποτε διαθέσιμη δυνατότητα αναφοράς, όπως γοητεία, έκταση έκθεσης, έκθεση TestNG ή εκθέσεις εκ των προτέρων χρησιμοποιώντας ELK στοίβα, και ούτω καθεξής 

Για να διατηρήσουμε την απλότητα, παρουσιάζουμε εδώ τη δυνατότητα αναφοράς με την αναφορά Extent, η οποία διαθέτει πολλές δυνατότητες μαζί της και μπορεί να θεωρηθεί ως ενδιάμεσο επίπεδο αναφοράς. 

Πρέπει να δημιουργήσετε μια τάξη για να έχετε τα βοηθητικά προγράμματα για να εργαστείτε με την έκθεση Extent και, ενώ το κάνετε αυτό, πρέπει να εφαρμόσετε το διεπαφή ITestlistener από TestNg; Ο παρακάτω κώδικας δείχνει πώς: 

package com.cyborg.core.generic.reportUtils;

import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.cyborg.core.generic.dataUtils.PropertiesDataUtils;

import io.appium.java_client.android.AndroidDriver;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.Augmenter;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.Reporter;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

public class ExtentReportUtils implements ITestListener {

  String screenShotPath = "";

  static ExtentReports extentReports;
  ExtentHtmlReporter extentHtmlReporter;
  protected ExtentTest extentTest;


  static String pathOfFile = "./configurator.properties";
  PropertiesDataUtils propertiesDataUtils = PropertiesDataUtils.getInstance(pathOfFile);
   Boolean log_to_kibana=Boolean.parseBoolean(PropertiesDataUtils.configDataStore.get("log_to_kibana"));
 
   public void setup() {
     try {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        Date now = new Date();
        String currentTime = simpleDateFormat.format(now);
        extentHtmlReporter = new ExtentHtmlReporter(
              new File(System.getProperty("user.dir") + "_Reports_" + currentTime + ".html"));
        extentHtmlReporter.loadXMLConfig(
              new File(System.getProperty("user.dir") + "/src/test/resources/config/extent-config.xml"));
        extentReports = new ExtentReports();
        extentReports.setSystemInfo("Environment", PropertiesDataUtils.configDataStore.get("Environment"));
        extentReports.setSystemInfo("AppName", PropertiesDataUtils.configDataStore.get("AppName"));
        extentReports.setSystemInfo("ModeOfExecution", PropertiesDataUtils.configDataStore.get("modeOfExecution"));

        extentReports.attachReporter(extentHtmlReporter);
        System.out.println("DONE SETUP FOR extent Report");
     } catch (Exception ex) {
        ex.printStackTrace();
     }
  }

  public void setup(String reportName) {
     extentReports = getExtent(reportName);
  }

  public ExtentReports getExtent(String reportName) {
     if (extentReports != null)
        return extentReports; // avoid creating new instance of html file
     extentReports = new ExtentReports();

     extentReports.attachReporter(getHtmlReporter(reportName));
     return extentReports;
  }

  private ExtentHtmlReporter getHtmlReporter(String reportName) {

     extentHtmlReporter = new ExtentHtmlReporter("./reports/" + reportName + ".html");
     extentHtmlReporter.loadXMLConfig("./src/test/resources/config/extent-config.xml");

     // make the charts visible on report open
     extentHtmlReporter.config().setChartVisibilityOnOpen(true);
     extentHtmlReporter.config().setDocumentTitle(PropertiesDataUtils.configDataStore.get("AppName"));
     extentHtmlReporter.config().setReportName("Regression Cycle");

     // Append the existing report
     extentHtmlReporter.setAppendExisting(false);
     Locale.setDefault(Locale.ENGLISH);
     return extentHtmlReporter;
  }

  public void registerTestMethod(Method method) {
     String testName = method.getName();
     extentTest = extentReports.createTest(testName);

  }

  public void sequenceScreenShot(AndroidDriver driver, String application, String step) {
     try {
        extentTest.addScreenCaptureFromPath(screenshotStepWise(driver, application, step));
     } catch (Exception e) {
        e.printStackTrace();
     }
  }

  public void screenshotAnyCase(ITestResult result, WebDriver driver, String application) {

     String testName = result.getName();
     File file = new File(".");
     String filename = testName + ".png";
     String filepath = null;
     try {
        filepath = file.getCanonicalPath() + "/ScreenShots/" + application + "/" + putLogDate() + filename;
     } catch (IOException e1) {
        e1.printStackTrace();
     }

     if (PropertiesDataUtils.configDataStore.get("run_on_jenkins").equalsIgnoreCase("true"))
        screenShotPath = "job/Cyborg2/" + PropertiesDataUtils.configDataStore.get("build_number")
              + "/artifact/ScreenShots/" + application + "/" + putLogDate() + filename;
     else
        screenShotPath = System.getProperty("user.dir") + "/ScreenShots/" + application + "/" + putLogDate()
              + filename;
     try {
        WebDriver augmentedDriver = new Augmenter().augment(driver);
        File screenshotFile = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(screenshotFile, new File(filepath));
        File reportFile = new File(filepath);
        reportLogScreenshot(reportFile, filename, application);
     } catch (Exception e) {
        Reporter.log("Unable to get the screenshot");
     }
  }

  public String screenshotStepWise(WebDriver driver, String application, String step) throws Exception {

     File file = new File(".");
     String filename = step + ".png";
     String filepath = null;
     try {
        filepath = file.getCanonicalPath() + "/ScreenShots/" + application + "/" + putLogDateWithoutmm() + filename;
     } catch (IOException e1) {
        e1.printStackTrace();
     }

     if (PropertiesDataUtils.configDataStore.get("run_on_jenkins").equalsIgnoreCase("true"))
        screenShotPath = "job/Cyborg2/" + PropertiesDataUtils.configDataStore.get("build_number")
              + "/artifact/ScreenShots/" + application + "/" + putLogDateWithoutmm() + filename;
     else
        screenShotPath = System.getProperty("user.dir") + "/ScreenShots/" + application + "/"
              + putLogDateWithoutmm() + filename;
     try {
        WebDriver augmentedDriver = new Augmenter().augment(driver);
        File screenshotFile = ((TakesScreenshot) augmentedDriver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(screenshotFile, new File(filepath));
     } catch (Exception e) {
        Reporter.log("Unable to get the screenshot");
     }
     return screenShotPath;
  }

  protected void reportLogScreenshot(File file, String fileName, String application) {
     System.setProperty("org.uncommons.reportng.escape-output", "false");
     String absolute = file.getAbsolutePath();
     if (PropertiesDataUtils.configDataStore.get("run_on_jenkins").equalsIgnoreCase("true"))
        absolute = " /job/Cyborg2/" + PropertiesDataUtils.configDataStore.get("build_number")
              + "/artifact/ScreenShots/" + application + "/" + putLogDate() + fileName;
     else
        absolute = System.getProperty("user.dir") + "/ScreenShots/" + application + "/" + putLogDate() + fileName;
     screenShotPath = absolute;

  }

  public void captureStatus(ITestResult result) {
     if (result.getStatus() == ITestResult.SUCCESS) {
        extentTest.log(Status.PASS, "The test method Named as :" + result.getName() + " is PASSED");
        try {
           extentTest.addScreenCaptureFromPath(screenShotPath);
        } catch (IOException e) {

           e.printStackTrace();
        }
     } else if (result.getStatus() == ITestResult.FAILURE) {
        extentTest.log(Status.FAIL, "The test method Named as :" + result.getName() + " is FAILED");
        extentTest.log(Status.FAIL, "The failure : " + result.getThrowable());
        extentTest.log(Status.FAIL, "StackTrace: " + result.getThrowable());
        try {
           extentTest.addScreenCaptureFromPath(screenShotPath);
        } catch (IOException e) {

           e.printStackTrace();
        }
     } else if (result.getStatus() == ITestResult.SKIP) {
        extentTest.log(Status.SKIP, "The test method Named as :" + result.getName() + " is SKIPPED");

     }

  }

  public String putLogDate() {
     Calendar c = new GregorianCalendar();
     c.add(Calendar.DATE, +0);
     Date s = c.getTime();
     String dateString = new SimpleDateFormat("_EEE_ddMMMyyyy_hhmm").format(s);
     return dateString;
  }

  public String putLogDateWithoutmm() {
     Calendar c = new GregorianCalendar();
     c.add(Calendar.DATE, +0);
     Date s = c.getTime();
     String dateString = new SimpleDateFormat("_EEE_ddMMMyyyy_hh").format(s);
     return dateString;
  }

  public void cleanup() {
     extentReports.flush();
  }

  public void onTestStart(ITestResult result) {

     /*
      * try { DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH-mm-ss"); Date
      * date = new Date();
      */
     /*
      * record = new ATUTestRecorder(System.getProperty("user.dir")+"/videos",
      * dateFormat.format(date), false); record.start();
      *//*
         *
         * } catch (ATUTestRecorderException e) { e.printStackTrace(); }
         */

  }

  public void onTestSuccess(ITestResult result) {

     /*
      * try { record.stop(); } catch (Exception e) { e.printStackTrace(); }
      */

     String testDescription = result.getMethod().getDescription();
     String testCaseNumber = testDescription.split("_")[0];
     String testDesc = testDescription.split("_")[1];
     String status = "PASSED";
     String exceptionType = "NA";
     String detailedError = "NA";
    
     String data ="{\n" +
           "   \"testCaseNumber\" : \""+testCaseNumber+"\",\n" +
           "   \"status\" : \""+status+"\",\n" +
           "   \"testDescription\" : \""+testDesc+"\",\n" +
           "   \"exceptionType\" : \""+exceptionType+"\",\n" +
           "   \"detailedError\":\""+detailedError+"\"\n" +
           "   \n" +
           "}";

     

  }

  @Override
  public void onTestFailure(ITestResult result) {
    
     String testDescription = result.getMethod().getDescription();
     String testCaseNumber = testDescription.split("_")[0];
     String testDesc = testCaseNumber.split("_")[1];
     String status = "FAILED";
     String exceptionType = String.valueOf(result.getThrowable().getClass().getSimpleName());
     String detailedError = String.valueOf(result.getThrowable().getMessage());
    
     String data ="{\n" +
           "   \"testCaseNumber\" : \""+testCaseNumber+"\",\n" +
           "   \"status\" : \""+status+"\",\n" +
           "   \"testDescription\" : \""+testDesc+"\",\n" +
           "   \"exceptionType\" : \""+exceptionType+"\",\n" +
           "   \"detailedError\":\""+detailedError+"\"\n" +
           "   \n" +
           "}";

    
     // TODO Auto-generated method stub

  }

  @Override
  public void onTestSkipped(ITestResult result) {
     String testDescription = result.getMethod().getDescription();
     String testCaseNumber = testDescription.split("_")[0];
     String testDesc = testCaseNumber.split("_")[1];
     String status = "SKIPPED";
     String exceptionType = result.getThrowable().getClass().getSimpleName();
     String detailedError = result.getThrowable().getMessage();
    
     String data ="{\n" +
           "   \"testCaseNumber\" : \""+testCaseNumber+"\",\n" +
           "   \"status\" : \""+status+"\",\n" +
           "   \"testDescription\" : \""+testDesc+"\",\n" +
           "   \"exceptionType\" : \""+exceptionType+"\",\n" +
           "   \"detailedError\":\""+detailedError+"\"\n" +
           "   \n" +
           "}";

  }

  @Override
  public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
     // TODO Auto-generated method stub

  }

  @Override
  public void onStart(ITestContext context) {
     // TODO Auto-generated method stub

  }

  @Override
  public void onFinish(ITestContext context) {
     // TODO Auto-generated method stub

  }
}

Συμπέρασμα: Με αυτό ολοκληρώνουμε την ανάπτυξη πλαισίου μοντέλου Σελίδας αντικειμένου Σελενίου μέσω της οποίας μπορείτε να ξεκινήσετε τη δημιουργία του πλαισίου μοντέλου Σελίδας Αντικειμένου και να το φτάσετε στο προχωρημένο επίπεδο, στην επερχόμενη σειρά του σεμιναρίου θα συζητήσουμε περισσότερα σχετικά με τα προηγμένα χαρακτηριστικά του πλαισίου Σελήνιο . Για να περάσετε από τη σειρά του Σεμινάριο σεμινάριο μπορείτε να διαβάσετε εδώ.

Σχετικά με την Debarghya

Myself Debarghya Roy, είμαι ένας μηχανικός ARCHITECT που συνεργάζεται με την εταιρεία Fortune 5 και έναν συνεισφέροντα ανοιχτού κώδικα, έχοντας περίπου 12 χρόνια εμπειρίας / εμπειρίας σε διάφορες τεχνολογίες.
Έχω εργαστεί με διάφορες τεχνολογίες, όπως Java, C #, Python, Groovy, UI Automation (Selenium), Mobile Automation (Appium), API / Backend Automation, Performance Engineering (JMeter, Locust), Security Automation (MobSF, OwAsp, Kali Linux) , Astra, ZAP κ.λπ.), RPA, Αυτοματισμός Μηχανικής Διαδικασίας, Αυτοματισμός Mainframe, Ανάπτυξη Back End με SpringBoot, Kafka, Redis, RabitMQ, ELK stack, GrayLog, Jenkins και επίσης έχοντας εμπειρία σε Cloud Technologies, DevOps κ.λπ.
Ζω στο Μπανγκαλόρ της Ινδίας με τη γυναίκα μου και έχω πάθος για το Blogging, τη μουσική, την κιθάρα και η Φιλοσοφία της ζωής μου είναι η Εκπαίδευση για Όλους που γέννησε το LambdaGeeks. Ας συνδεθούμε μέσω συνδέσμου - https://www.linkedin.com/in/debarghya-roy/

Αφήστε ένα σχόλιο

Η διεύθυνση email σας δεν θα δημοσιευθεί. Τα υποχρεωτικά πεδία σημειώνονται *

Lambda Geeks