您的位置:首页 > 其它

关键字驱动框架入门教程-12-数据驱动技术

2018-02-10 00:05 751 查看
什么是数据驱动
 
      数据驱动,意思是写一个测试用例,可以覆盖这个测试用例的各种不同条件的测试场景步骤。核心实现是,需要输入的参数是外部数据源提供。本框架输入的用户名和密码其实就写死的,但是很多场景我们都需要不同的测试数据去执行同一个测试用例。
 
       举例一个更具体的例子,在我之前做过的项目中,我们做了一个新的用户中心后台系统。系统上线之前,我们最担心的是会不会影响之前旧的用户的登录,进一步担心的是影响旧用户的数据丢失,例如收藏文章不见了等等。其中,第一个问题,用户会不会登录不成功,这个就可以使用数据驱动的思想去完成测试。这个时候,数据源基本上是数据库里的用户表。输入的数据有两个列,第一个列是用户名,第二个列是密码。假如,我们需要用前端selenium去实现所有的用户登录测试,我们可以这样去做。
1)让运维把线上用户数据表导出来,先拿到本地数据库环境。
2)让开发统一把本地用户表的密码全部改成简单的123456,当前这个步骤可以不做。
3)测试拿到本地数据库用户表,然后自动化去实现数据驱动完成所有用户登录测试。
写一个连接数据库公共类
使用while循环,依次取出用户名,密码都是123456
没循环一次,打开登录链接,用selenium的API去点击和输入,实现登录功能
如果需要登录后数据校验,需要写一些断言(看情况,可以不做这步)
点击登出,点击Logo回到首页,方便下一个循环用户登录.
       我们暂不考虑执行效率和时间快慢问题。这个过程就是典型的数据驱动思想来实现测试,一个用户登录应该不会超过5秒时间,一天能实现上千个用户登录测试,如果单机执行这个脚本。
 
       回到本框架的话题,我们需要这个关键字驱动框架也能支持数据驱动。本框架,我们输入的用户名和密码是硬编码,同样,如果和上面我举例的场景,我们也需要测试百度登录支持数据驱动,也就是支持很多个用户登录百度测试。还有一个问题,我们一直没有解决,那就是关键字驱动封装的方法,我们没有实现使用一个input方法,其他任何输入元素都能调用这个方法。
 
下面我通过具体步骤来实现这个input方法的构造过程和数据驱动的实现过程。
 
步骤1:修改Excel表格列和内容
 
1.打开dataExcel.xlsx文件,在Test Steps表中,我们在Results列左侧新插入一列,叫Data Set
2.输入浏览器名称,用户名和密码在Data Set对应单元格内。
3.把关键字名称inputUsername和inputPassword够改成唯一的input
 
修改后的Test Steps 表内容如下:



步骤2:修改常量类文件
1.创建一个新的常量变量用来找到Data Set这列
2.由于我们新增一列,所以记得要修改TestStepResult的索引为6
修改后的常量类文件全部内容如下package config;

public class Constants {

// 这里定义为public static的类型,方便其他任何类进行访问和调用
public static final String URL = "https://www.baidu.com";
public static final String Path_TestData = ".//src//dataEngine//dataEngine.xlsx";
public static final String File_TestData = "dataEngine.xlsx";
// OR(对象仓库)文件路径
public static final String Path_OR =".//src//config/OR.txt";

// dataEngine.xlsx中一些单元格的索引值
public static final int Col_TestCaseID = 0;
public static final int Col_TestScenarioID =1;
public static final int Col_PageObject =3 ;
public static final int Col_ActionKeyword =4 ;
public static final int Col_RunMode =2 ;
// 第一个是测试用例结果标记列的索引,第二个是测试步骤里面的结果列索引
public static final int Col_Result =3 ;
public static final int Col_DataSet = 5;
public static final int Col_TestStepResult =6 ;
// 结果状态标记
public static final String KEYWORD_FAIL = "FAIL";
public static final String KEYWORD_PASS = "PASS";

// DataEngmine.excel中sheet的名称
public static final String Sheet_TestSteps = "Test Steps";
// 第二个工作簿的名称
public static final String Sheet_TestCases = "Test Cases";

// 测试登录用到的用户数据
public static final String UserName = "xxxxxx";
public static final String Password = "xxxxxxx";
}
步骤3:修改ActionsKeywords.java类
       主要是构造一个input()的方法,我们修改每个关键字方法,参数都改成两个,一个参数是object,另外一个参数就是本文的data set。修改后的代码如下:

package config;

import executionEngine.DriverScript;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import utility.Log;

import static executionEngine.DriverScript.OR;

import java.util.concurrent.TimeUnit;

public class ActionsKeywords {

public static WebDriver driver;

public static void openBrowser(String object, String data) {

// 这里,我们暂时都写死用chrome来进行自动化测试
try{
Log.info("启动chrome浏览器。");
System.setProperty("webdriver.chrome.driver",".\\libs\\chromedriver.exe");
driver = new ChromeDriver();
}catch(Exception e){
Log.info("无法启动浏览器 --- " + e.getMessage());
DriverScript.bResult = false;
}
}

public static void openUrl(String object, String data) {

try{
Log.info("打开测试环境地址");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get(Constants.URL);
}catch(Exception e){
Log.info("无法打开测试环境地址 --- " + e.getMessage());
DriverScript.bResult = false;
}

}

public static void click(String object, String data) {
try{
Log.info("点击元素: "+ object);
driver.findElement(By.xpath(OR.getProperty(object))).click();
}catch(Exception e){
Log.error("无法点击元素--- " + e.getMessage());
DriverScript.bResult = false;
}
}

public static void input(String object, String data){
try{
Log.info("开始在 " + object +"输入文本");
driver.findElement(By.xpath(OR.getProperty(object))).sendKeys(data);
}catch(Exception e){
Log.error("无法输入文本 --- " + e.getMessage());
DriverScript.bResult = false;
}

}

public static void waitFor(String object, String data) throws Exception{
try{
Log.info("等待五秒");
Thread.sleep(5000);
}catch(Exception e){
Log.error("无法等待 --- " + e.getMessage());
DriverScript.bResult = false;
}
}

public static void closeBrowser(String object, String data){
try{
Log.info("关闭并退出浏览器");
driver.quit();
}catch(Exception e){
Log.error("无法关闭浏览器--- " + e.getMessage());
DriverScript.bResult = false;
}
}

}
 
步骤4:修改DriverScript.java类
1.创建一个新的变量public static String sData;
2.添加代码语句块,从excel中data set列复制给sData变量
在execute_Action()代码块,把sData参数传递进去。package executionEngine;
import com.sun.xml.internal.bind.v2.runtime.reflect.opt.Const;
import config.ActionsKeywords;
import config.Constants;
import org.apache.log4j.xml.DOMConfigurator;
import utility.ExcelUtils;
import utility.Log;

