专注测试技术的课程订阅站点

强行为新项目写ui自动化用例是一种什么样的体验

最近接了一个新项目,配套有个 web 管理后台页面,尽管需求一直在迭代以及测试时间相对不宽裕,我还是决定写点自动化用例作为功能测试的补充和回归测试的输入,顺便玩一下 playwright,不在真是项目中使用一种技术其实是很难对这种技术产生深刻理解的。

项目介绍

管理后台是前后端分离的,前端用的 react 加上蚂蚁的前端组件库,后端是基于 golang 构建的微服务。其实这种项目更适合做接口测试,ui 自动化作为补充就好了。

技术选型

这点很清楚,之前 benchmark 过,playwright 比 cypress 性能要好,所以直接选 playwright,另外 playwright 的 python 版本完全安装之后自带了 pytest 和一系列断言,基本上开箱即用,非常方便。另外为什么不用 js 而用 python,主要是因为我用 python 写了一点接口用例,有些数据库操作的代码可以稍微复用一下,所以统一起见用 python+playwright

第一个难点:登录

管理后台接的是 google auth,由于我的账号开启了二次验证,需要收验证码,所以从 ui 上输入用户名和密码登录就走不通了。不过登录的原理基本相同,就是往 cookie 里写一些东西,后面所有的请求都自动带 cookie 到后端,后端通过之前写的那些东西就可以判断用户是谁,什么时候登录失效等。知道了原理后面就是随便试试了,我的代码大概是这样写的

def login(page):
    page.goto("url")
    page.evaluate(f'()=> document.cookie="{COOKIE}"')

其实就是先访问被测页面,然后自动跳到登录页面,这时候去用 js 设置 cookie,之后再访问一次被测页面就可以自动登录了。

cookie 的话可以从浏览器的开发者工具里直接拷贝出来,因为是测试环境,所以 cookie 的有效期很长,基本可以放心使用。

至于如何定期刷新 cookie 其实也不难搞,写个浏览器插件,每次打开被测页面的时候就把 cookie 发到一个自建后台服务,这个服务就是把 cookie 存到 redis 里,在测试用例里直接访问 redis 拿最新的 cookie 就好了。

定位有点麻烦

作为熟练工,定位对我来说应该不会是大问题,然而现在的前端组件层级嵌套厉害,html 的表意性不强,而且 id,name 等比较有标志性的属性也不是很多,踌躇良久之后我决定请前端同学在一些关键的组件上面加上 id 或者 name,尽管他们不是很愿意,但是我倚老卖老,还是让他们从了。

如何加速执行集成测试

今天我看到了一个有趣的 UI 集成测试加速方法,该方法与我想的底层优化、分布式运行或多线程运行方式不同。该作者重新编排了测试用例的执行顺序,删除了一些代码,并从执行流程上进行了优化。这确实很有趣。在本文中,我将简单介绍他的原文,希望对大家有所帮助。

我们将展示如何加速一个客户的构建过程,这样他们可以在相同的预算下多运行 40%的构建。

我必须承认,我是单元测试的超级粉丝。我早期的一些博客文章就是关于单元测试的。

单元测试是快速的、可预测的、而且隔离的。它们被很好地隔离在一个沙盒中,这就是它们的可预测性和快速性。

我们推出了一个版本,用户无法进入登录页面,但这是另一个故事了。我把它命名为“一个没有集成测试和几十个单元测试的项目”。

并不是说我完全停止写单元测试,而是我很少使用它们。大部分是用于可以安全地进行隔离测试的功能,例如一个接受各种输入并返回各种输出的函数。用集成测试来测试可能的值矩阵是不值得的。

想象一下,有一个日历组件,用户可以输入一个日期,从一个下拉日历中选择数据,然后点击一个按钮来获得一个建议的日期。所有的日期都可以是不同的格式,这取决于用户如何输入它们。是否值得为每种可能的日期格式进行集成测试?也许不值得!

然而,我们把输入的日期发送到一个负责解释许多不同格式的输入日期的实用函数,但它总是返回一个 Date 对象。为这个实用函数写一个单元测试将是一个很好的主意!对于整个应用来说,就不是那么回事了。

假设你正在建立一个问题跟踪器。你有一个集成测试,打开一个对话框,试图保存一个里程碑而不指定名称。这将导致一个错误。你的另一个测试试图创建一个里程碑,但现在指定了一个名称。这不会导致错误,并显示消息“新的里程碑已保存”。

beforeEach(async () => {
  await createNewProject();
});

it("cannot create milestone without a name", () => {
  clickNewMilestoneButton();
  newMilestoneDialog.clickSave();
  newMilestoneDialog.should("have.text", "Milestone name is required");
});

it("creates a milestone", () => {
  clickNewMilestoneButton();
  newMilestonDialog.getNameField().type("February Milestone");
  newMilestoneDialog.clickSave();
  newMilestoneDialog.should("have.text", "New milestone saved");
});

乍一看,上面的测试没有问题。然而,从零开始创建一个新项目涉及设置名称,填写一些起始/结束日期,键入描述,从下拉列表中选择项目所有者,为项目提供相同的标签,填写其他几个字段。我们的测试运行器(我现在使用 Cypress)必须单击所有这些字段,键入一些内容,等待一些建议出现,然后单击,再等待。

或者,将运行时间放在注释里,像这样想象:

beforeEach(async () => {
  // 运行10秒
  await createNewProject();
});

it("cannot create milestone without a name", () => {
  // 运行2秒
  clickNewMilestoneButton();
  newMilestoneDialog.clickSave();
  newMilestoneDialog.should("have.text", "Milestone name is required");
});

it("creates a milestone", () => {
  // 运行3秒
  clickNewMilestoneButton();
  newMilestonDialog.getNameField().type("February Milestone");
  newMilestoneDialog.clickSave();
  newMilestoneDialog.should("have.text", "New milestone saved");
});

整个测试套件运行 25 秒(2x10 + 2 +3),但我们感兴趣的事情只占了其中的 5 秒(2 + 3)。

放弃postman?一个月4k star?接口测试工具hoppscotch评测

天下苦 postman 久矣!

记得当初 potman 刚横空出世时,其形态只是一个浏览器扩展而已,尽管功能简单,不过却带来了另一个非常大的优势,那就是软件体积非常小,安装到浏览器上以后可以借助于浏览器同步的功能,实现各种跨平台支持,特别是对我我这种拥有 win/mac/iinux 的人来说,方便快捷是第一位的。

后来 postman 推出了独立的桌面版本,功能逐渐迭代,性能差的慢慢变态,现在劝退我的是两点:启动速度慢和我用不到的功能慢慢变多;当然除了这两点外还有个相当大的槽点是:postman 会想方设法让你登录,如果你不小心使用了同步功能的话,你的测试文件会公开分享到 postman 上供人品评,这是一个巨大的安全隐患。

D 轮融了 2.25 亿美金,postman 注定要在商业化的道路上越走越远,注定会增加很多我不需要的功能,各种同步,花式协作,满屏的效率提升,不厌其烦的提示我升级等等,对我来说其实需求很简单,只要可以让我朴素的调试接口就可以了。

于是各种 postman 的替代工具应运而生,比如 postwoman,insomnia 等等,这种工具的技术栈都差不多,都是用 js 开发的类似于原生客户端的跨平台工具,今天给大家带来的是一款很火的开源 postman 替代工具: hoppscotch,这个工具在 github 上目前有 40,000 的 star,3 月份新增 4000 的 star,应该是目前最火的测试工具了。

安装

hoppscotch 只需要安装一个浏览器扩展就可以了,支持 chrome 和 firefox。比 postman 动则上百兆的安装包来说,安装过程简单了不少。

安装好扩展之后访问https://hoppscotch.io/就可以使用了。

UI

hoppscotch 的界面跟 postman 差不多,会用 postman 的同学应该会感到比较亲切。

功能

功能上 hoppscotch 也跟 postman 不相上下

  • 支持 rest api 调试
  • 支持 GraphQL 语法
  • 支持 websocket 和 socket.io
  • 支持从 collection 生成文档,这个我不会用
  • 支持 collection 的创建及导出
  • 支持多种 Authorization 方式
  • 支持 pre-request script
  • 支持断言,跟 postman 的写法不能说很像,只能说是一摸一样
  • 完善的快捷键支持
  • 支持 pwa,轻量化的网页解决方案,让网页应用的体验跟 desktop 一样,再也不用忍受 postman 的龟速启动了
  • 支持 proxy,支持自建 proxy
  • 个性化定制:白天模式和暗夜模式,各种颜色主题,可以调整字体大小
  • 支持 cli,这个真是没想到,看了一眼是 go 写的,功能有限,不过可以在命令行运行 collection 了,不过似乎不支持 websocket
  • 完全开源,前端应该是 vue 写的,有开发能力的同学可以进行定制

部署

我们可以在远程服务器上部署个 hoppscotch 版本,然后远程进行访问。不过用 docker 部署的话似乎有点问题,就是浏览器插件无法识别的问题,于是就需要部署个 proxy 用来转发请求,这样就会出现本地 localhost 无法解析的问题,所以如果不是必须的话,用 pwa 的版本体验上就已经很好了。

