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

作为测试人员,我们该如何看待AI

前几天看到一篇文章讨论从测试人员的角度去理解 AI 的,稍微翻译了一下。原文地址https://stevethedoc.wordpress.com/2023/06/18/how-should-we-view-ai-as-testers

上周三和周四,我有幸与我的两位同事 Sushmitha Sivan 和 Bhavana Akula 一起参加了伦敦的 AI 峰会。在那里,我们不仅听到了一些非常有趣的关于人工智能的演讲,还有机会为黑客马拉松的参与者们进行了大约一个小时的测试和质量工程的培训,教他们如何将这些知识应用到他们所面临的挑战中。

人工智能对我来说还是比较新的(我猜很多人也是如此),所以我们都处于学习的不同阶段,但这个学习过程非常有趣,因为它的范围和对社会的影响都是令人着迷的。

我不会告诉你如何测试人工智能,或者如何优化数据模型等等,这方面有其他地方可以去了解。这篇文章主要是关于我从参加的不同讲座中得到的一些更普遍的学习和想法,我脑海中浮现出了一些流行词和短语(以下是随机排列的):

  • 道德
  • 法规
  • 抵抗
  • 未知的恐惧
  • 失业
  • 激发人类创造力
  • 减轻繁琐工作
  • 数据模型偏见
  • 训练数据模型
  • 负责任地使用人工智能
  • 深度伪造

这让我思考起作为测试专业人员,我们应该如何应对人工智能。我故意使用这个词汇,因为它涵盖了测试中的每个角色。

我们大多数人在职业生涯中都测试过用户界面、后端数据库、API 等等,这些都可以生成特定的已知结果。我们有用户故事告诉我们预期的行为,以便我们可以相应地进行测试。那么对于这个新世界,我们该怎么看待呢?

我认为人工智能的目的是增强我们人类的工具,帮助我们做出决策。计算机的思维速度比我们快得多,因此它们可以帮助我们摆脱一些乏味的工作,我们可以利用我们的大脑去做更有创造力的事情。

当然,依赖人工智能可能会导致忽视固有的偏见,我们所做的决策可能基于有缺陷的数据。因此,我们需要谨慎对待我们对结果所放置的信任程度

  • 我们能相信 AI 工具使用的数据集吗?
  • 可能包含假数据吗?
  • 它是否包含偏见或者是偏差?
  • 我们是否相信输出涵盖了我们需要考虑的一切?
  • 结果是否受到了可能会影响的缺失参考文献的影响?

如果机器能够替我们进行批判性思考,并且我们毫无疑问地依赖它们,我们也可能失去自己的批判性思维能力。这种情况已经发生了,一个现实世界的例子是这样的——有多少 30 岁以下的人能够从书上读地图?如果他们的手机或汽车导航系统出故障了,有多少年轻一代能够应对并使用地图作为备用计划?他们在科技依赖下长大,而我们这些年纪稍大一点的人则能够两者兼顾。

作为测试人员,我们很容易陷入打开像 ChatGPT 这样的东西,并要求它根据我们提供的信息帮助生成测试计划或测试用例的陷阱中,然后将其用作完美答案。我们必须谨慎行事。是的,我们可能会得到一些可以开始的东西,而不是一张空白纸,但如果一直这样做,我们就会失去从头开始自己启动这个过程的能力。有时候,将事物进行思维导图有助于我们自己建立联系-我们必须训练自己从 AI 给我们的任何想法中开始中途进行,这可能行得通也可能不行。我并不是说这一定是件坏事,但我们需要小心,不要失去自己思考的能力。

有一些很棒的现实场景可以利用人工智能:

  • 寻找最佳的抵押贷款利率并将其整理在一张表格中
  • 为一个不熟悉的情况起草一封信件
  • 准备主持一场测验的研究工作
  • 准备一档广播节目(我可能会这样做)

随着我们在日常生活中开始使用人工智能,我们会越来越依赖它,它不会消失,而是需要受到监管(人类有一种令人羡慕的能力,可以将任何发明变成可以用于有害目的的东西!!),并且需要人们对其使用进行质疑。

作为测试人员,我的建议是以适度的怀疑态度接受人工智能。质疑所得到的结果,并进行独立验证。你无法获得结果所基于的数据,因此要谨慎行事,做好测试人员最擅长的事情——深入探究、调查和提问。

最后,保持你的批判性思维能力——在一个人们越来越依赖所听到的话作为真相的世界中,这一点将比以往任何时候都更加重要。那些能够退后一步,采取客观的方法的人将在未来脱颖而出。

欢迎来到崭新的世界。

谨慎的在测试过程中使用人工智能

作者的观点我是大部分赞同的,最近一直在关注 AI 领域,生成式 AI 爆发性的增长以及快速的落地应用让很多人都印象深刻。我甚至听到过一种观点:凡是现在可以被外包的工作将来都可能被 ai 所取代。

但事实果真如此吗?

首先我必须说明,我是非常看好 AI 在测试领域的应用的,从三体里借用一个词语,那我可能是降临派,历史的车轮滚滚向前,螳臂当车可能是不太明智的。尽管我看好未来,不过从现在这个阶段来说,把 AI 应用到测试工作中我们还有很多问题需要解决。

  • 首先值得借鉴的应用场景目前并不多。这篇推文写作的时间是 2023 年的年中,从目前的情况看将 AI 应用到测试中的案例并不多见.有一个非常有启发的例子是用 AI 自动进行网页上操作,不过离真正的测试活动还是有些差距的,预期结果和断言的缺失让这个想法目前还只是属于自动化的范畴。

微软的QA变迁史

看到一篇梳理微软的 QA 变迁史的文章,之前只听说过微软曾经直接干掉了所以的 qa 角色,不过也只是道听途说而已,这篇文章见微知著的以内部 qa 的视角描述了整个演进的过程,并对最终的结果进行了描述,还是非常有参考价值的。原文在这里:https://blog.pragmaticengineer.com/how-microsoft-does-qa。 下面是中文翻译。

SDET 角色

SDET(软件开发测试工程师)角色是微软在技术行业中首创的。他们是专注于编写自动化测试、构建和维护测试系统的软件工程师。SDET 与软件开发工程师(SDE)唯一的区别在于,SDET 通常不编写生产代码,而是编写测试代码,并与 SDE 在同一个团队中工作。

我无法追溯该角色的确切引入时间,但很可能是在 1990 年代。例如,这是微软 Exchange 团队的一位成员在 2004 年发表的一篇帖子,解释了在他们组织中成为 SDET 的含义:

“SDET 是一位在测试团队而非开发团队工作的开发人员。SDET 具备测试员的敏锐感,同时喜欢编写大量代码。

SDET 通过提供必要的工具和流程,使测试人员能够充分发挥他们的优势…在产品上市之前,尽可能多地测试产品并发现尽可能多的错误。

SDET 具备分析产品功能和架构的能力,从而设计和实现有助于测试的工具。

SDET 喜欢短期项目生命周期,在一年内设计和实现许多工具和测试框架,使用最新技术,并有充分的创新空间。

尽管产品质量是首要关注的问题,但 SDET 在产品生命周期末期不会像开发人员那样感到压力。通俗地说… SDET 很少会面临风险:)”

微软为 SDET 角色设定了正式的职业发展路径。同一篇帖子中写道:

“[SDET 职位]有很大的发展空间。如果你喜欢作为 SDET 所做的工作,你可以发展成为测试架构师。如果你想参与管理工作,那么你可以逐步晋升为 SDET 主管,然后成为测试经理。

如果你只想编码而不参与测试工作,你可以选择成为开发人员的道路。许多人选择了这条道路。如果你意识到你的心属于测试,那么你可以成为一名测试员。”

直到 2014 年左右,SDE 和 SDET 之间的比例在微软内部普遍为 2:1。在 2012 年我所在的 Skype for Xbox One 团队也是如此。以下是我们团队的人员构成,根据员工人数计算:

12 名 SDE(软件开发工程师) 6 名 SDET(软件开发测试工程师) 2 名 PM(产品经理) 1 名 EM(工程经理) 1 名 SDET 主管

更多的测试人员,更多的报酬

