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

什么是数据驱动

 

      数据驱动,意思是写一个测试用例,可以覆盖这个测试用例的各种不同条件的测试场景步骤。核心实现是,需要输入的参数是外部数据源提供。本框架输入的用户名和密码其实就写死的,但是很多场景我们都需要不同的测试数据去执行同一个测试用例。

 

       举例一个更具体的例子,在我之前做过的项目中,我们做了一个新的用户中心后台系统。系统上线之前,我们最担心的是会不会影响之前旧的用户的登录,进一步担心的是影响旧用户的数据丢失,例如收藏文章不见了等等。其中,第一个问题,用户会不会登录不成功,这个就可以使用数据驱动的思想去完成测试。这个时候,数据源基本上是数据库里的用户表。输入的数据有两个列,第一个列是用户名,第二个列是密码。假如,我们需要用前端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报告输出,测试后发送邮件通知等这样的内容。下一篇,还是要介绍下如何把这个关键字框架拿给不懂代码的黑盒测试人员使用。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值