Web UI自动化测试系统设计

1. 自动化测试简介

1.1 什么是好的自动化测试框架

在创建测试自动化框架时,我们应该考虑以下要点:

  1. 能够通过使用适当的抽象层快速创建自动化测试
  2. 应易于维护和扩展应该足够简单,以便测试人员编写自动化测试
  3. 该框架应具有有意义的日志记录和报告结构
  4. 重新运行失败测试的重试机制 - 这对WebDriver UI测试特别有用
  5. 对现有系统不会造成影响(setup teardowm)
  6. 最小化测试用例之间的重复 Minimize Test Overlap
  7. 每个用例之间相互独立 Keep each Test independent
  8. 将测试和产品代码分开 Keep test logic out of production code
  9. 对测试用例执行结果进行校验 Verify one condition per test

1.2 自动化测试的基本步骤

自动化测试的基本步骤.png
  1. Setup
    构造用例执行前的前置条件,构造执行环境
  2. Exercise
    执行用例
    3.Verification
    对执行结果进行校验
  3. Teardown
    用例执行结束后,对执行环境进行还原,使SUT回到用例执行前的状态

1.3. 自动化测试常用的思路

1.3.1 记录和回放Record and playback

  1. 功能
    直接录制执行过程,并回放
  2. 实现
    通过录制小工具,将用户对网页的操作过程记录保存
  3. 好处
    适合新手,上手快
  4. 缺点
    稳定性差,xpath一般是根据元素的绝对位置生成,稳定性很差
  5. 应用
    selenium、katalon等测试框架均支持相应的录制工具

1.3.2 数据驱动Data driven

  1. 功能
    “测试数据”与“执行代码”做分离, 使用不同的输入数据测试相同的工作流程。
  2. 实现
    将不同的场景对应的参数提取出来,放在文件中,使用时,只需要遍历文件,将这些参数分别作为测试流程的入参,生成多个测试用例
  3. 好处
    可以通过导入不同的配置,设置不同的执行场景,提高复用性
  4. 坏处
    测试数据和测试流程强关联,如果新增功能,需要增加新的配置参数,增加了使用和扩展的复杂性,只适用于单个简单行为测试,不适合流程测试
  5. 应用
    robotframework中的template,katalon中data set

1.3.3 关键字驱动Keyword driven

  1. 功能
    对页面上的操作行为进行拆分和抽象,保存为一个个具体的行为关键字。用户根据需求对关键字进行组装

  2. 实现
    将每个页面的操作行为,封装为不同的关键字函数,测试用例可调用不同关键字,组成不同的操作流程

  3. 好处
    将单个行为和系统流程拆分,减少耦合,所有的用例针对同一个行为是调用同一个函数,减少维护成本

  4. 坏处
    关键字的个数和页面功能的复杂性成正比

  5. 应用
    page object model

2. 自动化测试设计模式

2.1 Page Object Model

2.1.1 为什么

    考虑这个简单的脚本登录网站:

    如图所示,我们所做的只是找到元素并为这些元素填充值。这是一个小脚本。脚本维护看起来很简单 但随着时间的推移测试套件将会增长  随着代码添加越来越多,维护将变得越来越困难。脚本维护的主要问题是,如果10个不同的脚本使用相同的页面元素,并且该元素有任何更改,则需要更改所有10个脚本。这是耗时且容易出错的。
     更好的脚本维护方法是创建一个单独的类文件,该文件可以找到Web元素,填充它们或验证它们。可以在使用该元素的所有脚本中重用此类。将来,如果Web元素发生更改,我们只需要在1个类文件中进行更改,而不是10个不同的脚本。这种方法称为页面对象模型(POM)。它有助于使代码  更具可读性,可维护性和可重用性。

2.1.2 是什么

Page Object Model是一种为Web UI元素创建Object Repository的设计模式。在此模型下,对于应用程序中的每个网页,应该有相应的页面类。此Page类将查找该Web页面的WebElements,还包含对这些WebElements执行操作的Page方法。这些方法的名称应根据它们正在执行的任务给出,即,如果加载程序正在等待显示支付网关,则POM方法名称可以是waitForPaymentScreenDisplay()。