关于 ai 与测试的讨论现在逐渐流行起来,目前看来观点基本是积极和激进的,大多数人认为 ai 会重新塑造测试行业,不过基于 ai 的测试探索目前看来还是有限的,我稍微总结了一下,大概分为两类。

  • 利用大语言模型的推理能力进行驱动的自动化工具;这个之前的文章已经介绍过一些了,有兴趣的同学可以翻一下之前的存档;
  • 对融合了 ai 功能的软件产品进行测试。推荐大家研究一下这篇文章,里面的一些标准步骤还是让人备受启发的。https://blog.scottlogic.com/2023/11/14/testing-LLM-based-applications-strategy-and-challenges.html。这些测试大多是对prompt的安全,边界条件以及输出的稳定性进行测试。

就这个时间节点看来,ai 在测试领域上的应用其实不算太多。另外目前对于大模型本身的测试工作也基本是众测模式,模型提供商经过基本的 fine tuning 和测试之后发布模型或者提供 api 接口,通过使用者的反馈来持续的改进模型,基本上走的是强化学习的路子,对模型的测试不依赖于测试行为,而依赖于更多样性的标记数据,所以哪家大模型能跑出来其实就是看哪家的显卡多和数据多。

最近看到一篇非常积极拥抱 ai 的测试文章,里面的观点基本没有数据佐证,先不去讨论正确与否,不过文章确实传递出了一种很强烈的乐观信号,因为这篇文章认为 ai 会带来更多的测试岗位和更高的报酬。下面是对这篇文章的翻译,https://jarbon.medium.com/ai-more-testers-more-money-045e1a34741d。先提前说明,对这种观点我持谨慎的乐观态度,尽管我一直认为从事ai其实跟我们当年做黑盒测试差不多,不过下文的描述在短期看来还是比较难达成的,未来是什么样确实比较难以预测,所以不如积极投身其中去创造未来吧。

下面是原文的翻译:

AI 裂变正在迅速到来。AI 将在软件测试领域创造新的有和无。将 AI 引入软件测试将改变测试人员、供应商和工具的工作方式。但是,这种变化不会如大多数人所担心或梦想的那样。声称 AI 很快就会简单地取代人工测试人员的工作是错误的。希望 AI 无法足够聪明地完成大部分测试工作也是错误的。将会有更多的测试工作,并且它们很快将得到更高的报酬。在这个过渡中,有些人会失去工作,但这取决于他们自己。只有思想开放、乐观的测试人员才能在这个过渡中生存下来,并且他们将得到丰厚的工作保障和报酬。

AI 对测试工作的影响

在短期内,AI 不会减少测试工作的数量 - 对测试人员的需求将会增加。许多测试人员担心 AI 会消灭他们的工作 - 这对大多数人来说是不真实的。应用 AI 于工作的“AI 辅助”测试人员将更加高效。那些能够迅速做到这一点的人将获得最多的工作保障、进步和回报。

在 10 亿美元以上的测试领域中,最大的问题可能是如何衡量价值。工程团队知道他们需要测试,但很难量化,而事实是,大多数测试工作在今天没有 AI 的情况下几乎没有什么用处。当测试人员得到 AI 的辅助时,测试人员的速度、范围和价值将增长到明显的价值点。目前,大多数软件测试仅仅涵盖基本功能和一些边缘情况,成本高昂,并拖慢了工程团队的进展。

然而,AI 辅助测试将赋予这些人类测试人员“超能力”,他们的贡献将是压倒性的明显。正如测试领域的一位朋友上周所描述的那样 - 不久之后,测试人员将穿戴 AI-“钢铁侠”装备。企业将希望增加更多的 AI 测试人员,因为他们终于看到了明显的积极回报。这些 AI 辅助测试人员将足够快,以便在当前的开发周期内发挥作用,给人足够的信心进行发布,发现对业务有影响的问题,并揭示仍待测试的内容。对于 AI 辅助测试人员的需求将增加,因为他们将为企业增加明显的价值 - 就像开发人员增加功能和修复错误一样。

AI 还意味着开发人员正在创建更多的软件。AI 辅助工程师的加速是非常真实的,而且 AI 也意味着更多的人可以创建软件。所有这些新软件都需要由更多经过 AI 增强的测试人员进行测试。

在selenium中使用AjaxElementLocatorFactory来优化PO模式

