本系列之前的Selenium文章让您了解了Selenium测试的基本概念。然而,在这篇文章中,我将告诉您如何使用Selenium框架来优化您的代码结构,这将使您更接近成为Selenium认证的专业人员。
什么是Selenium框架?
Selenium框架是一种代码结构,用于简化代码维护,提高代码的可读性。框架涉及将整个代码分解成更小的代码片段,以测试特定的功能。 代码的结构使得“数据集”与将测试web应用程序的功能的实际“测试用例”分开。它的结构也可以是这样的:需要执行的测试用例可以从外部应用程序(如.csv)调用(调用)。
- 数据驱动框架
- 关键字驱动框架
- 混合框架
为什么需要Selenium框架?
如果没有合适的框架,将只有一个测试用例,它将包含整个测试功能。可怕的是,这个单一的测试用例有能力上升到一百万行代码。因此,很明显,如此庞大的测试用例将很难阅读。即使您稍后想要修改任何功能,您也会很难修改代码。 由于实现了一个框架,将产生更小但多个代码片段,有各种好处。
Selenium框架带来的好处
- 增加代码重用
- 提高了代码可读性
- 更高的便携性
- 减少脚本维护
数据驱动框架
Selenium中的数据驱动框架是将“数据集”与实际的“测试用例”(代码)分离的技术。该框架完全依赖于输入的测试数据。测试数据来自外部源,如EXCEL文件、.CSV文件或任何数据库。
因为测试用例与数据集是分开的,所以我们可以轻松地修改特定功能的测试用例,而无需对您的代码进行大规模更改。例如,如果您想修改登录功能的代码,那么您可以直接修改,而不必同时修改同一代码中的任何其他依赖部分。 除此之外,您还可以轻松控制需要测试的数据量。 通过向excel文件(或其他源)添加更多用户名和密码字段,您可以轻松地增加测试参数的数量。 例如,如果我必须检查网页的登录,那么我可以将用户名和密码凭据集保存在Excel文件中,并将凭据传递给代码,以便在单独的Java类文件中对浏览器执行自动化。
将Apache POI与Selenium WebDriver配合使用
WebDriver不直接支持读取Excel文件。因此,我们使用Apache POI来读/写任何Microsoft office文档。您可以从这里下载Apache POI(一组JAR文件)。根据您的需求下载zip文件或tar文件,并将它们与Selenium JAR集放在一起。
主代码和数据集之间的协调将由testng数据提供程序负责,它是ApachePOI JAR文件的一部分。出于演示目的,我创建了一个名为“LoginCredentials”的Excel文件,其中的用户名和密码存储在不同的列中。
请看下面的代码以理解测试用例。这是一个简单的代码,用于测试机票预订应用程序的登录功能。
package DataDriven;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class DDTExcel
{
ChromeDriver driver;
@Test(dataProvider="testdata")
public void DemoProject(String username, String password) throws InterruptedException
{
System.setProperty("webdriver.chrome.driver", "C:UsersVardhanDownloadschromedriver.exe");
driver = new ChromeDriver();
driver.get("http://newtours.demoaut.com/");
driver.findElement(By.name("userName")).sendKeys(username);
driver.findElement(By.name("password")).sendKeys(password);
driver.findElement(By.name("login")).click();
Thread.sleep(5000);
Assert.assertTrue(driver.getTitle().matches("Find a Flight: Mercury Tours:"), "Invalid credentials");
System.out.println("Login successful");
}
@AfterMethod
void ProgramTermination()
{
driver.quit();
}
@DataProvider(name="testdata")
public Object[][] TestDataFeed()
{
ReadExcelFile config = new ReadExcelFile("C:UsersVardhanworkspaceSeleniumLoginCredentials.xlsx");
int rows = config.getRowCount(0);
Object[][] credentials = new Object[rows][2];
for(int i=0;i<rows;i++)
{
credentials[i][0] = config.getData(0, i, 0);
credentials[i][1] = config.getData(0, i, 1);
}
return credentials;
}
}
如果您从上面注意到,我们有一个名为“TestDataFeed()”的方法。在此方法中,我创建了另一个名为“ReadExcelFile”的类的对象实例。在实例化该对象时,我提供了包含数据的myexcel文件的路径。我进一步定义了一个for循环来从excel工作簿中检索文本。但是,为了从给定的页码、列号和行号读取数据,需要调用“ReadExcelFile”类。我的“ReadExcelFile”代码如下。
package DataDriven;
import java.io.File;
import java.io.FileInputStream;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadExcelFile
{
XSSFWorkbook wb;
XSSFSheet sheet;
public ReadExcelFile(String excelPath)
{
try
{
File src = new File(excelPath);
FileInputStream fis = new FileInputStream(src);
wb = new XSSFWorkbook(fis);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
public String getData(int sheetnumber, int row, int column)
{
sheet = wb.getSheetAt(sheetnumber);
String data = sheet.getRow(row).getCell(column).getStringCellValue();
return data;
}
public int getRowCount(int sheetIndex)
{
int row = wb.getSheetAt(sheetIndex).getLastRowNum();
row = row + 1;
return row;
}
}
首先注意我导入的库。我已经导入了Apache POI XSSF_LIBRARY,它们用于读取/写入数据到Excel文件。在这里,我创建了一个构造函数(相同方法的对象)来传递值:Sheetnumber、行号和列号。为了更好地理解这个框架,我请求您浏览一下下面的视频,我在视频中以结构化的方式对此进行了解释。
关键字驱动框架
关键字驱动框架是一种技术,其中要执行的所有操作和指令都与实际测试用例分开编写。 它与数据驱动框架的相似之处在于,要执行的操作再次存储在外部文件(如Excel表格)中。
我所讨论的操作只不过是需要作为测试用例的一部分执行的方法。关键字驱动框架的好处是您可以轻松控制要测试的功能。您可以在Excel文件中指定测试应用程序功能的方法。因此,将只测试Excel中指定的那些方法名称。例如,为了登录到Web应用程序,我们可以在主测试用例中编写多种方法,每个测试用例都将测试某些功能。为了实例化浏览器驱动程序,可以有一种方法,用于找到用户名和口令字段,可以有方法,可以有用于导航到网页的方法,可以有另一种方法等等。
请看下面的代码,以了解框架的外观。如果您不理解,下面代码中注释掉的这些行可以作为解释。
package KeywordDriven;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class Actions
{
public static WebDriver driver;
public static void openBrowser()
{
System.setProperty("webdriver.chrome.driver", "C:UsersVardhanDownloadschromedriver.exe");
driver=new ChromeDriver();
}
public static void navigate()
{
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://newtours.demoaut.com");
}
public static void input_Username()
{
driver.findElement(By.name("userName")).sendKeys("mercury");
}
public static void input_Password()
{
driver.findElement(By.name("password")).sendKeys("mercury");
}
public static void click_Login()
{
driver.findElement(By.name("login")).click();
}
@Test
public static void verify_login()
{
String pageTitle = driver.getTitle();
Assert.assertEquals(pageTitle, "Find a Flight: Mercury Tours:");
}
public static void closeBrowser()
{
driver.quit();
}
}
如您所见,需要测试的不同功能存在于等待调用的不同方法中。现在,基于Excel文件中存在的方法名称,这些方法将从另一个类调用。类似地,为了读取EXCEL文件并返回结果,我编写了另一个类。它们都显示在下面。调用这些方法的类文件如下所示。
package KeywordDriven;
public class DriverScript
{
public static void main(String[] args) throws Exception
{
//Declaring the path of the Excel file with the name of the Excel file
String sPath = "C:UsersVardhanworkspaceSelenium Frameworks DemodataEngine.xlsx";
//Here we are passing the Excel path and SheetName as arguments to connect with Excel file
ReadExcelData.setExcelFile(sPath, "Sheet1");
//Hard coded values are used for Excel row & columns for now
//Hard coded values are used for Excel row & columns for now
//In later chapters we will replace these hard coded values with varibales //This is the loop for reading the values of the column 3 (Action Keyword) row by row
for (int iRow=1;iRow<=7;iRow++)
{
String sActions = ReadExcelData.getCellData(iRow, 1);
//Comparing the value of Excel cell with all the keywords in the "Actions" class
if(sActions.equals("openBrowser"))
{
//This will execute if the excel cell value is 'openBrowser'
//Action Keyword is called here to perform action
Actions.openBrowser();
}
else if(sActions.equals("navigate"))
{
Actions.navigate();
}
else if(sActions.equals("input_Username"))
{
Actions.input_Username();
}
else if(sActions.equals("input_Password"))
{
Actions.input_Password();
}
else if(sActions.equals("click_Login"))
{
Actions.click_Login();
}
else if(sActions.equals("verify_Login"))
{
Actions.verify_login();
}
else if(sActions.equals("closeBrowser"))
{
Actions.closeBrowser();
}
}
}
}
读取Excel值的类文件如下所示。
package KeywordDriven;
import java.io.FileInputStream;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
public class ReadExcelData
{
private static XSSFSheet ExcelWSheet;
private static XSSFWorkbook ExcelWBook;
private static XSSFCell Cell;
//This method is to set the File path and to open the Excel file
//Pass Excel Path and SheetName as Arguments to this method
public static void setExcelFile(String Path,String SheetName) throws Exception
{
FileInputStream ExcelFile = new FileInputStream(Path);
ExcelWBook = new XSSFWorkbook(ExcelFile);
ExcelWSheet = ExcelWBook.getSheet(SheetName);
}
//This method is to read the test data from the Excel cell
//In this we are passing parameters/arguments as Row Num and Col Num
public static String getCellData(int RowNum, int ColNum) throws Exception
{
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
String CellData = Cell.getStringCellValue();
return CellData;
}
}
混合框架
混合框架是一种可以充分利用DataDriven和关键字驱动的Selenium框架的技术。使用本文章中显示的示例,我们可以通过将要执行的方法存储在Excel文件中(关键字驱动方法)并将这些方法名称传递给Java反射类(数据驱动方法)来构建混合框架,而不是在“DriverScript”类中创建ANIF/ELSE循环。 看看下面代码片段中修改后的“DriverScript”类。 这里,不使用多个if/Else循环,而是使用数据驱动的方法从Excel文件中读取方法名称。
package HybridFramework;
import java.lang.reflect.Method;
public class DriverScriptJava
{
//This is a class object, declared as 'public static'
//So that it can be used outside the scope of main[] method
public static Actions actionKeywords;
public static String sActions;
//This is reflection class object, declared as 'public static'
//So that it can be used outside the scope of main[] method
public static Method method[];
public static void main(String[] args) throws Exception
{
//Declaring the path of the Excel file with the name of the Excel file
String sPath = "C:UsersVardhanworkspaceSelenium Frameworks DemodataEngine.xlsx";
//Here we are passing the Excel path and SheetName to connect with the Excel file
//This method was created previously
ReadExcelData.setExcelFile(sPath, "Sheet1");
//Hard coded values are used for Excel row & columns for now
//Later on, we will use these hard coded value much more efficiently
//This is the loop for reading the values of the column (Action Keyword) row by row
//It means this loop will execute all the steps mentioned for the test case in Test Steps sheet
for (int iRow=1;iRow<=7;iRow++)
{
sActions = ReadExcelData.getCellData(iRow, 1);
//A new separate method is created with the name 'execute_Actions'
//You will find this method below of the this test
//So this statement is doing nothing but calling that piece of code to execute
execute_Actions();
}
}
//This method contains the code to perform some action
//As it is completely different set of logic, which revolves around the action only, it makes sense to keep it separate from the main driver script
//This is to execute test step (Action)
private static void execute_Actions() throws Exception
{
//Here we are instantiating a new object of class 'Actions'
actionKeywords = new Actions();
//This will load all the methods of the class 'Actions' in it.
//It will be like array of method, use the break point here and do the watch
method = actionKeywords.getClass().getMethods();
//This is a loop which will run for the number of actions in the Action Keyword class
//method variable contain all the method and method.length returns the total number of methods
for(int i = 0;i<method.length;i++)
{
//This is now comparing the method name with the ActionKeyword value received from the excel
if(method[i].getName().equals(sActions))
{ //In case of match found, it will execute the matched method
method[i].invoke(actionKeywords);
//Once any method is executed, this break statement will take the flow outside of for loop
break;
}
}
}
}
学习安排上
作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。【保证100%免费】
视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。