AI人工智能与软件测试

gemini在自动化测试中的潜力

昨天 google 发布了全新的 ai 模型 gemini,在视频里 google 演示了 gemini 近乎神奇的实时反馈能力,比如测试人员画一只鸭子,ai 可以立即识别,以及后面的一些互动小游戏中,gemini 展示出了出人意料的精准度和推理能力,这是令我印象最为深刻的多模态模型的实时演示了。

珠玉在前,gpt4 的文本类型的推理能力已经到达了一个相对可用的状态,基于该能力,我们也看到了一些比较有意思的自动化类型的项目,比如通过简化 html 输入大语言模型,让大语言模型去推断用户想要进行的操作,最终调用浏览器 api 进行自动化操作的项目,以及利用 llm 的解释器能力,一步一步推理并进行浏览器操作的项目,这些项目都非常有创意,也有一定的实用性,但是缺乏完善的多模态支持总让人觉得想象空间可能没有变得非常广阔。gemini 的出现,强大的推理能力,代码生成能力以及多模态能力的结合,也许会为自动化测试领域带来翻天覆地的变化。

UI 自动化

这是难度最高的自动化测试类型,比如浏览器和 app 的自动化,尽管概念出现的非常早,而且也发展了相当长的一段时间,但是 ui 自动化的普及度却相对来说不算太高,在资源和时间有限的情况下,ui 自动化测试往往是被大家优先降本增效的不二选择。

类型 gemini 的大语言模型的出现,可能会给 ui 自动化带来革命性的变化。今后,我们可以直接向 ai 输入一些描述相对明确的测试用例,当然,是用自然语言编写的,ai 可以推断出我们的测试意图,还原测试步骤,最终将测试步骤转化成测试代码,自动运行,通过运行中提供的截图和代码报错信息自动分析结果,自动迭代和修正代码错误,直到输出最终代码,基本上 ui 自动化是可以完美闭环的。

也就是说也许不久之后我们只需要写好手工测试用例就可以完成相对完美的自动化测试工作了,以后的测试人员可能不再需要每个用例都去执行一遍,执行的工作应该可以被 ai 和机器替代绝大部分。

顺便再考虑一下测试用例,如果 ai 的推断能力足够强的话,ai 应该可以写出大部分的测试用例,这时候测试人员只需要补充一些极端场景的用例就可以了。

那测试用例是从哪里来呢?可能是从产品文档里分析出来的,同样,如果模型精通多模态和推断的话,那么产品文档和产品设计图也是可以用 ai 去生成一大部分的,人工只要负责查缺补漏和提出修改意见就好了。同理,代码的话 ai 也能写个大部分,也许今后我们的工作方式会发生巨大的转变,从单纯的跟人合作变成跟人和 ai 一起协作,通用知识和能力将变得廉价,垂类的信息和领域知识可能会越来越值钱。

接口自动化

接口自动化可能不太需要多模态,基于模型的推理和生成能力,如果模型支持海量的上下文输入的话,那么我们是完全可以为接口自动化的用例定义规则,并教会模型如何应用这些规则生成测试用例。

举个例子,如果我们 curd 的接口遵循 restful 规则的话,ai 是完全有能力生成 restful 接口的测试用例的,毕竟 restful 的规则比较清晰,而且对于具体资源来说接口和用例的数量都是可以枚举的。

因此对于一些相对简单的接口,用 ai 去编写用例从直觉上来说是可行的,不过对于复杂接口,比如一些接口有很繁杂的前置依赖和操作步骤,ai 自动根据接口文档的话可能不太好去推断各种具体场景,这种情况下我们可能需要一种接近自然语言的简化版中间语言,这种语言描述一些接口的输入输出以及构造复杂的接口测试场景,ai 根据这种 DSL 去生成代码的话可能效率和准确性都要更高一点。

测试并不能改进产品质量

