自动化测试框架de详细搭建

[自动化测试](javascript:;)框架结构说明
  目前实现的自动化测试框架大致可以分为以下四块内容:

  • 页面自动化测试

  • [API](javascript:?/WebService 自动化测试

  • 工具类/support类

  • 测试用例管理
      页面自动化测试
      页面自动化测试目前设计的目主要包括了如下几点:

  • 全部使用Page Object模式,进行测试数据和测试页面,测试流程分离

  • 定制WebElement,可以控制元素的特殊处理,或者统一记录日志等

  • 修改原生Selenium默认的Page Factory模式,转化为可以处理定制元素

  • Driver Factory 根据配置生成driver

  • 页面元素和测试的数据根据名字进行绑定

  • 测试检查点可以注入到测试流程中

  • 可以组装的测试步骤

  • 可以通过注解定义页面测试步骤
      页面自动化测试详细说明
      修改后的Page Factory模式,流程图:
      自动化测试框架de详细搭建_第1张图片
       可以组装的测试步骤
      可以组装的测试步骤的设计主要考虑以下几种组装方式:

  • 多个页面测试的组装

  • 过个业务流程测试的组装

  • API和页面测试的组装

  • 检查点可注入到组装了的流程中

  • 实现不同子系统直接的调用
      为了实现这个,主要定义了TestAction接口和TestActionsBuilder类,目的如下:

  • 所有的测试操作都实现TestAction接口的execute方法

  • TestActionsBuilder 用来组装不同的TestAction,实现不同业务流程组装
      页面元素和测试的数据根据名字进行绑定
      目前的一个实现就是每一个页面完成之后,都有一个相应的数据模型和页面绑定,每一个数据元素和每一个可输入的页面元素相绑定,作为测试的输入; 同时简单实现了页面数据输入时不需要指定设置样的数据,由框架来根据输入数据来决定进行什么样的操作。 之后可以做一些优化,比如根据页面模型,已经一些固定数据,来自动化分生成测试数据。
      注解驱动的页面流程组装
      使用注解的方式在单个页面上构建测试流程,以达到一定程度的减少[代码](javascript:;)量,目前主要通过如下的注解:

  • UIActions

  • UIAction
      来驱动注解的测试
      页面自动化实例-Login
      新的页面测试方式引入一个概念是TestAction,这个怎么理解呢?可以认为是如下几个事物:
      1、单个的一个测试动作,如点击某个按钮,访问某个连接
      2、一连串的测试动作,可以在页面上点击一连串的按钮,填写很多表单
      3、可以是操作读个页面,在每个页面上填写很多内容,点击很多按钮…
      4、可以是一个API请求,也可以是多个API请求
      5、可以是过个TestAction的组合
      关于TestAction,在实际的时候过程中,只要实现TestAction接口就可以了,以下是TestAction接口目前的定义:

      * 执行测试步骤的函数,可以是一个页面的多个步骤,可以是多个页面的步骤
      */ void execute(); /**
      * test action 的名字,默认是TestAction class的名字
      * @return */ default String getTestActionName(){ return this.getClass().getSimpleName();
      }
    

Login 实现Test Action的不同方式
  目前可以有两种方式来实现Login这个的TestAction,相信在以后的使用过程中可能这两种种方式都有可能会用到:

  • 完全写代码实现,和之前代码没有太多区别,唯一的区别是元素定位内容不会在TestAction代码中出现了完全,从而实现了和页面元素的解耦
  • 使用Annonation 来实现测试步骤
      实现例子
      代码实现可以分为三步:
  • 构建page
  • 构建和业务相关的TestAction
  • 构建测试类
    构建Page 类
public class LoginPage extends BasePage { @FindBy(id= "usercode") private InputBox userCode; @FindBy(id="password") private InputBox password; 
@FindBy(id="msg") private WebElement msg;
  ...... 省略 get set 方法
  }
  构建TestAction
  继承BaseWebTestAction

public class LoginActionByHand extends BaseWebTestAction { public LoginActionByHand(WebDriver driver, TestData testData) { super(driver, testData);
  } @Override public void execute() { //完全手动写TestAction LoginPage page = HtmlElementsLoader.createPageObject(driver,LoginPage.class);
  page.getUserCode().input(testData.get("userCode")); //or convert the test data to a model to get the value page.getPassword().input(testData.get("password"));
  page.getSubmit();
  }
  }

还有一种方式来些TestAction就是: 使用TestActionBuilder来写,可以给Builder添加多个TestAction,这个主要是组合多个TestAction使用的

  public class LoginActionSuperExecutor extends BaseWebTestAction {
  public LoginActionSuperExecutor(WebDriver driver, TestData testData) {
  super(driver, testData);
  }
  @Override public void execute() {//使用ActionBuilder // build 可以添加多个TestAction, 这样就达到了组合不同Action的目的 TestActionsBuilder.build(new LoginActionByHand(driver,testData)).
  addAfterActions(new TestAction() { // add AfterAction的意思就是可以在有些步骤后面添加一些特殊处理 @Override public void execute() {
  driver.get("[http://gzz.dooioo.com/workspace](http://gzz.dooioo.com/workspace)");
  }
  }).execute(); // 也可以在最后自己写一些特殊处理 driver.get("[http://gzz.dooioo.com/workspace](http://gzz.dooioo.com/workspace)");
  }
  }

