自动化测试模型可以看作自动化测试框架与工具设计的思想。随着自动化测试技术的发展,演化为以下几种模型:
- 线性测试
- 模块化驱动侧式
- 数据驱动测试
- 关键字驱动测试
数据驱动测试
前一篇所讲的模块化驱动测试能够很好的解决脚本重复的问题,但是在针对同一个功能进行不同数据的测试,从而检测测试结果的变化时仍然需要重复地编写测试脚本。于是,数据驱动测试的概念就为解决这类问题而被提出。
我们可以通过读取定义的数组、字典,或者是外部文件(excel、csv、txt、xml等),都可以看作是数据驱动,从而实现数据与脚本的分离,进一步增强脚本的复用性。![图片.png](http://in4.rccchina.com/doc_upload/2018-07-16/201807161503489119.png)
读取txt文件
Java
(ノへ ̄、)这段代码存在一个问题,txt文件中有四组数据,但运行时只执行了三组数据(运行时忽略了一条密码为空的数据)。
data.javapackage PublicMethods;import java.io.*;import java.util.*;public class data { //读取txt文件 public static Map txtData(String fileName) throws IOException { Mapmap = new HashMap (); //存放多个键值对 String[] arryTemp = null; String username = null; String password = null; String s = null; File file = new File(fileName); FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); while((s = br.readLine()) != null) { arryTemp = s.split(","); //将一行数据存入数组 username = arryTemp[0]; //获取账户 password = arryTemp[1]; //获取密码 map.put(username, password); //存储一组账号密码 } return map; }}
share.javapackage PublicMethods;import org.openqa.selenium.By;import org.openqa.selenium.NoAlertPresentException;import org.openqa.selenium.WebDriver;import java.util.Map;import java.util.Set;import org.openqa.selenium.firefox.FirefoxDriver;public class share { private static WebDriver driver; public static WebDriver OpenDriver(String url) { driver = new FirefoxDriver(); driver.get(url); return driver; } public static void UserLogin(WebDriver driver, Map map) throws InterruptedException { Setkeyset = map.keySet(); //获取Map的值 for(String count : keyset) { Thread.sleep(2000); driver.findElement(By.xpath("//*[@id='username']")).sendKeys(count); System.out.println(count); driver.findElement(By.xpath("//*[@id='password']")).sendKeys(map.get(count).toString()); Thread.sleep(2000); driver.findElement(By.xpath("//*[@id='login_button']")).click(); Thread.sleep(2000); try { driver.switchTo().alert().accept(); Thread.sleep(2000); driver.findElement(By.xpath("//*[@id='username']")).clear(); driver.findElement(By.xpath("//*[@id='password']")).clear(); }catch(NoAlertPresentException NofindAlert) { UserLogout(driver); } } } public static void UserLogout(WebDriver driver) throws InterruptedException { driver.findElement(By.xpath("//*[@id='logout_button']")).click(); Thread.sleep(2000); }}
LoginTest.javapackage Test;import java.io.IOException;import java.util.*;import PublicMethods.*;import org.openqa.selenium.WebDriver;public class LoginTest { public static void main(String[] args) throws InterruptedException, IOException { // TODO Auto-generated method stub WebDriver driver = PublicMethods.share.OpenDriver("file:///D:/%E7%99%BB%E5%BD%95.html"); String filename = "D:\\app_tool\\eclipse-workspace\\AutoTest\\TestData\\user_info.txt"; Map map = txtData(filename); UserLogin(driver, map); driver.quit(); }}
Python
data.pyclass data(): # 读取txt文件 def txtData(self, fileName): file = open(fileName, 'r') lines = file.readlines() file.close() return lines
share.pyfrom time import *from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECclass share(): # 启动浏览器 def open_driver(self, url): driver = webdriver.Firefox() driver.implicitly_wait(10) driver.get(url) return driver # 登录账号检测 def user_login(self, driver, lines): for line in lines: sleep(2) driver.find_element(By.XPATH, "//*[@id='username']").send_keys(line.split(',')[0]) driver.find_element(By.XPATH, "//*[@id='password']").send_keys(line.split(',')[1]) sleep(2) driver.find_element(By.XPATH, "//*[@id='login_button']").click() sleep(2) result =EC.alert_is_present()(driver) # 判断是否有弹窗 if result: result.accept() driver.find_element(By.XPATH, "//*[@id='username']").clear() driver.find_element(By.XPATH, "//*[@id='password']").clear() # 退出账号 def user_logout(self, driver): driver.find_element(By.XPATH, "//*[@id='logout_button']").click() sleep(2)
LoginTest.pyfrom public import share,datadriver = share.share().open_driver('file:///D:/%E7%99%BB%E5%BD%95.html')filename = 'user_info.txt'lines = data.data().txtData(filename)share.share().user_login(driver, lines)share.share().user_logout(driver)driver.quit()
Ruby
读取csv文件
该方法同样适用于读取txt文件
Java
data.javapackage PublicMethods;import java.io.*;import java.util.*;public class data { //读取csv文件 public static ArrayListcsvData(String fileName) { ArrayList list = new ArrayList (); //创建保存数据集合 CsvReader cReader = null; try{ cReader = new CsvReader(fileName); //是否跳过表头 cReader.readHeaders(); while(cReader.readRecord()) { list.add(cReader.getValues()); } }catch(Exception e) { e.printStackTrace(); } finally { cReader.close(); } //如果使用testng的DataProvider,可以返回一个二维数组 Object data[][] = new Object[list.size()][]; for(int i=0;i
share.javapackage PublicMethods;import org.openqa.selenium.By;import org.openqa.selenium.NoAlertPresentException;import org.openqa.selenium.WebDriver;import java.util.ArrayList;import org.openqa.selenium.firefox.FirefoxDriver;public class share { private static WebDriver driver; public static WebDriver OpenDriver(String url) { driver = new FirefoxDriver(); driver.get(url); return driver; } public static void UserLogin(WebDriver driver, ArrayListlist) throws InterruptedException { for(int i=0;i
LoginTest.javapackage Test;import java.io.IOException;import java.util.*;import PublicMethods.*;import org.openqa.selenium.WebDriver;public class LoginTest { public static void main(String[] args) throws InterruptedException, IOException { // TODO Auto-generated method stub WebDriver driver = PublicMethods.share.OpenDriver("file:///D:/%E7%99%BB%E5%BD%95.html"); String filename = "D:\\app_tool\\eclipse-workspace\\AutoTest\\TestData\\user_info.csv"; ArrayListlist = csvData(filename); UserLogin(driver, list); driver.quit(); }}
Python
data.pyimport csvclass data(): # 读取CSV文件 def csvData(self, fileName): lines = csv.reader(open(fileName, 'r')) return lines
share.pyfrom time import *from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECclass share(): # 启动浏览器 def open_driver(self, url): driver = webdriver.Firefox() driver.implicitly_wait(10) driver.get(url) return driver # 登录账号检测 def user_login(self, driver, lines): for line in lines: sleep(2) driver.find_element(By.XPATH, "//*[@id='username']").send_keys(line[0]) driver.find_element(By.XPATH, "//*[@id='password']").send_keys(line[1]) sleep(2) driver.find_element(By.XPATH, "//*[@id='login_button']").click() sleep(2) result =EC.alert_is_present()(driver) # 判断是否有弹窗 if result: result.accept() driver.find_element(By.XPATH, "//*[@id='username']").clear() driver.find_element(By.XPATH, "//*[@id='password']").clear() # 退出账号 def user_logout(self, driver): driver.find_element(By.XPATH, "//*[@id='logout_button']").click() sleep(2)
LoginTest.pyfrom public import share,datadriver = share.share().open_driver('file:///D:/%E7%99%BB%E5%BD%95.html')filename = 'user_info.csv'lines = data.data().csvData(filename)share.share().user_login(driver, lines)share.share().user_logout(driver)driver.quit()
Ruby
读取excel文件
Excel文件数据必须时文本格式
Java
进入http://poi.apache.org/download.html下载POI的Jar包
问题一:![图片.png](http://in4.rccchina.com/doc_upload/2018-07-20/201807201148256543.png)
问题二:
![图片.png](http://in4.rccchina.com/doc_upload/2018-07-20/201807201149356884.png)
问题三:
在遇到Excel单元值为空时sheet.getRow(i).getCell(j).getStringCellValue()会报错 解决方法: 在Excel中把空值改为空格,然后在代码中获取该值后去空格。data.javapackage PublicMethods;import java.io.*;import java.util.*;public class data { //读取Excel文件 public static XSSFSheet excelData(String fileName) throws IOException { File file = new File(fileName); FileInputStream is = new FileInputStream(file); XSSFWorkbook wb = new XSSFWorkbook(is); //加载workbook XSSFSheet sheet = wb.getSheetAt(0); //加载sheet return sheet; }}
share.javapackage PublicMethods;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.openqa.selenium.By;import org.openqa.selenium.NoAlertPresentException;import org.openqa.selenium.WebDriver;import org.openqa.selenium.firefox.FirefoxDriver;public class share { private static WebDriver driver; public static WebDriver OpenDriver(String url) { driver = new FirefoxDriver(); driver.get(url); return driver; } public static void UserLogin(WebDriver driver, XSSFSheet sheet) throws InterruptedException { for(int i=0;i
LoginTest.javapackage Test;import java.io.IOException;import PublicMethods.*;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.openqa.selenium.WebDriver;public class LoginTest { public static void main(String[] args) throws InterruptedException, IOException { // TODO Auto-generated method stub WebDriver driver = PublicMethods.share.OpenDriver("file:///D:/%E7%99%BB%E5%BD%95.html"); String filename = "D:\\app_tool\\eclipse-workspace\\AutoTest\\TestData\\user_info.xlsx"; XSSFSheet sheet = excelData(filename); UserLogin(driver, sheet); driver.quit(); }}
Python
data.pyimport xlrdclass data(): # 读取excel文件 def execelData(self, fileName, sheetName): data = xlrd.open_workbook(fileName) # 通过索引顺序获取 # table = data.sheets()[0] # table = data.sheet_by_index(0) table = data.sheet_by_name(sheetName) # 获取一行或一列的值,参数是第几行 # table.row_values(0) 获取第一行的值 # table.col_values(0) 获取第一列的值 return table
share.pyfrom time import *from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECclass share(): # 启动浏览器 def open_driver(self, url): driver = webdriver.Firefox() driver.implicitly_wait(10) driver.get(url) return driver # 登录账号检测 def user_login(self, driver, table): rows = table.nrows for i in range(rows): sleep(2) driver.find_element(By.XPATH, "//*[@id='username']").send_keys(table.cell(i, 1).value) driver.find_element(By.XPATH, "//*[@id='password']").send_keys(table.cell(i, 2).value) sleep(2) driver.find_element(By.XPATH, "//*[@id='login_button']").click() sleep(2) result =EC.alert_is_present()(driver) # 判断是否有弹窗 if result: result.accept() driver.find_element(By.XPATH, "//*[@id='username']").clear() driver.find_element(By.XPATH, "//*[@id='password']").clear() # 退出账号 def user_logout(self, driver): driver.find_element(By.XPATH, "//*[@id='logout_button']").click() sleep(2)
LoginTest.pyfrom public import share,datadriver = share.share().open_driver('file:///D:/%E7%99%BB%E5%BD%95.html')filename = 'TestData/user_info.xlsx'sheetname = 'test'table = data.data().execelData(filename, sheetname)share.share().user_login(driver, table)share.share().user_logout(driver)driver.quit()
Ruby
浅谈关键字驱动测试
在数据驱动的基础上,我们把“数据”转化为“关键字”后,通过关键字的改变从而引起测试结果的变化。
为何我要在这里说明是“浅谈”呢?在关键字驱动测试中,我们可以将测试的对象、满足条件、传输值、断言等,甚至是所需要读取的外部文件以及外部类库,所有的相关条件存储在文件中(典型的关键字驱动工具:UFT)。我们可以将关键字以“填表格”形式写入文件中,从而降低脚本的编写难度。 正因如此,采用关键字驱动测试来编写同样的脚本需要较高的学习成本。同样,这样的框架越到后期越难维护,可靠性也会变差。所以,暂时不深入研究关键字驱动测试。