数据驱动
相同的测试脚本使用不同的测试数据来执行,测试数据和测试行为进行了完全的分离,这样的测试脚本设计模式叫做数据驱动。
实行数据驱动测试的步骤如下:
(1)、编写测试脚本,脚本需要支持程序对象、文件或者数据库读入测试数据。
(2)、将测试脚本使用的测试数据存储程序对象、文件或者数据库等外部介质。
(3)、运行脚本,循环调用存储在外部介质的测试数据。
(4)、验证所有的测试结果是否符合期望的结果。
在TestNG中进行数据驱动
测试代码如下:
package cn.om.DataProvider; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.AfterMethod; public class DataProviderTest { private static WebDriver driver; @DataProvider(name="searchWords") public static Object[][] word(){ return new Object[][]{{"蝙蝠侠","主演","迈克尔"},{"超人","导演","唐纳"},{"生化危机","编剧","安德森"}}; } @Test(dataProvider="searchWords") public void dataProviderTest(String searchWord1,String searchWord2,String SearchResult) { driver.get("http://www.sogou.com"); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //在搜索框中输入参数 driver.findElement(By.id("query")).sendKeys(searchWord1+""+searchWord2); driver.findElement(By.id("stb")).click(); //单击搜索按钮后,等待3秒显示搜索结果 try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //判断搜索结果的页面是否包括测试数据中期望的关键词 Assert.assertTrue(driver.getPageSource().contains(SearchResult)); driver.quit(); } @BeforeMethod public void beforeMethod() { System.setProperty("webdriver.firefox.bin", "D:/Mozilla Firefox/firefox.exe"); driver = new FirefoxDriver(); } @AfterMethod public void afterMethod() { driver.quit(); } }
代码解释:
1、测试脚本会自动打开三次浏览器,分别输入三组不同词作为搜索词进行查询,并且三次搜索的结果均断言成功。
2、使用@DataProvider注解,定义当前方法中的返回对象作为测试脚本的测试数据集合,并且将测试数据集合命名为“searchWords”。
3、测试方法中,使用(dataProvider="searchWords")来引入数据。dataProviderTest方法的三个入参分别是使用了searchWords测试数据集中的每个一维数组中的数据进行赋值。这个测试方法会被调用三次,分别使用测试数据集合中的三组数据。
4、Assert.assertTrue(driver.getPageSource().contains(SearchResult));这个代码行用于判断搜索结果的页面中是否包含测试数据中期望的关键词。
使用TestNG和CSV文件进行数据驱动
具体的操作基本跟上面的代码一致,不同点在于,上面的代码中的数据是写死在代码里,而此处则是把数据存储在CSV文件中,需要通过代码读取后存放在Object对象中。
实例代码如下:
package cn.om.DataProvider; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestDataDrivenByCSVFile { private static WebDriver driver; String url = "http://www.sogou.com/"; @DataProvider(name = "testDate") public static Object[][] word() throws IOException { return getTestData("F:\\workspace\\WebDriver API\\testDate.csv"); } @Test(dataProvider = "testDate") public void testDataDrivenByCSVFile(String searchWord1, String searchWord2, String searchResult) { driver.get(url); driver.findElement(By.id("query")).sendKeys(searchWord1 + "" + searchWord2); driver.findElement(By.id("stb")).click(); new WebDriverWait(driver, 10).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver arg0) { // TODO Auto-generated method stub return driver.getTitle().toLowerCase().startsWith("ztree"); } }); System.out.println((String)driver.findElement(By.id("s_footer")).getText()); Assert.assertTrue(driver.getPageSource().contains(searchResult)); } public static Object[][] getTestData(String fileName) throws IOException { List<Object[]> records = new ArrayList<Object[]>(); String record; // 设定UTF-8字符集,使用带缓冲区的字符输入流BufferedReader读取文件内容 BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "UTF-8")); // 忽略读取CSV文件的标题行(第一行) file.readLine(); /* * 遍历读取文件中除第一行外的其他所有行内容 并存储在名为records的ArrayList中 * 每一个recods中存储的对象为一个String数组 */ while ((record = file.readLine()) != null) { String fileds[] = record.split(","); records.add(fileds); } file.close(); // 定义函数返回值,即Object[][] // 将存储测试数据的list转换为一个Object的二维数组 Object[][] result = new Object[(records.size())][]; for (int i = 0; i < records.size(); i++) { result[i] = records.get(i); } return result; } @BeforeMethod public void beforeMethod() { System.setProperty("webdriver.firefox.bin", "D:/Mozilla Firefox/firefox.exe"); driver = new FirefoxDriver(); } @AfterMethod public void afterMethod() { driver.quit(); } }
从上面代码可以看到,@DataProvider注解的方法中,是调用了getTestData方法,从CSV文件中读取数据存放到Object对象里。从而获取测试数据。
使用TestNG、Apache POI和Excel进行数据驱动测试
具体内容基本跟使用CSV进行测试一样,不同点在于,读取Excel文件的内容,借助了Apache POI工具进行读取。
具体代码如下:
package cn.om.DataProvider; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Assert; import org.testng.annotations.AfterMethod; public class TestDataDrivernByExcelFile { WebDriver driver; String url = "http://www.sogou.com/"; @DataProvider(name = "testDate") public static Object[][] word() throws IOException { return getTestData("F:\\workspace\\WebDriver API\\testDate.xls", "Sheet1"); } @Test(dataProvider="testDate") public void testDataDrivernByExcelFile(String searchWord1,String searchWord2,String searchResult) { driver.get(url); driver.findElement(By.id("query")).sendKeys(searchWord1 + "" + searchWord2); driver.findElement(By.id("stb")).click(); new WebDriverWait(driver, 10).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver arg0) { // TODO Auto-generated method stub return driver.getTitle().toLowerCase().startsWith("ztree"); } }); Assert.assertTrue(driver.getPageSource().contains(searchResult)); } @BeforeMethod public void beforeMethod() { System.setProperty("webdriver.firefox.bin", "D:/Mozilla Firefox/firefox.exe"); driver = new FirefoxDriver(); } @AfterMethod public void afterMethod() { driver.quit(); } public static Object[][] getTestData(String fileName, String sheetName) throws IOException { File file = new File(fileName); FileInputStream inputStream = new FileInputStream(file); Workbook workbook = null; // 获取文件名参数的拓展名,判断是.xlsx还是xls String fileExtensionName = fileName.substring(fileName.indexOf(".")); // 如果是.xlsx,则使用XSSFWorkbook对象进行实例化 // 如果是.xls,则使用HSSFWorkbook对象进行实例化 if (fileExtensionName.equals(".xlsx")) { workbook = new XSSFWorkbook(inputStream); } else if (fileExtensionName.equals(".xls")) { workbook = new HSSFWorkbook(inputStream); } else { System.out.println("该文件不是excel文件"); } // 通过sheetName参数,生成sheet对象 Sheet sheet = workbook.getSheet(sheetName); // 获取Excel数据文件sheet1中数据的行数,getLastRowNum方法获取数据的最后一行行号 // getFirstRowNum方法获取数据的第一行行号,相减之后算出数据的行数 // Excel的行号和列号都是从0开始的 int rowCount = sheet.getLastRowNum() - sheet.getFirstRowNum(); // 创建名为records的list对象来存储从Excel中读取的数据 List<Object[]> records = new ArrayList<Object[]>(); //使用两个for循环遍历Excel数据文件的所有数据。(除去第一行的列名称) for (int i = 1; i < rowCount; i++) { Row row = sheet.getRow(i); // 声明一个数组files,用来存储excel数据文件每行数据,数组的大小用getLastCellNum方法来进行动态声明。 String files[] = new String[row.getLastCellNum()]; for (int j = 0; j < row.getLastCellNum(); j++) { files[j] = row.getCell(j).getStringCellValue(); } // 吧files的数据对象存在records中 records.add(files); } Object[][] results = new Object[records.size()][]; for (int i = 0; i < records.size(); i++) { results[i] = records.get(i); } return results; } }
使用MySQL数据库实现数据驱动
前期准备:
(1)、安装mysql数据库(此处使用的是mysql5.5版本)。
(2)、在mysql的安装目录下,找到名为mysql-connector-java-5.1.34-bin.jar的文件,将其添加到eclipse的Build Path里。
(3)、在本地数据库执行create database test创建数据库test.
(4)、执行use test;切换到test数据库,并执行以下sql创建表格。
CREATE TABLE testdata(Movie_Name char(30),Movie_Property char(30),Excpect_result char(30))
(5)、执行如下sql创建数据。
insert into testdata values("功夫","主演","周星驰"); insert into testdata values("超人","主演","克里斯托弗"); insert into testdata values("蝙蝠侠1","女主角","克尔斯滕");
具体测试代码如下:
package cn.om.DataProvider; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestDataDrivenByMysqlDatabase { WebDriver driver; String url; @DataProvider(name = "testData") public static Object[][] words() { return getTestData("testdata"); } @Test(dataProvider = "testData") public void testDataDrivenByMysqlDatabase(String searchWord1, String searchWord2, String searchResult) { driver.get(url); driver.findElement(By.id("query")).sendKeys(searchWord1 + "" + searchWord2); driver.findElement(By.id("stb")).click(); new WebDriverWait(driver, 10).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver arg0) { // TODO Auto-generated method stub return driver.findElement(By.id("s_footer")).getText().contains("搜索帮助"); } }); Assert.assertTrue(driver.getPageSource().contains(searchResult)); } @BeforeMethod public void beforeMethod() { System.setProperty("webdriver.firefox.bin", "D:/Mozilla Firefox/firefox.exe"); driver = new FirefoxDriver(); url = "http://www.sogou.com"; } @AfterMethod public void afterMethod() { driver.quit(); } public static Object[][] getTestData(String tablename) { // 声明mysql数据库驱动 String mysqlDriver = "com.mysql.jdbc.Driver"; // 配置数据库的IP地址,端口,数据库名称,账号,密码 String mysqlUrl = "jdbc:mysql://127.0.0.1:3306/test"; String user = "root"; String password = "root123321"; List<Object[]> records = new ArrayList<Object[]>(); try { // 设定驱动 Class.forName(mysqlDriver); // 声明连接数据库的链接对象,使用数据库服务器的地址,用户名和密码作为参数 Connection connection = DriverManager.getConnection(mysqlUrl, user, password); // 如果数据库连接可用,打印数据库连接成功的信息 if (!connection.isClosed()) { System.out.println("连接数据库成功"); } // 创建statement对象 Statement statement = connection.createStatement(); // 使用函数参数拼接要执行的sql语句,此语句用来获取数据表的所有数据行 String sql ="SELECT * from "+tablename; // 声明ResultSet对象,存取执行sql语句后返回的数据结果集 ResultSet rs = statement.executeQuery(sql); // 声明一个ResultSetMetaData对象 ResultSetMetaData rsMetaDate = rs.getMetaData(); // 获取数据行的列数 int cols = rsMetaDate.getColumnCount(); // 使用next方法遍历数据结果集中的所有数据行 while (rs.next()) { String files[] = new String[cols]; for (int i = 0; i < cols; i++) { files[i] = rs.getString(i + 1); } records.add(files); System.out.println(rs.getString(1) + " " + rs.getString(2) + " " + rs.getString(3)); } rs.close(); connection.close(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } Object[][] results = new Object[records.size()][]; for (int i = 0; i < records.size(); i++) { results[i] = records.get(i); } return results; } }