之前看到的一篇对于 po 的改进的文章,非常有启发,简单翻译改写了一下,希望对大家有帮助。本文基于 java,至于其他语言是否有类似的实现,没有具体研究过。

原文地址: http://www.eliasnogueira.com/better-page-objects-strategy-using-ajaxelementlocatorfactory-with-selenium-and-java

PO 模式是 page object factory 设计模式的简称,主要是以页面为维度来聚合一些元素的定位,让代码有更好的维护性和重用性,具体细节可以看这里:https://www.selenium.dev/documentation/test_practices/encouraged/page_object_models。这里是官方文档,非常值得精读。

Page Factory

如果你已经对 po 很熟悉了,下面的内容可以放心跳过。

下面是最基本的 Page Factory 套路,本质上是按页面去封装元素定位和操作。

public class PageObjectExample {

    private final WebDriver driver;

    public PageObjectExample(WebDriver driver) {
        this.driver = driver;
    }

    public void login(String email, String password) {
        driver.findElement(By.id("email")).sendKeys(email);
        driver.findElement(By.id("password")).sendKeys(password);
        driver.findElement(By.name("next")).click();
    }
}

上面的代码只能说懂的都懂,不过这里有个问题,在 login 方法里,我们频繁使用driver.findElement方法,这会显得有一些的啰嗦,下面是改进版本,优雅了很多。

public class PageObjectExample {

    @FindBy(id = "email")
    private WebElement email;

    @FindBy(id = "password")
    private WebElement password;

    @FindBy(name = "next")
    private WebElement next;

    public PageObjectExample(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void login(String email, String password) {
        this.email.sendKeys(email);
        this.password.sendKeys(password);
        next.click();
    }
}

这里要注意的是在进行初始化的时候,需要调用PageFactory.initElements(driver, this);

测试人员必会的docker秘籍

Docker现在是许多 QA 工程师的常用工具。它用于生产环境和测试环境或两者兼而有之。docker 的文档制作精良,相对容易理解,但有时我们需要一些常用命令来解决问题。

在这里我列举一下对于测试同学来说比较值得去弄明白的 docker 秘籍。

**如何使用不同的参数运行已经启动的 docker 容器?**

可以用这个工具:https://github.com/lavie/runlike/

使用方法: runlike -p <container_name> ,这样就可以拿到该容器第一次启动时候用的具体命令了。

runlike -p testservice
docker run \
--name=testservice \
--user=test \
--env=KAFKA_HOST=172.17.0.1:9092 \
--env=PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin \
--env=LANG=en_US.UTF-8 \
--workdir=/home/testapp \
-p 8015:8080 \
--restart=always \
--log-driver=journald \
--runtime=runc \
--detach=true \
myrepo/testservice:master-1374

这时候我们就可以修改一些参数,比如端口号信息,生活变得容易了一些。

**如何在 docker 容器中运行本地 bash 脚本?**

cat local_script.sh | docker exec <container_name> /bin/bash

如何重启或移除所有的容器?

这个技巧非常管用,推荐牢记。

docker stop $(docker ps -a -q)
docker restart $(docker ps -a -q)

**如何清理旧的 docker 镜像、容器和卷?**

docker system prune -a

**如何过滤 docker ps 命令,以仅获取所需的信息,例如容器名称、状态和镜像?**

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"

**如何保存和恢复 docker 容器?**

docker commit -p <CONTAINER_ID> <YOUR_BACKUP_NAME>
docker save -o <CONTAINER_FILE>.tar <YOUR_BACKUP_NAME>
docker load -i <CONTAINER_FILE>.tar

如何将常用的 docker 命令简化成别名?

如果你是 docker 的重度用户的话,这个能力非常实用。

leetcode最有名的简单算法题:two sum

应该还是有很多同学在刷题找工作吧,如果大家刷 leetcode 的话,推荐的做法是从简单到难,这样一来 two sum 是大家绕不过去的最著名的简单算法题了,废话不多说,先看题目的描述。

给定一个整数数组  nums  和一个整数目标值  target,请你在该数组中找出  和为目标值 target  的那  两个  整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • 109 <= nums[i] <= 109
  • 109 <= target <= 109
  • 只会存在一个有效答案

**进阶:**你可以想出一个时间复杂度小于  O(n2)  的算法吗?