分享个人第一次Selenium自动化测试框架开发过程

  因为公司的开发团队偏向于使用Java技术,并且公司倡导学习开源技术,因此我选择用Java语言来进行Selenium WebDriver的自动化框架开发。因为本人没有Java开发经验,之前虽然学过QTP但从没有接触过Selenium,正好经过这个机会能学习一下自动化测试,同时也学习一下基本的Java开发过程。html

1、首先是搭建框架开发环境java

按照网上的方法部署eclipse,创建TestAction工程,并Import引用JDK和Selenium-2.44完整包c++

2、继续引用和安装相关jar包web

一、首先是要知足数据驱动(场景用例和动做用例、数据用例都须要放到excel表上),就须要引用jxl.rar包(实现调用和操做excel);chrome

二、须要实现自动化框架(有测试套件、测试层)就须要经过eclipse安装TestNg(网上有相关教程);express

3、构建框架的样例代码apache

一、实现可以对excel用例数据的调用(经过jxl的引用),建立ExcelData.java类文件(专门用于对excel的调用),如下截取部分代码样例:数组

 /**
     * @param fileName   excel文件名
     * @param caseName   sheet名
     */
    public ExcelData(String fileName, String caseName) {
        super();
        this.fileName = fileName;
        this.caseName = caseName;
    }
     /**
     * 得到excel表中的数据
     */
    public Object[][] getExcelData() throws BiffException, IOException {
 
        workbook = Workbook.getWorkbook(new File(getPath()));
        sheet = workbook.getSheet(caseName);
        rows = sheet.getRows();
        columns = sheet.getColumns();
        // 为了返回值是Object[][],定义一个多行单列的二维数组
        @SuppressWarnings("unchecked")
        HashMap<String, String>[][] arrmap = new HashMap[rows - 1][1];
        // 对数组中全部元素hashmap进行初始化
        if (rows > 1) {
            for (int i = 0; i < rows - 1; i++) {
                arrmap[i][0] = new HashMap<String, String>();
            }
        } else {
            System.out.println("excel中没有数据");
        }
 
        // 得到首行的列名,做为hashmap的key值
        for (int c = 0; c < columns; c++) {
            String cellvalue = sheet.getCell(c, 0).getContents();
            arrkey.add(cellvalue);
        }
        // 遍历全部的单元格的值添加到hashmap中
        for (int r = 1; r < rows; r++) {
            for (int c = 0; c < columns; c++) {
                String cellvalue = sheet.getCell(c, r).getContents();
                arrmap[r - 1][0].put(arrkey.get(c), cellvalue);
            }
        }
        return arrmap;
    }
 
    /**
     * 得到excel文件的路径
     * @return
     * @throws IOException
     */
    public String getPath() throws IOException {
        File directory = new File(".");
        sourceFile = directory.getCanonicalPath() + "\\src\\source\\"
                + fileName + ".xls";
        return sourceFile;
    }


二、实现对浏览器的调用,考虑到兼容性,须要同时知足对Chrome、FireFox、IE三大浏览器的调用,咱们须要准备相关驱动chromedriver.exe、IEDriverServer.exe,这两驱动都是谷歌和IE官方提供的,能够从网上下载到;而FireFox不须要下载驱动,只要安装浏览器就可调用(Selenium和FireFox属于一个团队开发出来的,待遇就是不同)。浏览器

