Featured image of post Playwright新版本筛选功能

Playwright新版本筛选功能

Playwright 最新的1.5.1版本中增加的一个实用更新介绍


前言

在进行软件测试,比如针对一个电商网站,你是否遇到过这些问题?

  • 动态加载的商品列表:部分商品因缺货、促销结束或未登录状态被隐藏。
  • 悬浮显示的促销标签:仅当用户鼠标悬停时才会展示优惠信息。
  • 广告弹窗干扰:某些弹窗可能遮挡核心功能,但测试时需要确保主流程不受影响。

这些场景的共同点是:页面元素可能存在于DOM中,但用户实际不可见, 比如设置CSS属性(display: nonevisibility: hidden)。传统测试方法需要手动判断元素可见性,遍历或预先这对具体对象进行分支判断,比较复杂。


Playwright 最新版本提供了一个简化方法

在最新更新的 Playwright V1.5.1 版本更新中,针对locator.filter()方法新增了visible选项,可以极大简化这部分操作。(目前针对node.js有此更新,Python语言尚未支持

其核心作用是:
仅筛选页面上用户实际可见的元素,自动忽略因CSS(如display: none)或布局原因隐藏的元素。

技术原理
Playwright通过计算元素的布局边界、透明度、层叠上下文等属性,判断元素是否在视口内且对用户可见。这与真实用户视角完全一致,避免因操作隐藏元素导致测试失败。


场景实战:过滤可见商品

假设我们测试一个中文电商平台的**“限时秒杀”页面**,其HTML结构如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html>
<head>
    <title>限时秒杀</title>
</head>
<body>
    <div class="seckill-list">
        <!-- 可见商品 -->
        <div data-testid="product-item" class="product">
            <h3>【爆款】无线蓝牙耳机</h3>
            <p class="price">促销价: ¥199</p>
            <button>立即抢购</button>
        </div>
        <div data-testid="product-item" class="product">
            <h3>智能手环</h3>
            <p class="price">促销价: ¥299</p>
            <button>立即抢购</button>
        </div>
        <!-- 隐藏商品(已抢光或未开始) -->
        <div data-testid="product-item" class="product" style="display: none;">
            <h3>家用投影仪</h3>
            <p class="price">促销价: ¥899</p>
            <button>已售罄</button>
        </div>
        <div data-testid="product-item" class="product" style="opacity: 0;">
            <h3>空气炸锅</h3>
            <p class="price">促销价: ¥399</p>
            <button>未开始</button>
        </div>
    </div>
</body>
</html>

需求场景

用户访问“限时秒杀”页面时,仅展示可抢购的商品(前两项),隐藏已售罄或未开始的商品。我们需要验证:

  1. 页面中用户可见的商品数量是否正确。
  2. “立即抢购”按钮仅对可见商品生效。

新旧方案对比

旧方法:手动遍历+可见性检查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 旧方案示例
import { test, expect } from '@playwright/test';
test('验证可见商品数量', async ({ page }) => {
    await page.goto('https://mall.example.com/seckill');
    const allProducts = await page.getByTestId('product-item').all();
    let visibleCount = 0;
    for (const product of allProducts) {
        if (await product.isVisible()) {
            visibleCount++;
        }
    }
    expect(visibleCount).toBe(2); // 断言可见商品为2个
});

痛点

  • 需要手动遍历所有元素,代码冗余。
  • 若商品数量动态变化(如分页加载),维护成本高。

新方案:一行代码过滤可见元素

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 新方案示例
import { test, expect } from '@playwright/test';
test('验证可见商品数量', async ({ page }) => {
    await page.goto('https://mall.example.com/seckill');
    const visibleProducts = page.getByTestId('product-item').filter({ visible: true });
    // 断言可见商品数量为2
    await expect(visibleProducts).toHaveCount(2);
    // 断言所有可见商品均可点击“立即抢购”
    await expect(visibleProducts.getByText('立即抢购')).toHaveCount(2);
});

优势

  1. 代码简洁:无需循环,直接通过链式调用过滤。
  2. 实时匹配:自动响应页面动态变化(如AJAX加载新商品)。
  3. 精准断言:结合Playwright的软断言(Soft Assertions),可同时验证多个条件。

扩展应用:电商测试中的常见场景

场景1:验证悬浮显示的促销标签

某些商品的“限时折扣”标签仅在鼠标悬停时显示。通过visible: true可确保仅操作实际可见的元素:

1
2
3
4
5
// 鼠标悬停后,验证促销标签可见
const productCard = page.getByTestId('product-card').filter({ visible: true }).first();
await productCard.hover();
const discountTag = productCard.getByText('限时5折');
await expect(discountTag).toBeVisible();

场景2:过滤弹窗干扰

若页面存在广告弹窗,可通过visible: true跳过隐藏的弹窗元素:

1
2
3
4
5
// 关闭可见的弹窗(忽略已隐藏的)
const activePopup = page.getByTestId('popup').filter({ visible: true });
if (await activePopup.isVisible()) {
    await activePopup.getByText('关闭').click();
}

结语

通过这个 Playwright 更新的实用功能,可以较大简化我们在进行自动化测试时编写的复杂度,也可以看到,作为势头正劲的新一代web测试工具,Playwright的不断升级优化还是很贴合实际且社区活跃,值得重点关注!

秋草也推出了一个 基于Pytest+Playwright的自动化框架实战课程,有兴趣的同学可关注:

使用 Hugo 构建
主题 StackJimmy 设计