构建测试类

public class LoginFlowByExecutorTest extends BaseWebTest { User user = new User(“110863”,“abcd1235”); @Test public void testLoginAction(){
  LoginActionByHand flow1 = new LoginActionByHand(driver,user);
  flow1.execute();
  System.out.println(“end of test”);
  } @Test public void testLoginAction_getTestActionName(){
  Assert.assertEquals(new LoginFlowByExecutor(driver,user).getTestActionName(),“LoginFlowByExecutor”);
  }
  }

  注解方式来构建TestAction
  在Page类上面添加注解,构建某个流程 格式如下例:
  UIActions 表示有多个UIAction的注解,每一个UIAction就表示一个TestAction
  每一个UIAction实际表示一个TestAction 下面这个例子中登陆,登陆2可以认为是两个不同的操作流程 elementActionDescription描述的是操作元素的动作,userCode input表示在元素userCode上面进行输入,输入什么,其实就是TestData中userCode的值 对于InputBox来说,动作input就是Inputbox的默认动作,所以在登陆2里面就省略了,所有省略动作的藐视都是用默认动作进行处理
 ```
 @UIActions(
  actions = { @UIAction(processName = "登陆",
  elementActionDescription = {"userCode input","password input","submit click"}), @UIAction(processName = "登陆2",elementActionDescription = { "userCode","userCode ","submit " })
  }
  ) public class LoginPageAnnotationWithUIAction extends BasePage { @FindBy(id= "usercode") private InputBox userCode; @FindBy(id="password") private InputBox password; @FindBy(id="msg") private HtmlElement msg; public Button getSubmit() { return submit;
  } public void setSubmit(Button submit) { this.submit = submit;
  } @FindBy(className = "btn_login") private Button submit;
  。。。。。。。 省略get/set 方法
  }
  构建注解方式的TestAction
  同样适用TestActionBuilder就可以了
  public class LoginActionByExecuteUIAction extends BaseWebTestAction { public LoginActionByExecuteUIAction(WebDriver driver, TestData testData) { super(driver, testData);
  } @Override public void execute() {
  LoginPage page = LoginPage.createPage(LoginPage.class,driver);
  AnnotationBasedActionBuilder.executeUIAction(page,"登陆",testData);
  }
  }

构建测试类
  构建测试类的方式和上面构建测试类是其实是一样的
  API/WebService 自动化测试
  API(接口)数据驱动测试
  API(接口)测试,这里主要是指http请求或者是指restful service类型的测试.主要的测试思路是根据API的规格 构造api的请求,然后向服务端发起请求,这样就可以得到服务端的请求返回值,进行验证。因此在整个测试过程 中如果构建这个请求是一个关键点,关于构建请求在前面介绍APITest的时候有提到过,可以参考 一下。但是一下的内容是在前文的基础上做了一些封装后,可以写少一点代码来实习API的数据驱动测试

如果你想学习软件测试的,我给你推荐个群:903217991,里面有从基础开始学习的软件测试学习视频讲解,还有大牛帮你解决疑惑。
  API(接口)测试流程
  在做了一些封装之后,api测试包括了以下几个步骤:

  • 构建一个JSON文件来描述这个API的接口
  • 构建一个调用这个API的java 类(构建请求)
  • 构建和API规格说明相匹配的一个外部数据(excel)
  • 构建测试用例类
     构建JSON的API接口描述文件
      以下是一个简单的json用来描述API,主要有以下几个字段:
  • queryParamters: 这个字段不是必须的,用来记录URL里面的可选参数,也就是在URL里面?之后的参数的
  • pathParameters: 这个字段也不是一个必须要填写的,这个参数主要是用来记录URL中的参数在//之间的
  • method:这个是必须要填写的,这是请求的方式,主要包括了get/post/delete/put等
  • resourceURL:必须填写,用来标示请求资源的位置
  • contentType:不是必须填写,如果请求的contentType是application/json,则可以不写,否则需要填写
  • headers,不是必须填写,一般情况下可以不需要填写,因为默认的header值已经在工具类里设好了
  • body: 如果请求没有body,可以不用填写,否则建议填写请求对应的JSON的类名(也不是必须要写的,目前框架还没有支持)
      事实上一上内容大部分不是必须要填写的,但是还是建议可以填写完成,或许以后会用到。
  {
  "queryParameters":["userCode", "password" ],
  "pathParameters":["ticketId","userId"],
  "method":"POST",
  "resourceURL":"/login",
  "contentType":"application/x-www-form-urlencoded",
  "headers":{"tokenId":"1234567432","Authorization":"890998776"} "body":"com.abcd.ddsf" }

构建一个调用API的JAVA类
  以下是构建一个调用API的JAVA类的例子,需要做以下的事情: - 这个类需要继承BaseWebService - 起上一个和这个API做的事情相匹配的名字 - 指定描述那个API接口的JSON文件的路径 - 继承BaseWebService的构造函数

  public class LoginAPI extends BaseWebService { private final static String loginAPIDescriptionPath = "servicedescription/loginapi.json"; public LoginAPI(RequestData data) { super(loginAPIDescriptionPath, data);
  }
  }

构建测试数据文件
  测试数据还是使用外部excel的方式,他的格式基本可以固定,如下例:img
  解释一下这个数据: RequestData.queryParameters(usercode), 表示queryParameter的一个key值是usercode,value就是用来进行数据驱动测试的值。
  那么如果需要body的值呢,只要excel新增一列,列的第一行名字是RequestData.body就可以,如果是JSON格式的,就把真实的JSON这里就可以
  如果是pathParameter,那么就是RequestData.pathParameters( k e y ) , {key}), key){key}表示你的pathParameter的名字
  这个测试数据文件,需要放在Test的resource是目录里面,可以放在一个子目录里面。
  构建测试用例
  主要步骤包括: - 构建Dataprovider - 构建测试方法

  @DataProvider(name="login_data") public Iterator getLoginData(Method m) throws InvocationTargetException, Exception, IOException {
  Map clazzMap = new HashMap();
  clazzMap.put("RequestData", RequestData.class); // build的参数就是所在测试数据文件的位置 Iterator y= ExcelHelper.build("testcase/login/loginapitest.xls").loadExcelDataToIterator(clazzMap); return y;
  } @Test(dataProvider = "login_data") public void testLoginAPITes(RequestData data){
  LoginAPI api = new LoginAPI(data);
  api.execute(); //获取返回的类 System.out.println(api.getResponse()); //获取返回的状态代码,如200,302,401,500 ....... System.out.println(api.getResponse().getStatusCode()); //获取返回的包体 System.out.println(api.getResponse().getBody().toString()); //获取返回的header内容 System.out.println(api.getResponse().getHeaders()); //可以根据返回值内容进行验证 }

具体的验证内容需要在得到返回值之后进行验证,由于每个接口的返回值都不一样,所以都需要定制这些检查点.
  如果你想学习软件测试的,我给你推荐个群:903217991,里面有从基础开始学习的软件测试学习视频讲解,还有大牛帮你解决疑惑。
  API测试代码结构

  • API类: 放置在apis目录里面
  • JSON: 放置在resource的servicedescription目录下
  • 测试数据文件: 放置在resource的testcase下面目录下,可以起一个子目录,名字和API相匹配
  • 测试类: 放置在test目录相面

结语:

如果你想学习软件测试的,我给你推荐个群:903217991,里面有从基础开始学习的软件测试学习视频讲解,还有大牛帮你解决疑惑。

你可能感兴趣的:(自动化测试框架de详细搭建)