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

Selenium Manager可以用起来了

前几天随手写了几个 headless 的 selenium 爬虫脚本,运行的时候发现本地的 chromedriver 竟然不需要更新,一时间有点没反应过来,毕竟 selenium 有个痛点就是chrome 浏览器自动升级之后需要下载新的 chromedrier, 否则之前的脚本将会报错。当然了,之前也有一些规避的方式,比如

这些方法其实都挺好,都能解决核心问题,特别是 python 的 webdriver-manager,几行代码就可以保持 driver 永远自动更新,举个例子

# selenium 4
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))

这次不用更新 driver 是因为使用了官方推出的selenium manager,之前没留意,不过真到用的时候发现还是比较方便的。对我来说 selenium manager 最方便的就是初始化环境的功能,比如

  • 自动安装浏览器
  • 自动安装 driver
  • 支持多架构多系统
  • 可以配置代理,这点很重要
  • 自动管理浏览器和 driver,其实就是把浏览器和 driver 放在了系统 PATH 里

如果我有一个脚本需要在 windows 和 macos 的最新版本 chrome 上跑,那么环境初始化就非常容易了,只需要下面的命令

秒会selenium grid

今天在看 selenium grid 文档的时候,发现 selenium grid4 的设计还是不错的,想顺手体验一下,于是就发现了docker-selenium项目,可以快速的设置好 selenium grid 环境,非常简单方便。

然而后面准备用 python 去写个简单例子的时候,发现很难找到 python 代码的例子,好不容易找到 1 个却发现跑不起来,于是简单的看了下源码,找到了正确的打开方式,这里简单分享一下。

selenium grid 的使用场景

在我看来 grid 的使用场景有两个

  • 在不同的浏览器上并行跑用例,这比挨个在不同浏览器上跑要省不少时间
  • 启动多个节点在同一个浏览器上并行跑用例,同样也是节约了执行时间

快速安装好 selenium grid 环境

Selenium grid 有多种模式,比如 Standalone, Hub and Node,对于初次体验来说无脑用 Standalone 是不会有问题的。

传统的方式是使用 java 来运行 jar 包安装,不过 docker selenium 提供了更简单的方式,直接用 docker 跑镜像就好了。 比如下面的命令就启动了 1 个 firefox 的远程节点。

docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-firefox:4.11.0-20230801

这里暴露了 2 个端口

  • 4444: hub 的端口,直接访问可以看到所有节点的信息
  • 7900: vnc 的端口,访问 http://localhost:7900/?autoconnect=1&resize=scale&password=secret 就可以看到远程节点上的浏览器运行情况,非常方便了

连接远程节点进行测试

代码很简单,我的运行环境是

如何实现线程安全的内存缓存

这两天正好看到一个用 go 实现的线程安全的内存缓存,实现代码非常简洁高效,不卖弄不烧脑,非常值得初学者拿来学习。

项目地址

项目地址在https://github.com/muesli/cache2go,目前已经有 1.8k 的 star。

如何使用

package main

import (
	"github.com/muesli/cache2go"
	"fmt"
	"time"
)

// Keys & values in cache2go can be of arbitrary types, e.g. a struct.
type myStruct struct {
	text     string
	moreData []byte
}

func main() {
	// Accessing a new cache table for the first time will create it.
	cache :=

	// We will put a new item in the cache. It will expire after
	// not being accessed via Value(key) for more than 5 seconds.
	val := myStruct{"This is a test!", []byte{}}
	cache.Add("someKey", 5*time.Second, &val)

	// Let's retrieve the item from the cache.
	res, err := cache.Value("someKey")
	if err == nil {
		fmt.Println("Found value in cache:", res.Data().(*myStruct).text)
	} else {
		fmt.Println("Error retrieving value from cache:", err)
	}

	// Wait for the item to expire in cache.
	time.Sleep(6 * time.Second)
	res, err = cache.Value("someKey")
	if err != nil {
		fmt.Println("Item is not cached (anymore).")
	}

	// Add another item that never expires.
	cache.Add("someKey", 0, &val)

	// cache2go supports a few handy callbacks and loading mechanisms.
	cache.SetAboutToDeleteItemCallback(func(e *cache2go.CacheItem) {
		fmt.Println("Deleting:", e.Key(), e.Data().(*myStruct).text, e.CreatedOn())
	})

	// Remove the item from the cache.
	cache.Delete("someKey")

	// And wipe the entire cache table.
	cache.Flush()
}

简单看一下核心 api

Slenium已死?

selenium 已死?其他的框架例如 playwright, cypress 当立?这是去年一个广泛讨论的话题。对于我来说这个观点很明显是偏颇的,因为

  • selenium 本身已经成为了 w3c 规范的一部分,现在市面上所有的浏览器都遵循这个规范
  • selenium 本来就不是一个纯测试工具,它是为自动化而生,除了浏览器测试之外,selenium 还有很广泛的用途,而 playwright/cypress 则更专精于测试领域
  • selenium 的 api 相当稳定,对于一些需要长期维护的项目来说这是非常有诱惑力的,而我去年用 playwright 做了一个项目,今年由于 api 升级,去年的代码基本上已经完全不可用了

所以对我来说,selenium 尽管已经徐娘半老,吸引力大不如前,但在某些场景下,selenium 仍然会是我的首选工具,就像是 vb/php 一样,尽管大家都已经看衰很多年了,但这些技术一直没有落幕退场。

selenium 官方可能也察觉到了这些广泛的讨论,昨天他们官网 blog 发了一篇文章,直接讨论 selenium 与其他工具的情感纠葛,上下文可能是不少人发博文比较 selenium 与其他工具,然后标题党一下,使得大家产生错觉:selenium 真的已经快死翘翘了。这篇内容专业简洁,适合给大家消除误解,原文地址:https://www.selenium.dev/blog/2024/selenium-vs-blog-posts/。

下面是全文翻译。

这篇博文讨论了那些比较 Selenium、Cypress 和 Playwright 的标题党文章。这些文章没有意义,也没有帮助。

作者:David Burns (@AutomatedTester) | 2024 年 1 月 9 日星期二

在博文中,关于自动化测试的标题党文章最容易的方式就是将 Selenium 与其他工具进行比较,并配以一个吸引人的标题,尤其是当它贬低现有工具时。

不幸的是,这可能会使人们对这些产品中的哪些功能可用产生困惑,尤其是当我们进行同类的过度类比时。

Selenium 一直是一个很好的浏览器自动化工具。对于该项目来说,幸运的是,它已经成为测试 Web 应用程序的首选工具近 20 年。该项目专注于构建越来越复杂的浏览器自动化的难点。项目的重点一直是稳定的 API 和可扩展性,以保证 Selenium 的运行。它没有关注人们如何进行测试,因为有非常好的测试框架可用,并且为 5 种不同的编程语言进行测试是一项非常重要的工程工作。

然而,这些博文中经常出现一些误解。

与 Playwright 和 Cypress 相比,设置浏览器和驱动程序太困难

过去确实如此,因为您需要下载驱动程序。对于 GeckoDriver 和 SafariDriver 来说,这并不太糟糕,因为它们可以优雅地处理浏览器升级。另一方面,对于基于 Chromium 的浏览器,您需要为每个新版本更新驱动程序。

AI大语言模型在自动化用例生成中的探索

最近读到这篇文章,原文在是https://drlee.io/implementing-ai-in-software-testing-creating-a-text-generation-model-for-test-automation-7294b26f93c4,里面涉及到一些基于ai进行自动化测试的探索,原文是这么说的:

将人工智能 (AI) 纳入软件测试可谓是游戏规则的改变者,能够显著提升效率和有效性。本文利用 OpenAI 的文本生成模型——尤其是 GPT-3.5-turbo 和 GPT-4-turbo-preview——在 Google Colab 中构建了一个文本生成模型,重点关注测试自动化用例。

看了一下,里面列举了 3 个测试用例。

The system shall allow users to securely login with a username and password.

这是用户登录的用例。

Ensure that the shopping cart allows users to add items, remove items, and proceed to checkout.

这是购物车的用例。

The weather API should return a JSON response with fields for temperature, humidity, and precipitation forecast for the next 5 days.

单元测试的最佳实践

看到一篇关于单元测试最佳实践的文章,简单翻译一下,很多都说到了点子上,不能赞同更多。

单元测试是对软件应用程序中各个单元或组件进行的软件测试。单元测试旨在验证每个软件单元的执行是否符合设计预期。单元测试可以确保代码质量,提高可维护性,方便重构,并提高开发速度。

当谈到最佳实践时,这里有一些应该遵循的:

  1. 为每个缺陷编写新测试:当你遇到一个缺陷时,编写一个暴露该缺陷的测试。这也称为回归测试。

  2. 保持测试的小而聚焦:一个单元测试应该限制在一个独立的函数或方法中。这使得当测试失败时更容易识别和修复问题。

  3. 隔离你的测试:确保每个测试都是相互独立的。这允许你单独运行每个测试,并以任意顺序运行。(划重点了)

  4. 按测试类型组织测试:你可以根据它们测试的对象类型或测试类型来组织测试。这使得查找和运行相关测试更容易。

  5. 每次测试一条代码路径:每个测试应该验证方法中的一条明确的代码路径。这使得理解被测试的内容以及测试可能失败的原因更容易。

  6. 避免在测试中加入逻辑:当你在测试中加入逻辑时,你有引入测试缺陷的风险。保持测试的简单。(重点)

  7. 避免在被测试的类中使用静态方法:静态方法不能在子类中重写,这使得它们难以测试。避免在你要测试的类中使用静态方法。

  8. 避免测试实现细节:你的测试应该关注代码的行为,而不是它的实现。如果测试实现细节,当你的代码行为保持不变时,测试仍可能中断。

  9. 首先为对应用影响最大的方法编写测试:将测试工作集中在对应用影响最大的方法上。这通常包括包含复杂逻辑或与外部资源交互的方法。

  10. 使用 AAA 模式:准备测试数据和测试环境(Arrange)、执行(Act)、断言(Assert)是编写单元测试的典型模式。单元测试方法的安排部分初始化对象和传递给被测试方法的数据值。执行部分调用带有 Arrange 参数的被测试方法。断言部分验证被测试方法的行为符合预期。(划重点)

原文如下:

𝗨𝗻𝗶𝘁 𝗧𝗲𝘀𝘁𝗶𝗻𝗴 𝗕𝗲𝘀𝘁 𝗣𝗿𝗮𝗰𝘁𝗶𝗰𝗲𝘀

Unit tests are software testing where individual units or components of a software application are tested. Unit testing aims to validate that each software unit performs as designed. Unit tests ensure code quality, and ease of maintenance, facilitates refactoring, and increase development speed.

When we talk about best practices, here is a list of that one should follow: