ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

gauge-python实践指南:用Markdown编写自然语言UI自动化用例

gauge-python实践指南:用Markdown编写自然语言UI自动化用例 简介Gauge是支持多种语言的轻量级测试自动化框架这个压缩包为其Python语言运行器插件面向测试开发工程师与自动化测试爱好者用于在Gauge规范中直接编写并执行Python步骤适合将Python生态与行为驱动开发结合使用的团队。资源压缩包共56个文件约70KB以34个Python源码文件为主体涵盖解析器、执行器、注册表、处理器等运行器核心模块并附带Markdown说明文档、YAML/Shell/Bat构建与配置脚本、依赖清单及项目配置信息结构清晰可分段阅读与二次开发。目前已有370人学习浏览属于小巧但完整的源码级工具包。进一步阅读时可重点观察消息协议处理、步骤注册与执行调度流程配合单元测试理解各模块职责针对Gauge插件机制或Python语言运行器有二次开发需求的读者也能从中获得直接的框架参考与实现范例。 半年前我们团队在调研UI自动化测试框架时遇到了一个很具体的问题业务同事要参加用例评审可pytest脚本在他们眼里就是一堆乱码换成behave之后大家又被Given/When/Then那套强制结构搞得放不开手。直到我翻到ThoughtWorks开源的Gauge情况才有了转机。Gauge的核心设计是规格即文档用例文件直接用Markdown编写步骤就是一句句自然语言。而gauge-python正是让Gauge这套框架能在Python生态里落地的语言运行器它负责建立spec步骤文本和Python函数之间的映射与调用。这篇文章我从环境搭建讲起覆盖步骤匹配、数据表、Hook、并行执行这些实战高频点再把我实际踩过的几个坑完整复盘一遍给准备用或者正在用gauge-python的测试工程师一个可参照的实践路径。1. gauge-python到底是什么它和Gauge核心的分工第一次接触Gauge的人很容易误解一件事装了Gauge就等于支持了Python。其实Gauge核心是一个用Go写的命令行工具它自己完全不执行测试代码。它的工作是扫描specs目录下的Markdown文件解析出规格、场景、步骤文本安排好执行顺序收集结果并生成报告。真正执行Python函数的是另一个独立进程也就是gauge-python运行器。这两个进程通过gRPC通信。当你执行gauge run时核心程序拉起gauge-python进程运行器启动后会扫描项目里的Python文件把所有带step装饰器的函数收集起来在进程内建一张步骤文本到函数的映射表。执行阶段核心把解析出来的步骤文本逐条发送过来运行器查表、调用函数、把执行结果回传。整个链路听起来有点绕但动手写过一遍之后就很好理解。1.1 理解分工后很多现象就有了合理解释为什么gauge run敲下去之后总要等一两秒才开始跑第一个步骤因为核心要先等待运行器完成加载和扫描。为什么步骤实现写得不对时错误信息看起来像协议异常而不是普通的Python堆栈因为异常要从运行器进程序列化后通过gRPC传回核心再打印中间链路长了信息自然会被包装。理解了这层翻译层的角色排查问题时就不容易慌。这种设计的实际收益也很明显。首先是语言解耦spec文件是纯文本换底层语言时用例文件一个字符都不用改只要装对应的运行器插件。其次是并发模型简单Gauge核心负责调度多个执行流每个流可以对应独立的运行器实例Python侧不需要自己实现复杂的并发控制。1.2 和behave/Cucumber那套玩法差异在哪用一句话概括Gauge比Cucumber系框架松得多。它没有强制Given/When/Then没有feature文件的缩进规则spec就是一个Markdown文件一级标题是规格名二级标题是场景场景下用无序列表写步骤。写出来的用例更像一份给人类看的验收清单。这个特点换来了更好的可读性但也把规范压力交给了团队自己。没人强制你步骤怎么命名如果团队写步骤随心所欲几个月后一样变成天书。我们在项目里定了两条规矩步骤描述一律动词开头涉及数据的部分全部做成参数而不是写死在文本里。这两条坚持下来spec文件看起来才一直像文档而不是代码。2. 安装配置里最容易被忽略的细节解释器与版本安装本身不复杂但装完跑不起来的比例很高而且大部分原因集中在两个地方Python解释器路径不对以及组件版本不齐。下面是我当时的完整安装顺序。# 1. 安装Gauge核心 brew install gauge # macOS choco install gauge # Windows # 也可以从GitHub releases下载对应系统的压缩包 # 2. 安装Python语言运行器插件 gauge install python # 3. 安装Python侧的库 pip install gauge-python # 4. 初始化标准项目结构 gauge init python # 5. 验证环境 gauge --version gauge envgauge init python会生成一个最小可运行的示例项目结构是标准的specs和step_impl两个目录。我的建议是刚装完先别写自己的用例直接跑一遍这个示例gauge run specs。如果示例能绿说明核心、插件、Python包这一整条链路是通的后面再出问题基本都是项目代码的问题排查范围一下子缩小很多。2.1 解释器路径问题venv是最容易被坑的一环gauge run启动运行器时是在PATH里找python命令来拉起gauge-python进程的。如果你直接开着系统Python跑运行器会把项目外的那套环境当成Python解释器后面import项目依赖就会报ModuleNotFoundError。我们项目用的是venv当初第一次碰到这个报错时我在依赖列表里反复检查都没发现问题后来才意识到运行器压根没走虚拟环境的Python。解决办法很朴素先在终端激活venv再执行gauge run保证gauge和运行器都继承虚拟环境的PATH。如果团队里有别的成员习惯用IDE里的终端还需要在项目文档里写清楚这一步不然新人接手第一件事就是踩这个坑。2.2 版本对齐一个很少被提起但必须锁定的组合gauge-python这条链上有三个版本概念Gauge核心版本、运行器插件版本gauge install python装的、PyPI上的gauge-python包版本。三者之间不是随便组合都能工作因为核心和运行器之间走gRPC协议协议版本不匹配时运行器可能直接崩溃或者报出完全看不懂的错误。我的建议是把组合钉在一个经过验证的版本上升级时当成一次专项来做。检查命令如下。gauge --version # 查看核心与已安装的插件版本 pip show gauge-python # 查看Python侧包版本 gauge update --all # 如果要升级插件统一升升级前先看Gauge官方文档里的兼容说明升级后立刻跑示例项目和回归用例。这套流程看起来多花几分钟但比在半夜排查一次明明什么都没改为什么挂了划算得多。3. 从第一个spec到可维护的步骤库匹配规则与参数传递假设项目已经init完成下面是我建议的第一次完整练习用spec描述一个登录场景。# 用户登录 ## 正常登录流程 * 打开登录页面 * 输入用户名 admin 和密码 admin123 * 点击登录按钮 * 页面跳转到首页对应的Python实现放在step_impl/step_impl.py里。from gauge.python import step step(打开登录页面) def open_login_page(): # driver是项目自己封装好的实例 driver.open(https://example.com/login) step(输入用户名 name 和密码 password) def input_credentials(name, password): login_page.input_name(name) login_page.input_password(password) step(点击登录按钮) def click_login_button(): login_page.submit() step(页面跳转到首页) def assert_homepage(): assert driver.current_url.endswith(/home)然后执行gauge run specs/控制台会按场景展示每个步骤的执行状态和耗时。3.1 参数匹配的规则引号和尖括号缺一不可这是gauge-python新手遇到最多困惑的地方。spec里凡是需要传参的数据都用双引号包起来而步骤注解里用一对尖括号加变量名占位。比如spec里是输入用户名 admin注解里就是输入用户名 运行器会识别出引号里的值把它作为参数传给函数。几个细节要特别留意spec里的引号必须是英文双引号写成中文引号或者单引号都会匹配失败。参数在spec里是什么类型函数收到的默认就是字符串。需要数字就得在函数里自己int()转换Gauge不会帮你做类型推断。没有参数的步骤spec文本和注解必须逐字符一致包括空格和标点。全角半角括号不一致这种问题报错信息不会告诉你是哪里不一样只能靠肉眼对比。我自己的习惯是先把注解里的文本完整复制到spec里再把需要参数化的值改成引号形式这样能减少一大半匹配类报错。3.2 步骤库组织从能跑到好维护距离不短一个项目迭代几个月后步骤数量很容易涨到几百个。如果全部堆在step_impl.py里文件会变成几千行的怪兽。我的做法是按业务模块拆分比如step_impl/login_steps.py、step_impl/order_steps.py模块之间用普通Python import互相调用。按官方约定把步骤实现放在step_impl目录下运行器加载这个目录里的模块时拆不拆分都不影响步骤发现。还有一条值得注意同一个步骤文本只能注册一次。如果你不小心在两个文件里写了相同的step文本运行器加载时不一定立刻报错但执行时会因为映射冲突出现不可预期的情况。所以重命名或者归类步骤时把步骤文本唯一这条写进团队代码评审清单是可以省下很多隐性bug的。4. 项目落地必须会的进阶能力数据表、Hook和并行执行等用例规模上来之后只靠最基础的步骤写法是不够的。这个部分说四个我几乎每个项目都会用到的能力。4.1 表格参数数据驱动最直观的写法spec里可以直接内嵌一张Markdown表格作为步骤参数非常适合做数据驱动的校验。* 下列单词的元音数应计算正确 | 单词 | 元音数 | |---------|--------| | gauge | 2 | | mingle | 2 | | thought | 3 |Python侧把表格参数声明出来按行迭代、按列名取值。表格参数在gauge-python里是以专用对象传入的不同小版本暴露的方法略有差别但迭代行、按列名取单元格这个思路是一致的。我第一次用的时候就是先在步骤里print一下参数对象看看它有哪些属性和方法再继续写业务逻辑。step(下列单词的元音数应计算正确 table) def assert_vowel_counts(table): for row in table: word row[单词] expected int(row[元音数]) assert count_vowels(word) expected, f{word} 元音数应为 {expected}4.2 概念Concept把步骤组合成业务动作有些动作在多个场景里反复出现比如登录它由四五个步骤组成。如果每个场景都展开写一遍spec文件会非常啰嗦。Gauge的解决办法是概念文件.cpt把一组步骤打包成一个新步骤。# 用户登录 * 打开登录页面 * 输入用户名 admin 和密码 admin123 * 点击登录按钮然后在spec里直接写* 用户登录就和调用一个步骤一样。概念还可以带参数比如把账号密码做成占位符在引用概念时传入具体值。这个概念机制是我觉得Gauge比许多BDD框架灵活的地方它允许你在spec的可读性和步骤的复用性之间自己找平衡。4.3 Hook和数据存储场景前后做事的标准姿势UI自动化几乎都要在每个场景前后准备和清理环境gauge-python提供了完整的Hook机制。from gauge.python import before_scenario, after_scenario from gauge.python import scenario_store, spec_store, suite_store before_scenario def init_browser(): # 每个场景前启动浏览器 after_scenario def close_browser(): # 每个场景后关闭浏览器Hook覆盖套件、规格、场景、步骤四个层级命名也很直观before_suite、before_spec、before_scenario、before_step以及对应的after版本。除了Hookgauge-python还提供了三种跨步骤传数据的Storescenario_store、spec_store、suite_store作用域分别是场景内、规格内、整个套件内。你可以在一个步骤里往里写数据在后面的步骤里读出来相当于测试内部的状态传递比到处用全局变量干净得多。4.4 并行执行和报告规模上来之后的必选项用例多到一定程度串行执行的时间就不能忍了。Gauge的并行执行非常简单gauge run --parallel specs/ # 自动选择并发数 gauge run -n 4 specs/ # 指定4个执行流执行报告是默认生成的跑完会自动在reports目录下产出HTML报告带时间戳、执行耗时和每一步的日志。这个报告可以直接发给业务团队看里面展示的是spec里的自然语言步骤和通过失败状态基本不需要额外解释。我之前是把报告上传到团队共享盘评审会上直接打开讲效果比贴一堆pytest输出好很多。5. 三个踩坑实录从现象到根因的完整排查过程最后分享三个我在真实项目中遇到的坑。这三个问题都不算罕见但报错信息都很有迷惑性如果不知道根因排查起来会很痛苦。5.1 步骤报未找到实现问题却出在不可见字符现象很简单gauge run跑一个场景核心提示某个步骤没有对应的实现但我明明在step_impl里写了。我当时的排查顺序是先确认注解和spec文本肉眼一致再确认函数真的被扫描到了在注解函数里临时加了个print发现加载阶段确实执行了最后把spec文本和注解文本同时复制进一个对比工具才看到有一处标点用了全角的冒号。在编辑器里全角和半角差别很细微但Gauge做文本匹配时是逐字符比对的这个差异直接导致匹配失败。这类问题没有捷径只能养成两个习惯一是spec文本尽量从注解复制二是偶尔遇到明明一致却匹配失败时果断用文本对比工具检查全角半角和不可见字符而不是盯着控制台发呆。5.2 升级之后运行器直接崩溃gRPC版本错配现象某个周五大伙儿升级了Gauge核心和插件紧接着CI上所有Python相关用例全部报错错误信息是类似协议层的报错堆栈里完全看不到业务代码。排查过程先看是不是代码改动导致的git log显示测试代码没变然后我在本地完整复现发现gauge run一执行运行器进程秒退。用gauge --version看到插件版本是新的用pip show看到gauge-python包还是旧版本两个版本之间存在协议差异。解决把gauge-python包升级到和插件匹配的版本问题立刻消失。后来我在项目里加了一个检查脚本把三个版本号输出一条记录每次有人改环境就能立刻发现版本漂移。Gauge的官方文档对版本兼容矩阵写得不算显眼建议大家升级前主动去查对应的兼容说明。5.3 并行执行后随机挂掉共享数据的隐性耦合现象更隐蔽单流执行一切正常一开并行就偶发断言失败而且每次失败的用例不一样。一开始怀疑是业务逻辑写错了排查了半天发现被测系统本身没有问题。真正的原因是两个用例用了同一个测试账号并行时A用admin登录把B顶下线B的断言就失败了。并行执行会把平时隐藏的耦合全部暴露出来共享账号、共享文件、共享端口、浏览器profile目录任何一个都可能成为偶发失败的源头。解决思路是让测试数据按执行流隔离比如把账号密码从环境变量或数据表里读出来每个流用独立的账号。这个教训让我养成了一个习惯凡是涉及账号、会话、文件输出这类有状态的外部资源一律假设会被并行执行碰到提前做隔离设计。5.4 定位问题的两个顺手工具如果你也遇到摸不着头脑的失败先用gauge run --verbose看详细执行日志它会把运行器和核心之间的通信过程打印出来很多加载类问题在这里能看到蛛丝马迹。其次是print调试依然有效步骤函数里的print输出会被运行器捕获并显示在执行结果里比什么高级调试器都直接。怀疑是模块导入问题时可以单独执行python -c import step_impl如果这一步都报错那问题就不在Gauge而在项目代码本身。我个人的体会是gauge-python的坑大多不在框架本身而在环境组合和团队使用习惯上。版本锁死、文本匹配靠复制、数据按执行流隔离这三条做到位这套方案跑起来会非常省心。后面如果你们团队也遇到有意思的踩坑经历欢迎交流。本文还有配套的精品资源点击获取
返回列表