有了浏览器驱动后(咱们把驱动放到工程目录的WebDriver文件夹下,方便按相对路径统一调用),咱们就须要一个能调用浏览器的类,如下提供核心代码样例:安全

    public static WebDriver getChromeDriver(String url) {
        //加载Google驱动
        //System.setProperty("webdriver.chrome.driver","D:\\java\\chromedriver.exe");
        System.setProperty("webdriver.chrome.driver",System.getProperties().getProperty("user.dir")+"\\WebDriver\\chromedriver.exe");
        ChromeOptions options = new ChromeOptions();
        //经过配置参数禁止data;的出现
        options.addArguments("--user-data-dir="+System.getProperties().getProperty("user.home")+"/AppData/Local/Google/Chrome/User Data/Default");
         //经过配置参数删除“您使用的是不受支持的命令行标记:--ignore-certificate-errors。稳定性和安全性会有所降低。”提示
        options.addArguments("--start-maximized","allow-running-insecure-content", "--test-type");
        WebDriver driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.navigate().to(url);
        return driver;
    }
    public static WebDriver getFireFoxDriver(String url){
        System.setProperty("webdriver.firefox.bin", "D:\\Program Files\\Mozilla Firefox\\firefox.exe");
        // TODO Auto-generated method stub
        WebDriver driver = new FirefoxDriver();
        //Puts a Implicit wait, Will wait for 10 seconds before throwing exception
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        //Launch website
        driver.navigate().to(url);
        return driver;
    }
    public static WebDriver getIEDriver(String url){
        //System.setProperty("webdriver.ie.driver", "D:\\java\\IE64\\IEDriverServer.exe");
        System.setProperty("webdriver.ie.driver", System.getProperties().getProperty("user.dir")+"\\WebDriver\\IE32\\IEDriverServer.exe");
        DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
        capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS,true);
        capabilities.setPlatform(Platform.WINDOWS);
        capabilities.setCapability("silent", true);
        // TODO Auto-generated method stub
        WebDriver driver = new InternetExplorerDriver(capabilities);
        //Puts a Implicit wait, Will wait for 10 seconds before throwing exception
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        //Launch website
        driver.navigate().to(url);
        return driver;
    }

三、写一个以数据驱动的场景类,来进行单个事务的用例跑测

 

(1)首行咱们须要用TesgNg提供的数据驱动方法(@DataProvider),来获取一个场景的用例表数据,这个场景从excel的第一个附表获取

经过action名,调取用例表(用例表是以action名命名的附表),用例表以下所示(ExpectedObject表示用例校验对象的页面Element标签,用;分隔,分号前面的表示ID,分号后面的表示xpath):

如下为用例表数据获取的代码:

@DataProvider(name="action")
    public Object[][] Numbers() throws BiffException, IOException{
        getActionString = actionData.getActionStr(1);//获取第一个场景的broswer、url、action名
        ExcelData e=new ExcelData("testdata", getActionString.get(2));
        return e.getExcelData();
    }