跟AI一起结对编程,测试驱动开发

martin fowler的博客上新发了一篇关于 AI 和 TDD 的文章,先翻译一下,然后聊聊我的看法。

使用测试驱动开发(TDD)与 GitHub Copilot 编码助手

AI 编程助手如 GitHub Copilot 的出现意味着我们不再需要测试了吗?TDD 将过时吗?为了回答这个问题,我们来看一下 TDD 如何帮助软件开发的两点:提供良好的反馈,以及在解决问题时“分治法”。

TDD 提供良好的反馈 良好的反馈要快速和准确。在这两方面,没有什么能比一个编写良好的单元测试更好。不论是手动测试,文档,代码审查,甚至是生成式 AI,都不能取代。事实上,大型语言模型提供无关信息,甚至 hallucinate。当使用 AI 编程助手时,尤其需要 TDD。我们需要对自己编写的代码快速准确的反馈,也同样需要对 AI 编程助手编写的代码快速准确的反馈。

TDD 通过分治法解决问题 通过分治法解决问题意味着较小的问题可以比较大的问题更早解决。这实现了持续集成,基于主线的开发,最终实现持续交付。但是如果 AI 助手为我们编写了代码,我们是否真的还需要所有这些?

是的。大语言模型很少能在一次提示后就提供我们所需的确切功能。所以迭代开发还没有走到尽头。此外,大语言模型似乎在通过思路提示的增量方式解决问题时“激发了推理”(参见相关研究)。基于 LLM 的 AI 编程助手在分治法解决问题时表现最好,而 TDD 是我们在软件开发中所做的。

使用 GitHub Copilot 的 TDD 技巧

Thoughtworks 从年初开始就一直在使用带有 TDD 的 GitHub Copilot。我们的目标是实验、评估和发展一系列围绕使用该工具的有效实践。

0. 开始

从一个空白的测试文件开始并不意味着从一个空白的上下文开始。我们通常从一个带一些粗略笔记的用户故事开始。我们也会与配对伙伴讨论一个起点。

所有这些上下文都是 Copilot 在我们把它放入一个打开的文件之前(例如测试文件顶部)“看不到”的。Copilot 可以处理拼写错误、点式格式、糟糕的语法等等。但是它无法处理一个空白文件。

一些对我们有效的启动上下文示例:

  • ASCII 艺术画布
  • 验收标准
  • 引导假设,例如:
  • “不需要 GUI”
  • “使用面向对象编程”(而不是函数式编程) Copilot 使用打开的文件作为上下文,所以同时保持测试文件和实现文件打开(例如并排)大大提高了 Copilot 的代码补全能力。

1. 红色

我们首先编写一个描述性的测试示例名称。名称越描述性越好,Copilot 代码补全的表现也越好。

grpc简介

RPC

试想这样一种场景,一个复杂系统中的两个模块之前需要互相调用,一般的做法是什么?

可能这两个模块是跑在同一个进程上,那么通信起来其实是非常方便的,也有可能这两个模块分别是跑在不同的进程之上,那么就涉及到复杂一点的跨进程通信的技术了。但这些都是模块部署在同一机器下的情景,大家想象起来也会比较容易。

更加深入一些,如果两个模块跑在不同的机器之间,那么模块之前的调用如何实现呢?这就需要使用 RPC 技术了。

RPC(Remote Procedure Call)— 远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC 协议假定某些传输协议的存在,如 TCP 或 UDP,为通信程序之间携带信息数据。在 OSI 网络通信模型中,RPC 跨越了传输层和应用层。RPC 使得开发包括网络分布式多程序在内的应用程序更加容易。

RPC 采用客户端/服务器模式。请求程序就是一个客户端,而服务提供程序就是一个服务器。首先,客户端调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

简单来说 RPC 需要 server 端和 client 端,server 端定义一些函数,client 端通过网络请求去调用这些函数拿到返回值。server 端和 client 端跑在不同的机器上,结合微服务的概念就是 server 端就是一个独立的微服务,其他微服务需要通过启动 client 端来调用该微服务提供的服务。

gRPC

gRPC 一开始由 Google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。

在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。

组成

典型的 grpc 实现有两端组成,分别是

  • server
  • client

grpc%E7%AE%80%E4%BB%8B%2082e57cd2e8434314addbe47d6725a434/Untitled.png

