zoukankan      html  css  js  c++  java
  • 让自动化测试脚本更好地描述业务

    标签(空格分隔): 让自动化测试脚本更好地描


    如何把控操作函数的粒度?

    操作函数的粒度是指,一个操作函数到底应该包含多少操作步骤才是最合适的

    • 如果粒度太大,就会降低操作函数的可重用性。极端的例子就是,前面文章中涉及的百度搜索的案例,把“登录”“搜索”“登出”的操作作为一个操作函数。
    • 如果粒度太小,也就失去了操作函数封装的意义。极端的例子就是,把每一个步骤都作为一个操作函数。
    • 更糟糕的是,在企业实际自动化测试开发中,每个测试工程师对操作函数的粒度理解也不完全相同,很有可能出现同一个项目中脚本粒度差异过大,以及某些操作函数的可重用性低的问题。

    那么,操作函数的粒度到底应该如何控制呢?其实这个问题,在很大程度上取决于项目的实际情况,以及测试用例步骤的设计,并没有一个放之四海而皆准的绝对标准。

    但是,脚本粒度的控制还是有设计依据可以遵循的,即往往以完成一个业务流程(business flow)为主线,抽象出其中的“高内聚低耦合”的操作步骤集合,操作函数就由这些操作步骤集合构成。
    比如,对于“用户注册”这个业务流程,其中的“信用卡绑定”操作就会涉及多个操作步骤,而这些操作在逻辑上又是相对独立的,所以就可以包装成一个操作函数。也就是说,业务流程会依次调用各个操作函数,来完成具体的业务操作。

    如何衔接两个操作函数之间的页面?

    完成一个业务流程操作,往往会需要依次调用多个操作函数,但是操作函数和操作函数之间会有页面衔接的问题,即前序操作函数完成后的最后一个页面,必须是后续操作函数的第一个页面。如果连续的两个操作函数之间无法用页面衔接,那就需要在两个操作函数之间加入额外的页面跳转代码,或者是在操作函数内部加入特定的页面跳转代码。

    业务流程抽象

    在解决如何把控操作函数的粒度,以及如何衔接两个操作函数之间的页面这两个问题的过程中,我引入了业务流程的概念。
    这个概念有点拗口,难以理解。但是,没关系,我举个例子,你就豁然开朗了。
    假设,某个具体的业务流程是:已注册的用户登录电商平台购买指定的书籍。那么,基于业务流程抽象的测试用例伪代码,如图 1 所示。
    image.png-564.8kB

    这 4 个业务流程都是作为独立的类封装的,可以被很方便的重用并灵活组合,类的内部实现通常是调用操作函数。而操作函数内部,则是基于页面对象模型完成具体的页面控件操作。
    然后,对于每一个业务流程类,都会有相应的业务流程输入参数类与之一一对应。具体的步骤通常有这么几步:
    初始化一个业务流程输入参数类的实例;给这个实例赋值;用这个输入参数实例来初始化业务流程类的实例;执行这个业务流程实例。

    执行业务流程实例的过程,其实就是调用操作函数来完成具体的页面对象操作的过程。

    代码的第 2-6 行,调用的是 LoginFlow,完成了用户登录的操作。2: LoginFlowParameters loginFlowParameters = new LoginFlowParameters();3: loginFlowParameters.setUserName("username");4: loginFlowParameters.setPassword("password");5: LoginFlow loginFlow = new LoginFlow(loginFlowParameters);6: loginFlow.execute();

    第 2 行,初始化了 LoginFlow 对应的 LoginFlowParameters 的实例。第 3-4 行,通过 setUserName 和 setPassword 方法将用户名和密码传入该参数实例。第 5 行,用这个已经赋值的参数实例来初始化 LoginFlow。第 6 行,通过 execute 方法发起执行。执行之后,LoginFlow 会调用内部的操作函数,或者直接调用页面对象方法,完成用户登录的操作。

    伪代码的第 9-12 行,用和 2-6 行类似的方式调用了 SearchBookFlow,完成了书籍搜索的操作。

    9: SearchBookFlowParameters searchBookFlowParameters = new SearchBookFlowParameters();
    10: searchBookFlowParameters.setBookName("bookname");
    11: SearchBookFlow searchBookFlow = new SearchBookFlow(searchBookFlowParameters);
    12: searchBookFlow.withStartPage(loginFlow.getEndPage()).execute();

    需要特别注意的是,第 12 行中 withStartPage(loginFlow.getEndPage()) 的含义是,SearchBookFlow 的起始页面将会使用之前 loginFlow 的结束页面。显然,通过这种方式可以很方便地完成两个业务流程之间的页面衔接。同时,从中还可以看出,其实每个业务流程都可以接受不同的起始页面。以 SearchBookFlow 为例,它的起始页面既可以是书籍首页,也可以是其他页面,但是需要在它的内部对不同的初始页面做出相应的处理,以保证这个业务流程真正开始的页面是在书籍搜索页面。同样,由于业务流程存在分支的可能性,每个业务流程执行完成的最终页面也不是唯一的,你可以使用 getEndPage 方法拿到这个业务流程执行结束后的最后页面。通过这段代码的解读,你可以很清楚地理解,业务流程之间的页面衔接是如何实现的。

    伪代码的第 15-18行,调用了CheckoutBookFlow,完成了书籍购买操作

    15: CheckoutBookFlowParameters checkoutBookFlowParameters = new CheckoutBookFlowParameters();
    16: checkoutBookFlowParameters.setBookID(searchBookFlow.getOutPut().getBookID());
    17: CheckoutBookFlow checkoutBookFlow = new CheckoutBookFlow(checkoutBookFlowParameters);
    18: checkoutBookFlow.withStartPage(searchBookFlow.getEndPage()).execute();

    第 15 行,初始化了 CheckoutBookFlow 对应的 checkoutBookFlowParameters 的实例。第 16 行,通过 setBookID(searchBookFlow.getOutPut().getBookID()),将上一个业务流程 searchBookFlow 的输出参数,作为了当前业务流程的输入参数。这是典型的业务流程之间如何传递参数的示例,也是很多测试场景中都要用到的。第 17 行,用 checkoutBookFlowParameters 参数实例来初始化 checkoutBookFlow。第 18 行,通过 execute 方法发起执行。这里需要注意的是,checkoutBookFlow 的起始页面将会使用之前 searchBookFlow 的结束页面。开始执行后,checkoutBookFlow 会调用内部的操作函数,或者直接调用页面对象方法,完成书籍的购买操作

    伪代码的第 21-22 行,调用 LogoutFlow,完成了用户登出操作。

    21: LogoutFlow logoutFlow = new LogoutFlow();
    22: logoutFlow.withStartPage(checkoutBookFlow.getEndPage()).execute();

    第 21 行,由于 LogoutFlow 不带参数,所以直接初始化了 LogoutFlow。第 22 行,通过 execute 方法发起执行。这里 LogoutFlow 的起始页面将会使用之前 CheckoutBookFlow 的结束页面。开始执行后,LogoutFlow 会调用内部的操作函数,或者直接调用页面对象方法,完成用户登出操作。通过对这些代码的解读,我解释了业务流程是什么,并从使用者的角度分析了它的主要特点。比如,如何实现不同业务流程间的页面衔接,如何在不同的业务流程间传递参数等。为了加深印象,我再来总结一下业务流程的优点:业务流程(Business Flow)的封装更接近实际业务;基于业务流程的测试用例非常标准化,遵循“参数准备”、“实例化 Flow”和“执行 Flow”这三个大步骤,非常适用于测试代码的自动生成;由于更接近实际业务,所以可以很方便地和 BDD 结合。BDD 就是 Behavior Driven Development,即行为驱动开发,我会在后续文章中详细讲解。

  • 相关阅读:
    用wamp配置的环境,想用CMD连接mysql怎么连
    Mysql删除表
    MySQL创建表
    Leetcode 130. Surrounded Regions
    Leetcode 111. Minimum Depth of Binary Tree
    Leetcode 110. Balanced Binary Tree
    Leetcode 98. Validate Binary Search Tree
    Leetcode 99. Recover Binary Search Tree
    Leetcode 108. Convert Sorted Array to Binary Search Tree
    Leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/surewing/p/12593199.html
Copyright © 2011-2022 走看看