这个是我后来写的一本书,http://www.ituring.com.cn/minibook/10775。这个是我后来找到的自动化完美解决方案。

首先我们谈论下Automation语言组织管理,因为一个Automation 的框架要使用它,就得用语言去驱动它,在一些自动化的软件中,你会见到那种不需要写语言,直接录制回放就去执行你脚本的自动化软件,但其实在录制的过程中,它只是智能的代替你生成脚本化语言,而这语言很多时候是没有你手写的健壮(即不容易出错)。你要时不时去修改它,修改的时候你肯定必须懂得脚本语言。

我们先看一种方法,用XML去写自己的XML表达式语言然后去驱动相关的Java类或者Java方法执行.

首先,我们先说一种设计模式,叫模板方法,它是用公共的父类去制定好子类的行为,就像上一篇Junit示例那样,先定好之类可执行的方法setup()、teardown(),并在父类中指定好他们的执行顺序;就是怎么说我用父类先做好模板,子类只要继承这个模板写出自己的特定业务实现就行了。用它就像大学时你考四六级英语用的作文模板一样的用就行了。

好了,开始

首先制定一个模板类,这个模板所要做的工作是限定子类只能用什么方法,并且规定好这些方法的执行顺序。

public abstract class Demo{

public abstract void setUp();

public abstract void getValueFromXml();

public abstract void execute(Element e);

public abstract void tearDown();

public final void run(Element e){

setUp();

getValueFromXml(e);

execute();

tearDown();

}

}

分析一下这个方法,里面的setUp()和tearDown()是每个子类都会用到且用的方法一模一样,所以也可以抽出来作为第二级模板

public abstract class JSPDemo extends Demo{

SeleniumServer server;
    Selenium selenium;
    public void setUp() {

RemoteControlConfiguration cfg=new RemoteControlConfiguration();
        
        try {
            server=new SeleniumServer(cfg);
            server.boot();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

public void tearDown() {
        selenium.close();
        server.stop();
    }

}

接着就简单了,最后的子类即实际应用类只要继承这个第二级类就行了

public class FirstDemo extends JSPDemo {

public void getValueFromXml(Element e) {

System.out.println("getValueFromXml");

}

@Override

public void execute() {

System.out.println("execute");

}

}

这样以后每种实现类都以这种方式书写就行了。

在转回正题,我们接着讨论xml,首先我们看下面一个test.xml.

<?xml version="1.0" encoding="UTF-8"?>
<Script>   
<FirstDemo name="testjingdongcom" password="jingdong" productId="286048"/>

<JingDongCustomerService name="admin" password="admin"/>   
 
</Script>

接着我们看下解析它的类文件

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class AnalyzeScript {
    private String xmlRoad;
     private Document doc = null;

/**
     * @param:String(xmlRoad)
     * 在构造器中导入xml所在的路径
     */
    public AnalyzeScript(String xmlRoad) {
        this.xmlRoad = xmlRoad;
    }
    
    /**
     * @param:String(xmlRoad)
     * 读xml.
     */
    public void parse(String xmlRoad) throws Exception {
        File scriptFile = new File(xmlRoad);
        if (!scriptFile.exists()) {
            throw new FileNotFoundException("the script file does not exists. ");
        } else if (scriptFile.isDirectory()) {
            throw new IllegalArgumentException(
                    "the script file is not a file. ");
        }

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        doc = db.parse(scriptFile);
    }
    
    /**
     * @param:String(xmlRoad)
     * @return NodeList
     * 获得xml其中一个节点.
     */
    public NodeList analyzeXmlForGetALlNodeName(){
        Node fatherNode=null;
        try {
            parse(xmlRoad);
            Element root = doc.getDocumentElement();
             NodeList nodeList = doc.getElementsByTagName("Script");
            System.out.println(root.getNodeName());
            fatherNode = nodeList.item(0);
                   
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return fatherNode.getChildNodes();
    }
    
    /**
     * @param:Element String
     * @return 根据传入的element和属性名得到属性值。
     *
     */
    public static String analyzeXML(Element e,String attributs){
        String attr=null;
        try {
             if(e.hasAttributes()){
              attr=e.getAttribute(attributs);
             }
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
         return attr;
        
    }

}

那解析好xml后我们干什么呢?看下面代码,把xml节点名字和java类对应起来,看我们的下面这段代码,通过反射对应找到相对应得java类

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ReflectJavaClassRun {
    private String xmlRoad;
    public ReflectJavaClassRun(String xmlRoad){
        this.xmlRoad=xmlRoad;
        
    }
    private List scriptNodeList=new ArrayList();
    
    /**
     * 通过反射找到对应的java类
     */
    public void ReflectJavaClass() throws ClassNotFoundException,Exception{
    AnalyzeScript as=new AnalyzeScript(xmlRoad);
    NodeList childNode=as.analyzeXmlForGetALlNodeName();     
    for(int i=0;i<childNode.getLength(); i++){
        //得到xml节点
        Node node=childNode.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {        
             Element e=(Element)node;
        //通过反射找到对应的java类
        Class clazz=Class.forName(e.getNodeName());
         Demo instance=(Demo)clazz.newInstance();
         //得到刚才模板模式中定义好的run方法,注意new Class[] { Element.class }和下面的m.invoke(instance,e)都是表示在反射中如何把参数传入对应的方法中。
         Method m = clazz.getMethod("run", new Class[] { Element.class });
        m.invoke(instance,e);
        }
    }    
    }

好,那我们看最后一步,它调用的FirstDemo类是什么样子。

import org.w3c.dom.Element;
import com.thoughtworks.selenium.DefaultSelenium;

public class FirstDemo extends JSPDemo{

private String name;
    private String password;
    private String productId;
    
    
       public void getValueFromXml(Element e) {
      //把传入的节点中属性名为name的属性值取出来。
        name=AnalyzeScript.analyzeXML(e, "name");
        System.out.println(name);

//把传入的节点中属性名为passeword的属性值取出来。
        password=AnalyzeScript.analyzeXML(e, "password");

//把传入的节点中属性名为productId的属性值取出来。
        productId=AnalyzeScript.analyzeXML(e, "productId");
      }

public void execute()  {
            try {
            selenium=new DefaultSelenium("localhost",4444,"*firefox","http://www.360buy.com/");
            selenium.start();
            selenium.windowMaximize();
            selenium.setTimeout("600000");
            selenium.open("http://www.360buy.com/product/"+productId+".html");
            Thread.sleep(20000);
            
            selenium.click("xpath=id('InitCartUrl')");
            Thread.sleep(20000);
            selenium.click("xpath=id('GotoShoppingCart')");
            Thread.sleep(20000);
            selenium.click("xpath=id('gotoOrderInfo')");
            Thread.sleep(5000);
            selenium.type("xpath=id('loginname')", name);
            selenium.type("xpath=id('loginpwd')", password);
            selenium.click("xpath=id('loginsubmitframe')");
            Thread.sleep(10000);
            selenium.type("xpath=id('consignee_addressName')", "张俊卿");
            selenium.select("xpath=id('consignee_province')", "index=2");
            Thread.sleep(5000);
            selenium.select("xpath=id('consignee_city')", "普陀区*");
            Thread.sleep(10000);
            selenium.select("xpath=id('consignee_county')", "桃浦新村*");
            selenium.type("xpath=id('consignee_address')", "上海西站");
            selenium.type("xpath=id('consignee_message')", "13999999999");
            selenium.click("xpath=id('part_consignee')//div[@class='footer']/input");
            Thread.sleep(5000);
            selenium.check("xpath=id('IdPaymentType1')");
            String s=selenium.getText("xpath=id('part_cart')//div[@class='middle']//tr[@class='align_Center']/td[1]");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
      }
 }

呵呵,还记得模板方法中定义的这些方法调用的顺序吗。他们会按照setUp()- getValueFromXml(e)-execute()- tearDown()的顺序先后执行。

检查一下上面的方法正确与否?运行

public static void main(String[] args) {
        ReflectJavaClassRun rj=new ReflectJavaClassRun("src\\test.xml");
        try {
            rj.ReflectJavaClass();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }

执行完后,他们接着找xml中写出的第二个类JingDongCustomerService去执行,JingDongCustomerService类如何使用模板的就不详细说了,只要继承JSPDemo就行了。

未完待续-下面小节会接着说验证是如何在xml中定义和在java类中如何使用它,对数据库的调用xml的参考格式在下面之下章节也会说到。最后说下这种方法的优缺点和改进方法。

用java构建企业级自动化框架(首篇-制定测试者使用语言1)相关推荐

  1. 用java构建企业级自动化框架(前序篇)

    这个是我后来写的一本书,http://www.ituring.com.cn/minibook/10775.这个是我后来找到的自动化完美解决方案. 谈到企业级自动化测试,大家肯定会想到QTP,Ratio ...

  2. 使用Cypress自动化框架进行Web/API测试

    文章目录 Cypress介绍 Cypress特点 Cypress运行原理 Cypress安装 Cypress使用 Web页面测试 元素定位方法 元素常用操作 示例演示 参数化测试 使用PO模型 命令运 ...

  3. Java接口自动化框架系列07:Web接口自动化测试框架设计思路

    1.Java web接口自动化框架 框架名称:Java+Maven+httpClients+TestNg+Allure (因本次只讲解java部分,未包括git和jenkins,如果是包括git和je ...

  4. 基于JAVA实现的WEB端UI自动化 - WebDriver高级篇 - 关联

    文章目录 关联 (公共变量传递一些值) 基于JAVA实现的WEB端UI自动化 -自动化测试简单介绍 基于JAVA实现的WEB端UI自动化 - WebDriver基础篇 - 实现简单的浏览器操作 基于J ...

  5. 「构建企业级推荐系统系列」推荐系统的未来发展

    作者 | gongyouliu 编辑 | auroral-L 全文共11510字,预计阅读时间60分钟 目录 一.政策及技术发展对推荐系统的影响 1.政治层面 2.科技层面 二.推荐系统的就业 1.推 ...

  6. Java安全(十三) SSM-Spring框架

    概述 Spring 是目前主流的 Java Web 开发框架,是一个轻量级的开源框架,具有很高的凝聚力和吸引力. Spring 框架不局限于服务器端的开发.从简单性.可测试性和松耦合的角度而言,任何 ...

  7. 测试自动化框架的重要性– iSAFE的优势

    测试自动化并不像某些人想象的那样容易或经济. 仅应在必要和适用的情况下使用.而且,最重要的是,它不能替代手动测试.相反,它补充了手动测试. 自动化框架和正确的测试自动化工具对于增强测试自动化过程至关重 ...

  8. java自动化测试报告_Java自动化测试框架-10 - TestNG之测试结果篇(详细教程)

    1.-测试结果 1.1-成功,失败和断言 测试被认为是成功的,如果它不引发任何异常完成,还是它扔的预期异常(请参阅文档expectedExceptions属性上找到的@Test注释). 您的测试方法通 ...

  9. CI/CD——构建企业级Docker+Jenkins+Git+Harbor流水线自动化持续集成持续发布平台

    构建企业级Docker+Jenkins+Git+Harbor流水线自动化持续集成持续发布平台 CI/CD是什么? 持续集成(CI)/持续交付(CD)的优势 自动化部署流程图 Git Github Gi ...

最新文章

  1. UVA 10714 - Ants
  2. Cetos 7 命令行登陆与图形界面登陆相互切换
  3. 预定义变量 - PHP手册笔记
  4. java 本地通信_java – 本地JVM之间的通信
  5. Codeforces Round #395 (Div. 2)(未完)
  6. Boost:can_require的使用测试程序
  7. cloud foundry_将Spring Boot应用程序绑定到Cloud Foundry中的服务的方法
  8. OpenSSL原理与实现
  9. 【JUnit 报错】 method initializationerror not found:JUnit4单元测试报错问题
  10. 免费视频直播点播服务器系统,搭建一套完整的网络视频流媒体直播/点播服务系统需要具备哪些条件?...
  11. SQL_Server_2008完全学习之第五章操作架构、索引和视图
  12. 【百度大脑新品体验】行驶证识别
  13. 360插件化Replugin爬坑之路
  14. 本科数学基础差的感觉 SLAM 很难,如何去提高?
  15. Excel公式与函数——每天学一个
  16. 排序总结(排序算法稳定性、如何选择排序算法以及排序算法常见的坑)
  17. 互联网周刊:Web 3.0还有多远
  18. 前途迷茫不知.NET与JAVA那个好
  19. 一个笔记本能连WiFi 通过网线共享网络给另一个电脑上网(笔记本对台式/笔记本对笔记本)
  20. “中国第一国门”首都机场的新Wi-Fi网:带你智能带你飞

热门文章

  1. 【pytorch笔记】损失函数nll_loss
  2. 不止围棋 手机里的阿尔法狗帮你p图选发型
  3. java集成测试_到底什么是集成测试?
  4. iOS高仿新版微信扫一扫源码
  5. 远丰集团:企业布局移动电商该怎么选APP
  6. 最全 内网 gitblit git
  7. 访黏度计算公式_常用粘度单位换算
  8. Python常见的数据分析工具有哪些?
  9. 2022年java中级开发工程师最新面试题
  10. 使用MAC版 Word简化工作的 6 个小窍门