而后经过Java的反射机制,实现动态的获取具体事务类和执行相关操做(每一个事务的类名和方法名都与action场景名一致),如下截选相关场景的部分调用代码:

  @Test(dataProvider="action")
    public void testAction(HashMap<String, String> data) throws BiffException, IOException {
        try {
            Class<?> MyClass = Class.forName(packageName+"."+getActionString.get(2));
            Method method = MyClass.getMethod(getActionString.get(2),WebDriver.class);
            @SuppressWarnings("unused")
                    String [] results = (String []) method.invoke(,driver);
                String ExpObject=data.get("ExpectedObject");
            String ExpObject_by=ExpObject.split(";")[0].toString();
            String ExpObject_Desc=ExpObject.split(";")[1].toString();
            if(ExpObject_by.length()>0){
                Assert.assertEquals(driver.findElement(By.id(ExpObject_by)).getText(),data.get("ExpectedData"), getActionString.get(2)+data.get("ID")+"验证结果:");
            }
            else if(ExpObject_Desc.length()>0){
                Assert.assertEquals(driver.findElement(By.xpath(ExpObject_Desc)).getText(),data.get("ExpectedData"), getActionString.get(2)+data.get("ID")+"验证结果:");
            }
            
            WebDriverDemo.WebSleep(500);    
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }


另外说明的是,调用浏览器的方法,须要明确是放在@BeforeMethod中,仍是在@BeforeClass中,若是是登陆校验测试,就要保证每次执行测试方法都要打开一次浏览器和关闭一次浏览器,那么咱们就要把调用浏览器,和关闭浏览器的方法放到@BeforeMethod中和@AfterMethod中。其余业务测试,只要在一个套件类中打开一次浏览器和关闭一次浏览器就能够,因此用到的是@BeforeClass和@AfterClass。

 

四、咱们须要再写一个以动做(关键词)驱动的场景类

 

一样,调用第二个场景的用例表,样例代码以下:

 @DataProvider(name="action")
    public Object[][] Numbers() throws BiffException, IOException{    
        getActionString = actionData.getActionStr(2);//获取第二个场景的broswer、url、action名
        ExcelData e=new ExcelData("testdata", getActionString.get(2));
        return e.getExcelData();
    }


而后在测试方法中,动态的调用具体操做动做,获取WebElement标签的方法,包括经过By ID或者By xpath,操做动做以最多见的两个为例(sendKeys、click),如下为样例代码节选:

  @Test(dataProvider="action")
    public void testAction(HashMap<String, String> data) throws BiffException, IOException { 
        //driver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);//找不到element就再给5秒查找
        try {
            WebElement TestWebElement = ;
            String SetObject=data.get("SetObject").trim();
            String SetObject_by=SetObject.split(";")[0].toString();
            String SetObject_Desc=SetObject.split(";")[1].toString();
            if(SetObject_by.length()>0){
                TestWebElement=driver.findElement(By.id(SetObject_by));
            }
            else if(SetObject_Desc.length()>0){
                TestWebElement=driver.findElement(By.xpath(SetObject_Desc));
            }
            if(data.get("SetOperate").equals("sendKeys")){
                TestWebElement.clear(); 
                TestWebElement.sendKeys(data.get("SetValue"));
            }else if(data.get("SetOperate").equals("click")){
                TestWebElement.click();
            }
            String ExpObject=data.get("ExpectedObject").trim();
            if(ExpObject.length()>0){
                String ExpObject_by=ExpObject.split(";")[0].toString();
                String ExpObject_Desc=ExpObject.split(";")[1].toString();
                if(ExpObject_by.length()>0){
                    Assert.assertEquals(driver.findElement(By.id(ExpObject_by)).getText(),data.get("ExpectedData"), getActionString.get(2)+data.get("ID")+"验证结果:");
                }
                else if(ExpObject_Desc.length()>0){
                    Assert.assertEquals(driver.findElement(By.xpath(ExpObject_Desc)).getText(),data.get("ExpectedData"), getActionString.get(2)+data.get("ID")+"验证结果:");
                }
            }
            
            WebDriverDemo.WebSleep(500);    
            } catch (Exception e) {
            // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }


这段方法所调用的用例表以下所示(以登陆为例):


五、剩下就是业务扩展类了,全部复杂的事务均可以单独创建测试类和方法(方便扩展维护,只须要在excel场景表中定义后就能调用,利用的是Java反射机制),在这里就不举例了。
4、实现测试套件调用和报告输出

有了以上步骤,一个可扩展的自动化框架已经基本造成,可是还达不到大规模应用测试和脚本方即可移植,这时候咱们引入Ant(能够在Eclipse中安装插件,能够直接上网下载后引用),为了能输出漂亮一点的报告格式,咱们还引入一个saxon-8.7.jar。

有了Ant后,咱们就能够建议build.xml文件,就能一键bulid咱们以上的自动化代码,并将执行测试后的结果输出成报告。

一、首先咱们须要编辑好测试套件调用的testng.xml,简单举例以下:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> 
<suite name="Suite" parallel="false"> 
  <test verbose="2" name="Test_Action"> 
      <!--<groups> 
      <run> 
          <include name="aaa" />
         <include name="bbb" />  
         <include name="ccc" /> 
       </run> 
    </groups>-->
    <classes> 
      <class name="TestBrowser.ExcActions"/>
      <class name="TestBrowser.ExcActions2"/> 
    </classes> 
  </test> <!-- Default test --> 
</suite> <!-- Default suite -->


二、而后咱们须要编辑好一个能引用基础jar包、build测试代码、调用testng、输出漂亮报告的build.xml文件

<?xml version="1.0" encoding="UTF-8"?>
 
<project name= "TestAction" basedir= "." default="testoutput"><!--default设置为run表示只执行脚本,设为testoutput表示执行完脚本并输出视图报告-->
<echo message="import libs" />
<property name= "lib.dir" value= "lib" /> <!--<property name="libdir" location="${basedir}/lib" />-->
<!--<property name="testng.output.dir" location="${basedir}/test-output" />-->
<path id= "test.classpath" >
 
<!-- adding the saxon jar to your classpath -->
 
<fileset dir= "${lib.dir}" includes= "*.jar" />
 <fileset dir="${basedir}/selenium-2.44.0">
    <include name="selenium-java-2.44.0.jar" />
    <include name="libs/*.jar" />
 </fileset>
 
</path>
<taskdef name="testng" classname="org.testng.TestNGAntTask" classpathref="test.classpath" />
<target name="clean">
    <delete dir="build"/>
</target>
<target name="compile" depends="clean">
<echo message="mkdir"/>
 <mkdir dir="build/classes"/>
 <javac srcdir="src" destdir="build/classes" debug="on" encoding="UTF-8" includeAntRuntime="false">
    <classpath refid="test.classpath"/>
    </javac>
</target>
<path id="runpath"> 
    <path refid="test.classpath"/> 
    <pathelement location="build/classes"/> 
    </path> 
<target name="run" depends="compile">
    <testng  classpathref="runpath"  outputDir="test-output">
        <xmlfileset dir="${basedir}" includes="testng.xml"/>
        <jvmarg value="-ea" />
    </testng>
</target>
<target name= "testoutput" depends="run">
<xslt in= "test-output/testng-results.xml" style= "test-output/testng-results.xsl"
out= "test-output/index1.html" >
<!-- you need to specify the directory here again -->
<param name= "testNgXslt.outputDir" expression= "${basedir}/test-output/" />
    <param name="testNgXslt.showRuntimeTotals" expression="true" />
<classpath refid= "test.classpath" />
</xslt>
</target>
 
</project>


三、完成这些后,咱们就能够经过Eclipse直接Run As Ant Build咱们的自动化脚本了,输出一份还算漂亮的报告:

同时,须要在事务操做类中,对实际结果和预期结果进行比较,并将测试结果写入excel的用例表中,以下:

       String[] result=new String [2];
        result[0] = driver.findElement(By.xpath(pars.get(3).split(";")[1].toString())).getText();
        result[1] = pars.get(4);
        if(result[0].equals(result[1])){//pars.size()-1
            ActionsDemo.modifyExcel(Thread.currentThread().getStackTrace()[1].getMethodName(),k,5,"经过");
        } else {
            ActionsDemo.modifyExcel(Thread.currentThread().getStackTrace()[1].getMethodName(),k,5,"失败");
        }


5、实现自动化框架脚本的迁移调用

以上的脚本始终是在Eclipse下编译和调用的,若是要实现灵活迁移,随便换任何一台只装了JDK的电脑都能运行,那么咱们就要来点改造

一、首行是保证咱们写的代码中,因此须要引用文件的地方,都用相对路径的方式,避免代码包迁移后须要改路径。

二、经过批处理调用build文件及用例文件,调用时也是经过批处理自动找到相关路径,避免用绝对路径。

三、须要用环境变量的地方,尽可能用批处理的方式实现,甚至最好是不用配置环境变量,直接调用相引用相对命令文件的路径调用

如下举个经过bat批处理调用Ant来执行整个框架代码的build:

@echo off
::先将测试用例文件拷到用户目录下
copy src\source\testdata.xls %UserProfile%\src\source
%cd%\org.apache.ant_1.9.6\bin\ant.bat -buildfile build.xml
echo 在%cd%\test-output下查看测试报告
pause


6、进一步实现自动化的持续集成

在以上基础上,咱们还能够经过jenkins实现对自动化脚本的调用,以及达到每日构建,持续集成开发的要求。

一、首先部署jenkins(网上有相关方法),因为本人公司一直在用jenkins,我就省了搭建部署这一步,直接将以上的自动化框架脚本上传

二、自动化脚本完整目录(包括代码、用例、lib、引用的jar、build.xml文件等)上传到SVN(再自动从SVN下到jenkins所在服务器)

三、在jenkins中新建一个测试项目TestAction,主要配置以下:

四、配置完后,就能够当即构建(若是碰到相关报错问题,就按输出的提示进行处理),构建成功后,就能够在HTML_Report中看到测试结果:

7、后续处理

到此为止,一个完整的Selenium自动化框架就出来了,要说好用不,很差说,还得通过实践的检验,可是以上这个思考过程和框架的演进过程,应该也是值得借鉴的,毕竟这是我这几天摸索和学习的过程,对于一个没有从事过自动化测试,并且没有作过Java开发的测试人员来讲,这只是个开始。

目前来看,这个框架在架构分层上,仍是不够清晰,有不少要改进的东西,从技术上来讲,我已经实现了个人目标(学习自动化测试),可是在总体架构和代码重构上,还有不少工做没作,如下贴出一份Selenium自动化框架的分层结构,以便后期按照这个标准进行改进:

测试数据层:独立封装数据;
页面对象层:封装页面对象,共页面任务层作调用;
页面任务层:实现各个独立页面的操做;
测试层:实现页面测试;
测试套件层:实现测试层的管理调用;

跟你们推荐一个学习资料分享群:747981058,里面大牛已经为咱们整理好了许多的学习资料,有自动化,接口,性能等等的学习资料!人生是一个逆水行舟的过程,不进则退,我们一块儿加油吧!

相关文章
相关标签/搜索