关于页面对象是否应该包含断言本身,或者仅为测试脚本提供数据以进行断言,存在意见分歧。
在页面对象中包含断言的倡导者说,这有助于避免在测试脚本中重复断言,使得更容易提供更好的错误消息,并支持更多的TellDontAsk样式API。
无断言页面对象的倡导者说,包含断言将提供对页面数据的访问权限与断言逻辑混合在一起,并导致一个膨胀的页面对象。
我赞成在页面对象中没有断言。我认为您可以通过为常见断言提供断言库来避免重复 - 这也可以使提供良好诊断更容易。页面对象通常用于测试,但不应自行进行断言。他们的职责是提供对底层页面状态的访问。由测试客户端来执行断言逻辑。

2.1.3 好处

  1. 页面对象模式表示UI中的操作和流程应与验证分开。这个概念使我们的代码更清晰,易于理解。
  2. 对象存储库独立于测试用例,因此我们可以使用相同的对象存储库用于不同的工具。例如,我们可以将POM与TestNG / JUnit集成用于功能测试,同时与JBehave / Cucumber集成以进行验收测试。
  3. 由于POM类中可重用的页面方法,代码变得更少并且得到优化。
  4. 方法获得更真实的名称,可以通过UI中的操作轻松映射。即如果点击我们登陆主页的按钮后,方法名称就像'gotoHomePage()'。

2.1.4 实现

简单的例子:


详细的例子:

步骤1)转到Guru99演示站点


步骤2)在主页检查文本“Guru99 Bank”存在


步骤3)登录应用程序


步骤4)验证主页是否包含“Manger Id:demo”


功能中包含两个页面:

  1. 登录页面
  2. 主页(登录后显示)
    因此,我们创建了2个POM类

1. Login page POM

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

public class Guru99Login {

WebDriver driver;

By user99GuruName = By.name("uid");

By password99Guru = By.name("password");

By titleText =By.className("barone");

By login = By.name("btnLogin");

public Guru99Login(WebDriver driver){

    this.driver = driver;

}

//Set user name in textbox

public void setUserName(String strUserName){

    driver.findElement(user99GuruName).sendKeys(strUserName);

}

//Set password in password textbox

public void setPassword(String strPassword){

     driver.findElement(password99Guru).sendKeys(strPassword);

}

//Click on login button

public void clickLogin(){

        driver.findElement(login).click();

}

//Get the title of Login Page

public String getLoginTitle(){

 return    driver.findElement(titleText).getText();

}

/**

 * This POM method will be exposed in test case to login in the application

 * @param strUserName

 * @param strPasword

 * @return

 */

public void loginToGuru99(String strUserName,String strPasword){

    //Fill user name

    this.setUserName(strUserName);

    //Fill password

    this.setPassword(strPasword);

    //Click Login button

    this.clickLogin();        
}

}

2. Home Page POM;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

public class Guru99HomePage {

WebDriver driver;

By homePageUserName = By.xpath("//table//tr[@class='heading3']");



public Guru99HomePage(WebDriver driver){

    this.driver = driver;

}

//Get the User name from Home Page

    public String getHomePageDashboardUserName(){

     return    driver.findElement(homePageUserName).getText();

    }

}

3. 测试用例

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.firefox.FirefoxDriver;

import org.testng.Assert;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.Test;

import pages.Guru99HomePage;

import pages.Guru99Login;

public class Test99GuruLogin {

WebDriver driver;

Guru99Login objLogin;

Guru99HomePage objHomePage;

@BeforeTest

public void setup(){

    driver = new FirefoxDriver();

    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

    driver.get("http://demo.guru99.com/V4/");

}

/**

 * This test case will login in http://demo.guru99.com/V4/

 * Verify login page title as guru99 bank

 * Login to application

 * Verify the home page using Dashboard message

 */

@Test(priority=0)

public void test_Home_Page_Appear_Correct(){

    //Create Login Page object

objLogin = new Guru99Login(driver);

//Verify login page title

String loginPageTitle = objLogin.getLoginTitle();

Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank"));

//login to application

objLogin.loginToGuru99("mgr123", "mgr!23");

// go the next page

objHomePage = new Guru99HomePage(driver);

//Verify home page

Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123"));

}

2.1.5 扩展

Page Factory是Selenium WebDriver的内置页面对象模型概念,但它已经过优化。在这里,我们遵循页面对象存储库和测试方法的分离概念。另外,在PageFactory类的帮助下,我们使用@FindBy注释来查找WebElement。我们使用initElements方法初始化Web元素

@FindBy可以接受tagName,partialLinkText,name,linkText,id,css,className,xpath作为属性。让我们使用Page Factory查看与上面相同的示例

2.2 BDD (Behavioral Driven Development)

2.2.1 为什么

软件开发中常见的浪费活动包括:

  1. Dev/QA/BA对需求理解不一致,由于误解或模糊的要求导致的返工
  2. 由于不愿意重构代码而导致的技术债务
  3. 孤岛和交接造成的反馈周期缓慢

低行为的沟通可能是使用BDD的最大优势,使技术团队和非技术团队之间的协作能够以更高的效率运行。用通用语言编写的BDD测试用例的优点是所有人都可以容易地理解应用程序的行为方式。例如,可以使用实际需求的实时示例编写测试用例,以解释系统的行为,减少误解。

能更方便的会用例进行管理

2.2.2 是什么

行为驱动开发(BDD)是一种从TDD(测试驱动开发)发展而来的软件开发方法。它的不同之处在于用共享语言编写,这改善了技术与非技术团队和利益相关者之间的沟通。在这两种开发方法中,测试都是在代码之前编写的,但在BDD中,测试更加以用户为中心,并且基于系统的行为。设计要求为:

  1. 需求应转换为可定义具体示例的用户故事。
  2. 每个示例都应该是有效的用户场景,而不仅仅是测试用例。

2.2.3 应用

'Given-When-Then'公式
这是为用户故事编写BDD测试用例的建议模板,可以定义为:

  • 给定某种情况

  • 当一个动作发生时

  • 那么这应该是结果。

一个实际的例子是:

  • -由于用户没有输入窗体上的任何数据。

  • 当他们点击提交按钮

  • 然后显示验证成功的消息

2.2.4 好处

  1. 不再定义'测试',而是定义'行为'。
  2. 开发人员,测试人员和产品所有者之间更好的沟通因为使用简单语言解释BDD,学习曲线将更短。
  3. 它本质上是非技术性的,可以覆盖更广泛的受众。
  4. 行为方法在开发之前定义了验收标准。

2.2.5 坏处

  1. 要在BDD工作,需要先前的TDD经验。
  2. BDD与瀑布式方法不兼容。
  3. 如果未正确指定要求,BDD可能无效。
  4. 使用BDD的测试人员需要具备足够的技术技能。

3. 自动化系统设计实例

3.1 为什么要分层

  1. 用户在对web UI进行测试时,一般会包含多个Page(功能页面),每个Page都有自己的UI元素和行为操作,各个Page之间相互不干扰,需要分离。

  2. 在新增用例的时候,每个用例设计时都需要考虑配置信息、页面元素信息、行为操作、具体流程设计。不同用例之间的配置信息、页面元素信息、行为操作会有重叠部分,只是流程上会有差异,因此,需要将业务操作和测试用例分离,进行分层设计。

因此,测试系统设计可采用Page Object Model设计模式,以用户登陆为例,可以分成以下几个层次:

Page层:完成单个页面页面元素、页面行为的配置,包括CommonPage基本页面层、PageElement页面对象层、ActionOperator行为操作层。
Workflow TCs:完成单个页面的行为流程和校验的test cases,该test case不能直接执行,只能被真正Main TCs引用。
Main TCs:真正执行的测试用例
Test Suite:测试用例集合
Data-bingding:测试系统所需的配置数据

3.2 Data-binding 数据配置层

功能: 完成系统配置,如:web服务地址、用户名、密码、git/p4地址等信息
实现:

  1. katalon本身支持dataMap,可以上传excel/csv文件,该文件可以被多个testcase同时复用
  2. 配置全局的Execution Profile,此时变量可以在各个case中使用
  3. case 可以设置全局变量和case 内部的变量

3.3 Page层

完成单个页面页面元素、页面行为的配置

3.3.1 CommonPage基础页面层

功能: 完成Page交互时的通用功能,如:点击、切换到frame、拖动滚动条、元素获取等. 该层是Page最底层,可供ActionOperator行为操作层调用

实现:定义CommonPage,调用katalon WebUI对应的接口,实现上述功能。

3.3.2 PageElement页面对象层

功能:保存不同page的元素path。当页面元素变更了,直接修改单个元素,不存在测试用例维护问题。

实现:新建Object Repository, 按照page划分目录,对每个page的元素Xpath/Css/Arribute进行配置

3.3.3 ActionOperator行为操作层

功能:对每个Page用户独立的行为操作进行封装,如:登陆、新增workspace等。将业务操作与测试用例分离,因为多个用例可能是对应一个业务操作的,这样,我业务代码ji'hu,只需要修改用例就好了。

实现:继承于 CommonPage,实现各个页面独有的所有行为(不包括校验)。每个页面的元素,引用于 PageElement页面对象层

命名:

  • 应该尽可能具有描述性名称
  • 清晰解释这个关键字是做什么的,而不是怎么做的,是抽象级别的(譬如:Input Text或者Administrator logs into system)
  1. 去掉后缀下划线换成空格
  2. 如果名字全部小写,单词首字母换成大写名字可能适当加长
    Good:
    Login With Valid Credentials

Bad:
Input Valid Username And Valid Password And Click Login Button

3.4 WorkFlow TCs 工作流程层

功能:对每个page可能的页面流程进行设计并校验。

实现: 引用ActionOperator行为操作层,将页面流程封装称测试用例

3.5 TestCase测试用例(Main TCs)

功能:完成具体测试用例

实现 : 调用WorkFlow工作流程层,进行流程组装

命名:

  • 应该尽可能具有描述性名称
  1. 去掉后缀下划线换成空格
  2. 如果名字全部小写,单词首字母换成大写名字可能适当加长

例子:
Login With Empty Password Should FailLogin With Empty Username Should FailLogin With Empty Username And Password Should FailLogin With Invalid Username Should FailLogin With Invalid Password Should FailLogin With Invalid Username And Invalid Password Should Fail

3.6 TestSuit测试用例套件层

功能:每个testSuit中包含多个测试用例,可对testcase进行分组,指定待执行的测试用例。
实现:配置test suit
命名:

  • 应该尽可能具有描述性名称
  1. 去掉后缀下划线换成空格
  2. 如果名字全部小写,单词首字母换成大写名字可能适当加长
    举例:login_tests.robot -> Login Tests
    IP_v4_and_v6 -> IP v4 and v6

3.7 Log日志层

功能: 保存测试用例中运行过程中的日志、截图。

实现:

  1. 采用katalon本身的日志打印,KeywordUtil.logInfo(String message). 而不是Print函数
  2. webUi.takeScreenshot()可以直接截图
    3.katalon支持配置录屏功能

3.8 Report报告层

功能: 保存执行结果。
实现:katalon默认会生成每个test suit执行结果

3.9 SetUp 和 TearDown

功能:为每个测试用例/用例集提供用例执行的前置配置和后置配置
实现:

  1. 每个testcase内部支持自定义method

  2. testsuits中的script模式下可进行基于每个testcase和每个testsuit下的通用配置。

  3. Test Listeners支持全局范围内的配置。

执行顺序如下:

参考文档

page object model

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 洞见SELENIUM自动化测试 写在最前面:目前自动化测试并不属于新鲜的事物,或者说自动化测试的各种方法论已经层出...
    厲铆兄阅读 6,706评论 3 47
  • 基于 SELENIUM 的自动化测试架构 非常感谢各位查阅本篇文章,笔者在此感谢各位。 目前市面上有分门别类的自动...
    厲铆兄阅读 6,042评论 6 43
  • 当前一切UI自动化都是建立在selenium2的API基础上的,最底层都是调用的模式。 UI自动化主要的体现应该在...
    我为峰2014阅读 5,571评论 0 7
  • 大多数的iOS App (没有持续集成)迭代流程是这样的: 也就是说,测试是发布之前的最后一道关卡。如果bug不能...
    伯牙呀阅读 4,864评论 1 22
  • 区块链1.0应用以比特币为代表,为了解决货币和支付手段的去中心化,那么区块链2.0就是更宏观的对整个市场的去中心化...
    李壮相阅读 1,727评论 0 2