import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
* create by Anthony on 2018/1/30
*/
public class DriverScript {

// 声明一个public static的类对象,所以我们可以在main方法范围之外去使用。
public static ActionsKeywords actionsKeywords;
public static String sActionKeyword;
// 下面是返回类型是方法,这里用到反射类
public static Method method[];
// 新建一个Properties对象
public static Properties OR;
public static String sPageObject;

public static int iTestStep;
public static int iTestLastStep;
public static String sTestCaseID;
public static String sRunMode;
public static boolean bResult;
public static String sData;

// 这里我们初始化'ActionsKeywords'类的一个对象
public DriverScript() throws NoSuchMethodException, SecurityException{
actionsKeywords = new ActionsKeywords();
method = actionsKeywords.getClass().getMethods();
}

public static void main(String[] args) throws Exception {
// 这样一定要加,否则报log4j初始化的警告
DOMConfigurator.configure("log4j.xml");
ExcelUtils.setExcelFile(Constants.Path_TestData);
// 创建一个文件输入流对象,参数来源外部OR.txt文件
FileInputStream fs = new FileInputStream(Constants.Path_OR);
// 创建一个Properties对象
OR = new Properties(System.getProperties());
// 加载全部对象仓库文件
OR.load(fs);
// 执行用例
DriverScript startEngine = new DriverScript();
startEngine.execute_TestCase();
}

private void execute_TestCase() throws Exception {
//获取测试用例数量
int iTotalTestCases = ExcelUtils.getRowCount(Constants.Sheet_TestCases);
//外层for循环,有多少个测试用例就执行多少次循环
for(int iTestcase=1;iTestcase<=iTotalTestCases;iTestcase++){
//从Test Case表获取测试ID
bResult = true;
sTestCaseID = ExcelUtils.getCellData(iTestcase, Constants.Col_TestCaseID, Constants.Sheet_TestCases);
//获取当前测试用例的Run Mode的值
sRunMode = ExcelUtils.getCellData(iTestcase, Constants.Col_RunMode,Constants.Sheet_TestCases);
// Run Mode的值控制用例是否被执行
if (sRunMode.equals("Yes")){
// 只有当Run Mode的单元格数据是Yes,下面代码才会被执行
iTestStep = ExcelUtils.getRowContains(sTestCaseID, Constants.Col_TestCaseID, Constants.Sheet_TestSteps);
iTestLastStep = ExcelUtils.getTestStepsCount(Constants.Sheet_TestSteps, sTestCaseID, iTestStep);

bResult=true;
//下面这个for循环的次数就等于测试用例的步骤数
for (;iTestStep <= iTestLastStep;iTestStep++){
sActionKeyword = ExcelUtils.getCellData(iTestStep, Constants.Col_ActionKeyword,Constants.Sheet_TestSteps);
sPageObject = ExcelUtils.getCellData(iTestStep, Constants.Col_PageObject, Constants.Sheet_TestSteps);
sData = ExcelUtils.getCellData(iTestStep, Constants.Col_DataSet, Constants.Sheet_TestSteps);
execute_Actions();
if(bResult==false){
//If 'false' then store the test case result as Fail
ExcelUtils.setCellData(Constants.KEYWORD_FAIL,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
//End the test case in the logs
Log.endTestCase(sTestCaseID);
//By this break statement, execution flow will not execute any more test step of the failed test case
break;
}
}

//This will only execute after the last step of the test case, if value is not 'false' at any step
if(bResult==true){
//Storing the result as Pass in the excel sheet
ExcelUtils.setCellData(Constants.KEYWORD_PASS,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
Log.endTestCase(sTestCaseID);
}
}
}
}

private static void execute_Actions() throws Exception {

for(int i=0;i<method.length;i++){

if(method[i].getName().equals(sActionKeyword)){
//This code will pass three parameters to every invoke method
method[i].invoke(actionsKeywords,sPageObject, sData);
if(bResult==true){
ExcelUtils.setCellData(Constants.KEYWORD_PASS, iTestStep, Constants.Col_TestStepResult, Constants.Sheet_TestSteps);
break;
}else{
ExcelUtils.setCellData(Constants.KEYWORD_FAIL, iTestStep, Constants.Col_TestStepResult, Constants.Sheet_TestSteps);
ActionsKeywords.closeBrowser("","");
break;
}
}
}
}

}

      测试运行一下main方法,是可以运行成功,可以看到输入用户名和密码是从Excel Test Steps表中的Data Set里面对应的单元格数据。如果只是测试这个登录用例,手动测试人员,只需要修改这两个单元格的数据内容就可以测试各种登录场景的用例。例如正确用户名,错误密码;错误用户名,正确密码;错误用户名和错误密码;用户名和密码一项为空等。
      其实到这里,一个简单的关键字驱动框架已经实现了。其他的,你可以考虑添加html报告输出,测试后发送邮件通知等这样的内容。下一篇,还是要介绍下如何把这个关键字框架拿给不懂代码的黑盒测试人员使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: