Selenium Web 自动化测试框架 sweetest 介绍

tonglei · 2017年10月16日 · 最后由 OSCer 回复于 2021年11月23日 · 3494 次阅读

介绍

sweetest 是一款 Web 自动化测试框架,或者说是解决方案,名字取 Selenium, Web UI, Excel, Element, Test 含义。
特点:

  1. 简单快速,轻松上手
  2. 无需编码能力
  3. 在 Excel 中以文本编写测试用例
  4. 维护成本低
  5. 支持千、万级别的用例规模
  6. 拥抱变化,支持敏捷

背景

目前,Web 自动化测试基本上是以 Selenium 为接口来编写测试代码,但效果往往不是很好,普遍遇到如下问题:

  1. 用例设计人员的编码能力很弱,测试代码编写和维护成本高,效果差;
  2. 测试代码量大,测试意图不直观,无法支撑千、万级别的用例规模;
  3. Web 页面元素的定位非常繁琐,且页面结构经常变动,导致用例失效。

我们知道,传统的测试用例一般是在 Excel 中用文本编写的,如果自动化测试用例也这么写,是不是就可以解决问题 1 和 2?
对于问题 3,我想是时候对开发提出一些要求了,同时我们的元素定位也要优化,让页面自由的去变化,而我们的定位只做最小适用。

实现思路

  1. Selenium 为底层接口;
  2. 在 Excel 中用文本编写测试用例;
  3. 元素定位表格化,且优先使用 “板块通用定位法”;
  4. 要求开发提供必要的、统一的元素属性;
  5. 框架负责解析测试用例,执行用例,记录日志,输出测试结果。

方案

  1. 开发语言:Python
  2. 底层接口:Selenium
  3. 用例工具:Excel

测试用例如下图:
testcase

安装

环境要求

  • 系统要求:Windows
  • Python 版本:3.6+
  • Selenium
  • 浏览器:Chrome
  • Chrome 驱动: chromedriver

安装 sweetest

pip install sweetest

快速体验

打开 cmd 命令窗口,切换到某个目录,如:D:\Autotest

sweetest
cd sweetest_sample
python start.py

install

OK,如果一切顺利的话,sweetest 已经跑起来了

目录结构

dir

目录 说明
element\ 页面元素表目录
\Baidu-Elements.xlsx 页面元素表,名称格式:project_name + "-Elements.xlsx"
junit\ junit 格式测试结果目录
log\ 自动化测试运行日志目录
report\ Excel 格式测试结果目录
snapshot\ 错误截图目录
testcase\ 测试用例目录
\Baidu-TestCase.xlsx 测试用例,名称格式:project_name + "-TestCase.xlsx"
start.py 启动脚本,test = Autotest(project_name, sheet_name)

备注:以上 3 处的 project_name 必须一致

页面元素表

页面元素表的作用主要是把元素定位独立出来,一是方便维护定位信息,二是测试用例中用元素名称书写,可读性更高。

elements

目录 注释
page element 所在的页面,在所有页面都可用的 element 放在 “通用” 下面,如 title
frame element 所在的 frame id,如果是顶层 frame,可为空。
name element 名称,在不同的 page 下面可以同名
by Selenium 定义方式
value Selenium 定义的值
备注 注释作用

元素定位

  1. id, link_text, partial_link_text, xpath, class_name

    如:

    page name by value
    百度搜索页面 搜索框 id kw

    则自动化运行时会以 find_element_by_id('kw') 来定位

  2. 带变量的定位方式

    如示例中:

    page name by value
    百度搜索页面 搜索结果 # xpath //*[@id="#"]/h3/a

    写用例时,需要在 搜索结果 # 后面带上变量,如: 搜索结果 #1

    操作 页面 元素
    点击 百度搜索页面 搜索结果 #1

    则自动化运行时会以 find_element_by_xpath('//*[@id="1"]/h3/a') 来定位

    已定义好的常用变量定位方式:

- id#
- link#
- *link#
- xpath#
- class#
- name#
- url#

如:url#www.baidu.com

当然,如果 # 后面的变量不够直观的话,不建议太多使用这几个变量方式。

  1. 页面标题

    页面的 title

  2. 页面 URL

    页面的 url

    一般来讲,导航栏在所有页面都存在,应该把导航栏放在 “通用” 下面,做成变量定位方式,如示例中的:

    page name by value
    通用 搜索页导航栏 # xpath //*[@class="s_tab"]//a[text()="#"]

    用例中的写法:

    操作 页面 元素
    点击 通用 搜索页导航栏 # 新闻

测试用例

testcase

下拉菜单配置

操作、页面、元素这些列其实都是选项列表,利用 Excel 的下拉菜单功能,能够让书写用例更方便,且不易笔误。
下图是测试用例文件中的 ElementsMap 页面:

maps

我们可以通过 Excel 的菜单栏 “公式 - 名称管理器” 来配置这些菜单,同时在用例页面通过 “数据 - 数据有效性” 配置好 “操作” 的下拉菜单,以及 “页面 - 元素” 的二级联动下拉菜单。

用例字段

必填字段:

  • 用例编号
  • 步骤编号
  • 操作
  • 页面
  • 元素

前置条件:

  • BASE: 整个测试套件的基础,必须通过才会执行下一步,如:登录;如果有的话应该为第一个测试用例。
  • SETUP:每个测试用例执行前需要执行的用例,只有 SETUP 执行成功才会执行该用例,如:返回首页。
  • MAIN:一组用例的第一用例,和 SUB 一起使用,一个 MAIN 后面可以带多个连续的 SUB 用例。此用例需要先执行 SETUP 用例。
  • SUB:和 MAIN 一起使用,当前一个用例 (MAIN or SUB) 执行结果为通过时才会执行,否则测试结果置为 Blocked;且执行此用例前不会执行 SETUP 用例。
  • SNIPPET:用例片段,运行到此用例时不会立即执行,需要在其他用例中使用 “执行” 关键字调用此 “用例片段”,才会执行;配合 “执行” 关键字的变量赋值功能,可以实现用例复用。

注意事项:

  • 一般必须有 SETUP 用例。当执行 SETUP 失败,会尝试执行一次 BASE->SETUP 作为 SETUP 的执行结果。
  • BASE 用例可以有 0 到多个,但作为 SETUP 中 BASE->SETUP 的 BASE 只有最后一个 BASE 用例。
  • SETUP 用例只能有 1 条,如果写了多条,只有最后一条起作用。

操作 (关键字) 及对应的测试数据

  • 打开

    get 方法,打开一个链接。

    打开操作,一般要在测试数据中指定新窗口名称,如:新窗口=百度搜索窗口。

  • 检查

    取页面元素的值、属性和预期结果对比。

    测试数据中如果没有写 “k=v” 的方式,则默认是取元素的 text。

    • 检查 text:
    操作 页面 元素 测试数据
    检查 百度搜索页面 搜索按钮 百度一下

    等价于

    操作 页面 元素 测试数据
    检查 百度搜索页面 搜索按钮 text=百度一下
    • 检查属性:
    操作 页面 元素 测试数据
    检查 百度搜索页面 搜索框 name=wd
    • “页面标题” 和 “页面 URL” 直接在测试数据中写预期结果即可。
    操作 页面 元素 测试数据
    检查 百度搜索页面 页面标题 百度一下\,你就知道

    注意:测试数据中,由于逗号 (,or ,) 是多个 “k=v” 的分隔符,所以如果 v 中有逗号,要用反斜杠 (\) 转义;但等号 (=) 无需转义。

  • 输入

    在输入框中输入文本。

    测试数据列为要输入的内容。

  • 点击

    点击按钮或者链接等 (一切可点击操作的) 元素。此关键字支持在同一个页面上顺序点击多个元素,在元素列以竖杠 (|) 分割即可,如:

    操作 页面 元素
    点击 百度搜索页面 搜索按钮 | 搜索结果 #1
  • 移动到

    有些页面元素,当鼠标移动到上面时,会弹出下拉菜单等。此操作同关键字 “点击” 类似。

  • 执行

    即执行测试用例片段,支持在测试数据中给变量赋值,如我们有用例片段 SNIPPET_001,则测试用例 BAIDU_002 中,步骤 1 如下:

    操作 页面 元素 测试数据
    执行 用例片段 SNIPPET_001 keywords=搜狗

    把变量 keyswords 赋值为 “搜狗”,此步骤会执行用例片段 SNIPPET_001,其搜索的关键字为 “搜狗”。

  • # 检查

    把检查结果反向,此关键字暂时未完整实现。

测试数据:

测试数据支持模糊匹配,如下:

操作 页面 元素 测试数据
检查 通用 页面标题 * 知乎

则,页面标题中含有 “知乎” 即为通过。注意星号 (*) 要写在开头。

输出数据:

在运行时,把元素的值或属性赋值给变量,此变量可以在之后的步骤中使用"<>"引用变量名。

操作 页面 元素 测试数据 输出数据
点击 百度搜索页面 搜索结果 #1 title=text
检查 通用 页面标题 <title>

步骤编号:

除了控制语句符号外,步骤编号必须为数字,建议在 Excel 中设置为文本格式。

控制语句:

  • if then else

    步骤编号 操作 页面 元素 测试数据
    ^3 检查 通用 页面标题 * 知乎
    >4 点击 通用 link# 登录
    <5 点击 通用 link# 注册机构号

    ^ 表示 if 语句

    > 表示 then 语句

    < 表示 else 语句

    if() 语句为真时,执行 then(>) 语句,为否时执行 else(<) 语句。无论后面有没有 then 或者 else 语句,不影响后续步骤执行。

    then 语句 或者 else 语句,当不被执行时,测试结果为 '-',不影响测试用例结果和后续步骤执行。当执行时,和正常步骤一样,成功则继续,失败则该用例失败。

进阶

元素管理

测试用例中元素是以 page + name 为唯一标识,来页面元素表中查找定位信息的。因此,不同 page 下的元素 name 可以相同,但不能和 “通用” 下的相同。

测试用例中,如果 page 不为 “通用”,当 <page> + name 查找不到,会继续以 “通用” + name 为标识符来查找。

“通用” 是方便我们写页面元素表的,写用例时我们建议还是用 <page> 来代替 “通用”,甚至有时候我们必须这么做。

窗口管理 (页面,frame)

在浏览器中,有可能会打开多个标签页,我们叫它为窗口。当你新打开一个标签页时,你可以在测试数据中给它起个名字,格式为:新窗口=, 如:

操作 页面 元素 测试数据
打开 通用 百度搜索链接 新窗口=百度搜索窗口
检查 百度搜索页面 页面标题 百度一下\,你就知道

当你给新的标签页起了窗口名字,它之后步骤的页面 ("通用"除外) 就会绑定到这个窗口。如上面第 2 步,“百度搜索页面” 会绑定到 “百度搜索窗口”。那么之后的步骤或用例中,即使打开了多个标签页,只要页面是 “百度搜索页面”,就会切换到 “百度搜索窗口” 这个标签页上操作。

注意:“通用” 是不绑定到任何窗口的,也不做窗口切换,它直接在 “当前窗口” 操作。

“当前窗口” 规则为:

  • 执行到某个步骤时,“当前窗口” 是浏览器焦点所在的窗口,也就是上个步骤执行操作的窗口。
  • 如果此步骤的页面已绑定到其他窗口,则 “当前窗口” 会切换过去。
  • 如果此步骤的页面尚未捆定任何窗口,则会捆定到 “当前窗口”。
  • 上个步骤如果是新打开的窗口,则 “当前窗口” 是新打开的窗口。

注意:

  • 如果打开了 2 个或以上窗口,没有起名字的窗口,在执行到切换窗口的步骤时,会自动被关掉。
  • 起了名字的窗口不会被关掉。
  • 但如果起了同样的名字,则原先的那个窗口会被关掉,绑定在其上面的页面也会被注销。

测试执行

python start.py

测试报告

见 report 目录

QQ 交流群:158755338 (验证码:python)

项目地址:https://github.com/tonglei100/sweetest

共收到 10 条回复 时间 点赞

大牛,我试用了下,感觉还不错啊,对复杂场景的支持是否可以支持呢?

这个貌似只能进行页面验证,多业务流程的没法验证,资源间共享怎么解决

lomoons 回复

和场景复杂度关系不大,只要所做的操作都有关键字就可以支持

jjj 回复

多业务流程依然是页面操作来完成的,你这里有什么特殊的地方吗?
资源共享?是指那些东东

2017-10-27 11:32:55,217 [INFO] autotest.py line:74 run: From Excel import testsuite success
2017-10-27 11:32:55,271 [DEBUG] remote_connection.py line:478 _request: POST http://127.0.0.1:49849/session {"capabilities": {"firstMatch": [], "alwaysMatch": {"browserName": "chrome", "version": "", "platform": "ANY", "chromeOptions": {"prefs": {"": "", "credentials_enable_service": false, "profile.password_manager_enabled": false}, "excludeSwitches": ["ignore-certificate-errors"], "extensions": [], "args": ["--start-maximized"]}}}, "desiredCapabilities": {"browserName": "chrome", "version": "", "platform": "ANY", "chromeOptions": {"prefs": {"": "", "credentials_enable_service": false, "profile.password_manager_enabled": false}, "excludeSwitches": ["ignore-certificate-errors"], "extensions": [], "args": ["--start-maximized"]}}}
2017-10-27 11:32:55,311 [DEBUG] remote_connection.py line:565 _request: Finished Request
2017-10-27 11:32:57,315 [CRITICAL] autotest.py line:86 run: Init global object fail
2017-10-27 11:32:57,316 [DEBUG] autotest.py line:87 run: Message: unknown error: chrome failed to start
(Driver info: chromedriver=2.24.417431 (9aea000394714d2fbb20850021f6204f2256b9cf),platform=Windows NT 6.1.7601 SP1 x86_64)

大神,我是菜鸟一枚,用您的这代码跑,报了上面的错,希望您可以将 sweetest 文件夹里的 pyc 文件以 py 的格式上传一下,我想查看一下源代码看看是不是我配置有问题,感恩

回复

因为是公司项目,还不确定领导对开源的态度,所以暂不开源

关于你这个问题,chromedriver 有对应支持的 Chrome 版本,你看一下对不对:http://chromedriver.storage.googleapis.com/2.33/notes.txt

chromedriver 下载地址:http://chromedriver.storage.googleapis.com/index.html

还有问题加 QQ 群,这里不常来
158755338 (验证码:python)

这个相当于是低层 selenium 实现,然后把用例表格化么?我做了几年 UI 自动化,确实代码量太大,如果这样感觉写用例起来快很多,就是不知道是否稳定?还有多个浏览器及窗口切换支持么?

@meilisong 支持标签页自动切换,但只能是一个浏览器。如果是需要切换登录用户,可以在打开网页时清除缓存来解决

sweetest 能做 http 的 api 接口测试吗?

请问这个框架是开源的吗,github 上面代码加密了,这算开源吗

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册