gRPC 的特性

  • 由于 client 和 server 需要通过网络进行消息的传递,那么网络协议成了 grpc 里重要的一环。grpc 协议是 HTTP/2,这是一种优化过的 http 协议,实现了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。可以节省带宽、降低 TCP 链接次数、节省 CPU,帮助移动设备延长电池寿命等。
  • 服务端向外提供了一些可供调用的函数,这些函数的原型通过 ProtoBuf 协议来进行定义。ProtoBuf 是由 Google 开发的一种数据序列化协议(类似于 XML、JSON、hessian)。ProtoBuf 能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强。
  • 支持多种编程语言。比如支持 golang/java/c++/ruby/python/nodejs 等。

gRPC 的优点

  • 使用 protobuf 进行消息的序列化,压缩率高,性能好,毕竟压缩的越小在网络上传播的速度就相对会更快一点
  • 序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射,其实除了可读性差之外,pb 的使用方式跟 json 基本都差不多了
  • 支持向前兼容和向后兼容,升级比较简单
  • 支持多语言

典型的 gRPC 实现

典型的 gRPC 实现有 3 个部分,分别是

QA要像消防队一样

原文地址: https://medium.com/@dstekanov.tech/qa-team-as-a-fire-department-9b5abd470e44

翻译及总结如下。

作者是一名有十多年经验的 QA 工程师,作者曾经在不同的公司和项目中工作过,从小型的创业公司到大型的跨国公司,从传统的水瀑式方法到现代的敏捷方法。在这些年里,作者观察到了 QA 团队在软件开发过程中扮演着不同的角色和职责,有时候是成功的,有时候是失败的。作者想分享一下作者对 QA 团队的看法和建议,希望能对那些想要提高 QA 团队效率和价值的人有所帮助。

作者喜欢用消防队来比喻 QA 团队。消防队是一个重要的组织,它可以在紧急情况下保护人们和财产免受火灾的危害。消防队员需要具备以下几个特点:

  • 快速反应:消防队员需要能够在第一时间到达火灾现场,并迅速采取措施控制火势。
  • 高效协作:消防队员需要能够和其他消防队员以及其他救援人员密切合作,共同完成救援任务。
  • 专业技能:消防队员需要掌握各种消防设备和技术,以及如何应对不同类型和规模的火灾。
  • 持续学习:消防队员需要不断地更新自己的知识和技能,以适应不断变化的环境和需求。

类似地,QA 团队也是一个重要的组织,它可以在软件开发过程中保证产品的质量和性能。QA 工程师也需要具备以下几个特点:

  • 快速反馈:QA 工程师需要能够在第一时间发现并报告产品中存在的问题,并提供有效的解决方案。
  • 高效沟通:QA 工程师需要能够和开发工程师以及其他利益相关者密切沟通,共享信息和反馈。
  • 专业技能:QA 工程师需要掌握各种测试工具和技术,以及如何针对不同类型和规模的产品进行测试。
  • 持续学习:QA 工程师需要不断地更新自己的知识和技能,以适应不断变化的环境和需求。

基于这个比喻,作者想给出以下几点建议,来帮助 QA 团队更好地发挥自己的作用和价值

  • QA 团队应该和开发团队紧密合作,共享信息和反馈,而不是互相指责或隔离。这样可以提高沟通效率,减少误解和冲突,提升产品质量。作者举例说,他曾经在一个项目中,QA 团队和开发团队使用同一个工具来管理问题和需求,这样可以及时地交流和解决问题,避免了重复工作和延误。
  • QA 团队应该使用自动化测试工具,提高测试效率和覆盖率,而不是依赖人工测试或过时的方法。这样可以节省时间和资源,发现更多的问题,提高测试质量。作者举例说,他曾经在一个项目中,QA 团队使用了自动化测试框架来执行回归测试,这样可以在短时间内完成大量的测试用例,而不需要人工干预。
  • QA 团队应该关注用户的需求和体验,而不是只关注技术细节或功能。这样可以更好地满足用户的期望,增加用户的满意度,提高产品价值。作者举例说,他曾经在一个项目中,QA 团队使用了用户故事来定义测试场景,这样可以从用户的角度来验证产品的功能和性能,而不是只从技术的角度来检查。
  • QA 团队应该持续地学习和改进,跟上行业的发展和变化,而不是停滞不前或满足现状。这样可以提高自身的能力和知识,适应不同的环境和需求,保持竞争力和创新力。作者举例说,他曾经在一个项目中,QA 团队使用了敏捷方法来进行测试活动,这样可以灵活地调整测试计划和策略,根据实际情况来优化测试过程。

作者最后总结说,QA 团队是一个重要的角色,它可以帮助产品成功地上市和运行,但是它也需要不断地适应和创新,才能保持竞争力和价值。