今天看到了有人给出了这样的观点,那就是测试并不能改进产品质量,觉得挺有意思的,所以把作者的原文翻译一下,希望对大家有所裨益。

在世界上有一种天经地义的看法,那就是在软件开发过程的早期预防问题会比在测试后期发现问题带来更高质量的产品,但那不是真的。

这是不真实的,但不是因为大多数人可能首先想到的原因。问题不在于尽早解决问题是个坏主意。这通常是一个非常好的主意。

问题是,测试自身不会导致更高质量的产品,在所有。问题预防和测试是不同的追求。测试不能预防问题,测试不能改进产品。

对我而已——一名教师和熟练测试的倡导者——这可能看起来很疯狂,但这是真的。称体重不会让你减肥。验血不会让你更健康。学校的标准化考试不会让孩子更聪明,当然也不会提高教育质量。

测试可以做的是通过质疑产品以对其进行评估来提高我们对可能摆在我们面前的事物的理解和意识。测试——通过体验、探索和试验了解产品来评估产品的过程——帮助我们意识到可能需要解决的问题。

在日常生活中,浴室秤上的某个特定读数可能会促使我们更加谨慎地进食,或者进行更多的锻炼。验血可能会促使医生开抗疟疾药物。这些标准化的学校考试可能会建议改变课程、教育资金或教师培训。但在有人采取行动之前,测试只会提高对现状的认识,而不是情况本身。

在软件开发中,除非有人解决测试帮助我们发现的问题,否则改进不会发生。当然,如果问题没有被发现,改进的可能性就会大大降低——这就是测试如此重要的原因。测试帮助我们了解我们拥有的产品,因此我们可以判断是否是我们想要的产品。在需要改进的地方,测试揭示了改进的必要性。

有些人认为测试要求我们操作产品,这是软件开发流程的一部分。确实这是是一种非常重要的测试,但也只是产品测试的一种方式而已。

将产品更广泛地理解为某人生产的东西会很有帮助。这意味着我们可以有单元,模块,原型等多种手段的测试。

尽管我们通常将其称为审查,但我们确实可以在产品开发之前就进行全方位的思考,在这种情况下,产品其实就是之前所有的讨论,设计和思考的产出物,测试其实在产品的研发的初期就开始了。

测试的结果是通过这些活动进行的评估和学习。这种学习可以应用于产品——但它是响应测试而发生的事情,而不是测试本身,这是可以改进产品。

正如测试不能改进产品一样,测试也不能防止问题。作为测试人员,我们有一个持久的信念,即我们被要求测试的任何东西都已经存在问题。也就是说,产品中的问题在我们遇到之前就已经存在。

那么,如果测试不能预防问题,那又有什么用呢?测试可以帮助我们意识到存在的问题,然后人们可以进行更改以防止这些问题进一步发展。

在开发早期尝试预防问题是一个好主意。如果尝试能够成功,我们就更有可能开发出高质量的产品。尽管如此,即使是高度规范的开发过程也可能会出现问题。至少有两种方法可以确定是否发生了这种情况。

第一种方法是全程测试产品。通过与一系列客户互动并了解他们所做的事情,确定我们开发的东西就是客户想要的。通过检查和讨论,测试那些最初模糊然后却越来越清晰的设计。

另一种方式是在代码开发的初级就做单元测试,然后在后续的构建步骤里进行集成测试,code review,静态代码扫描和自动化测试,从而找出组件自身的问题或者是配置的问题。这些形式的测试通常不是很深入——这是一件好事,因为深度测试可能需要时间、精力和准备,这可能会对开发人员造成更多负担。

在开发人员测试的同时,测试人员专注于并执行深度测试。深度测试的目标是测试少见的、隐藏的、微妙的、偶尔发生的、紧急的错误,这些错误可以通过手工测试或者探索性测试来发现。

如果您的问题预防和问题缓解策略是成功的,并且你的代码和产品是可测试的,那你不太可能在测试后期遇到一些显而易见的低级问题。如果您不需要测试和报告这些问题,那么后续的深度测试会相对更快、更容易。

如果您的问题预防和问题缓解策略不成功,全面和深入测试是找出问题的一种方法。您发现的问题可以解决;可以改进产品,并且可以在产品交付之前防止业务和客户出现问题。

当人们面临损失、伤害、不良情绪或价值降低的风险时,最好在为时已晚之前意识到问题,这就是测试的终极意义之所在。

测试本身既不能防止问题也不能改进产品。但是测试确实可以预测需要预防的问题,并且测试可以照亮产品需要改进的地方。

因为全文大部分是机翻,所以行文肯定有不流畅的地方,另外加上作者本身的笔法比较曲折,有一些点机器翻译可能难以驾驭,因此全文可能看起来观点比较分散,没有强一致性,不过大家可以简单的意会,忽略那些遣词造句里的机器感。

总而言之作者的观点其实并不离经叛道,而且还是有一定的道理的,比如癌症筛查并不能治疗癌症,不过如果你尽可能早的可以通过筛查确定自身的风险,提前治疗和预防,那么癌症很有可能将不会发生。测试也是如此,测的再多开发和产品不去修改,那么产品本身的质量也不会得到改进,但是如果我们频繁的提前的进行测试,那么我们就可以尽早的暴露问题,我们的开发和产品也就会有足够的时间去进行修复工作。这也是为什么我们总强调 bug 生命周期的原因,测试并不只是简单的提 bug,而是要尽早提 bug,并保证 bug 得到及时修复并得到验证。

原文地址:Testing Doesn’t Improve the Product (linkedin.com)

使用重试模式来提升自动化测试的稳定性

看到一篇非常好的关于在自动化测试中引入重试模式的文章,https://www.thegreenreport.blog/articles/enhancing-automation-reliability-with-retry-patterns/enhancing-automation-reliability-with-retry-patterns.html 忍不住跟大家分享一下。

自动化测试,特别是 ui 自动化的稳定性提升是非常困难的,出错了就重试这个简单的策略可以帮助我们处理一些难以预料的异常情景,从而提升测试的整体稳定性。

这篇文章的作者就分享了几种重试的设计模式,通俗易懂而且相当实用。

动态重试

async function dynamicRetry(actions, maxRetries) {
  let retryCount = 0;

  async function retryAction() {
    try {
      return await actions();
    } catch (error) {
      if (retryCount < maxRetries) {
        retryCount++;
        return retryAction();
      } else {
        throw error;
      }
    }
  }
  return await retryAction();
}

it("Testing the dynamic retry pattern", async () => {
  await demoPage.navigateToDemoPageTextBoxes();
  await browser.pause(1000);
  await dynamicRetry(async () => {
    await demoPage.fillFullName("John Doe");
    await demoPage.fillEmail("test@gmail.com");
    await demoPage.fillCurrentAddress("test address");
    await demoPage.clickFakeButton();
  }, 3);
});

该模式的核心是设置一个最大的重试次数,每次重试过后次数加一,直到达到阈值。

轮询重试

另一种常见的重试模式是使用超时和轮询。这种方法会重复检查一组操作是否成功完成或者是否达到了超时时间。

async function pollRetry(actions, timeout, pollInterval) {
  const startTime = Date.now();
  let lastError;

  while (Date.now() - startTime < timeout) {
    try {
      await actions();
      return;
    } catch (error) {
      lastError = error;
      await sleep(pollInterval);
    }
  }

  throw lastError;
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

it("Testing the poll retry pattern", async () => {
  await demoPage.navigateToDemoPageTextBoxes();
  await browser.pause(1000);
  await pollRetry(
    async () => {
      await demoPage.fillFullName("John Doe");
      await demoPage.fillEmail("test@gmail.com");
      await demoPage.fillCurrentAddress("test address");
      await demoPage.clickFakeButton();
    },
    20000,
    5000
  );
});

这个模式的核心是设置一个总的超时时间,如果在这个时间段内发生了异常,那么就每隔一段时间重试一下。

什么是向量数据库

对于向量数据库有疑问吗?以下是对这个数据库的简要解释。

什么是向量?

向量是一组数字的数组,表示点在空间中沿多个维度的位置。例如,向量{12, 13, 19, 8, 9}表示一个点在 5 个维度上的位置。向量可以几何地表示数据,使得数据点之间可以进行数学比较。

向量与嵌入有什么关系?

在机器学习中,嵌入是表示数据点(如单词、句子、图像等)的向量。嵌入将数据的语义含义编码为向量形式。它们由经过训练的神经网络生成,这些网络将数据点映射到有效的向量表示。这些嵌入将相关概念放置在向量空间中靠近的位置。

向量数据库如何工作?

向量数据库存储了各种数据点(如文档、图像、产品等)的嵌入,并将这些嵌入映射回其原始数据。数据库可以基于向量的相似性进行快速的相似性搜索。查询嵌入可以与存储的嵌入进行比较,最相似的向量可以几乎即时地被检索出来。这为语义搜索、推荐和其他人工智能应用提供了支持。

向量数据库在人工智能中的应用是什么?

向量数据库具有几个关键的人工智能应用:

  • 语义搜索 - 基于含义而不仅仅是关键词来检索信息
  • 推荐 - 提供与用户兴趣最相关的内容
  • 大型语言模型 - 理解上下文中的单词,用于生成和摘要
  • 异常检测 - 识别与正常情况相比的异常数据点
  • 图像分类 - 基于视觉属性对图像进行分类

通过促进快速的相似性比较,向量数据库使得机器学习模型能够在数据之间建立联系。这支持了使用原始数据无法实现的高级人工智能功能。向量空间充当算法构建理解的一种"记忆"。

移动测试指南

Guide to Mobile Testing

移动应用已经风靡全球,在移动互联网如此普及的今天,移动测试的重要性不言而喻。个人认为移动应用现在是大部分互联网公司的主要业态,在竞争激烈的现时,移动应用的质量可能会影响某个产品的成败与存亡,在去测试化思潮如此普遍的今天,移动端应用应该是最不可能砍掉测试人员的。因为

  • 移动应用的质量是第一大事
  • 竞争越激烈,好的质量越重要
  • 测试移动应用的效率目前还是偏低,用高薪的开发人员去兼任测试职能有点得不偿失
  • 移动端更新成本相对较高,测试充分再发出去才能尽可能地规避更新应用进行 bugfix 的风险

诚然,有些公司在推进去测试化,但那些公司可能是

  • 所在行业垄断性质明显,没有其他公司可以进行正面竞争,比如微软
  • 公司和用户对线上问题忍耐度相对较高,应用形态相对单纯,试错成本相对较低,比如之前的头条
  • 行业已过高速增长期但存量竞争激烈,产品基本处于维护阶段,不需要投入太多的开发和测试资源,比如腾讯的某些产品

从这里开始就是翻译了,原文地址在:https://medium.com/@iamfaisalkhatri/guide-to-mobile-testing-d0dd2d9b59f1

所以大部分情况下,移动端的测试以及质量提升是需要专职测试人员进行负责和统筹的,所以不必焦虑。相反,了解一些基本的移动端测试知识是一件较为必要的事情。

质量是关键

我们需要检查所有内容以及所有可能的排列和组合,以免出现任何 bug。由于移动设备也存储了最终用户的个人数据,因此有必要对安全性和数据完整性进行检查。

测试应用程序的性能同样重要,因为如今人们对应用程序的速度更感兴趣。如果功能能用,但应用响应时间过长,可能无法吸引用户。因此,应用程序的性能测试也是需要考虑的重要因素。

谈到测试移动应用程序,我认为我们应该首先弄清楚测试策略,因为它可以帮助我们分解测试阶段并进行高质量的测试,并帮助我们避免漏测一些重要内容。

定义测试策略

首先我们需要弄清楚移动应用的类型

  • 原生应用:离线可以直接用安装包进行安装,一般情况下可以在应用商店下载
  • 移动 web 应用:比如 h5 应用,基本是用 html+css+js 进行开发的,可能长得跟原生应用很像,但基本上不是一回事
  • 混合应用:既有原生也有移动 web 的应用,一般情况下对开发人员比较友好,毕竟 web 应用比原生应用开发要容易一点点

我们以混合应用为例在说明一下如何定义我们的测试策略,在进入细节之前,我们先来了解一下测试类型的相关知识。

测试类型

理想情况下,虑到混合应用程序,我认为应该考虑以下测试类型

  1. 功能测试。
  2. 性能测试
  3. 安全测试
  4. 可用性测试
  5. UI/UX 测试

%E7%A7%BB%E5%8A%A8%E6%B5%8B%E8%AF%95%E6%8C%87%E5%8D%97%2031ddadb1681b4287803ef98d6ca78960/Untitled.png

何时以及如何开始测试

由于我们处于当今软件世界虔诚地遵循敏捷的时代,因此最好尽早开始测试。

测试应该在软件开发生命周期的每个阶段进行,而不仅仅是在功能完全开发时进行。

话虽如此,请始终确保开发人员正在编写单元测试。还应涵盖集成和服务层测试。只写测试没有帮助,代码覆盖率报告应该显示单元测试覆盖率至少大于 80%,如果有可能的话,可以逐渐增加到 100%。有一条流水线可以帮助我们轻松监控生命周期并在每个阶段采取纠正措施,这很好。因此,除非构建是绿色的,否则继续进行测试并尽快进行所需的修复是不好的。

测试计划

有一个测试计划是很好的,因为它会更容易检查所有的测试活动,所以我们不会遗漏任何东西,顺利地执行测试并提供高质量的输出。

第一个也是最重要的情况是用户是否能够使用 PlayStore/App Store 成功安装应用程序。

Selenium Manager使用指南

Selenium 社区最近发布了 Selenium Manager 工具,主要是解决每隔一段时间就要重新去下载 driver 的痛点。当然了,这也是我痛点。因为 chrome 浏览器会自动更新的关系,之前我都是关掉自动更新从而回避去下载新 driver 的问题,不过因为用户的版本大多都是较新的,所以测试浏览器每隔一段时间还是要更新一下才比较好。我自己试用了一下,感觉还是很不错的,非常有意思的一个点是 sm 竟然是 rust 开发的,在我的印象里这种对性能和稳定性要求不是特别高的命令行用 go 开发和维护的话效率可能会更高一点。下面是官方 blog 的翻译以及我自己的一点点体验。

大多数人使用 Selenium 的第一次经验都会出现这样的错误消息:

java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see https://chromedriver.chromium.org/. The latest version can be downloaded from https://chromedriver.chromium.org/downloads

然后他们不得不在网上搜索有关如何处理他们下载的驱动程序的说明。

Selenium:现在已经内置了驱动程序!

Selenium 项目希望改善用户体验,其中一项首要任务是帮助所有用户简化他们设置环境的方式。多年来,配置浏览器驱动程序一直是用户需要执行的任务,以便运行 Selenium。

设置一次浏览器驱动程序并不那么复杂,但随着浏览器发布周期缩短,现在每 4-6 周就有一个新的 Chrome/Firefox/Edge 版本,使得保持浏览器驱动程序与浏览器版本同步的任务变得不那么容易了。

Selenium Manager 是一个新的工具,可帮助轻松获得运行 Selenium 所需的工作环境。如果 Chrome、Firefox 或 Edge 不在 PATH 中,Selenium Manager Beta 1 将配置它们的浏览器驱动程序。