storycap-testrun 具有类似于 storycap 内部的 Stories 稳定性检查功能,可以准确地截取 Stories 的屏幕截图 :camera
为什么选择 storycap-testrun?
使用 @storybook/test-runner
进行视觉回归测试时,在截取屏幕截图之前使用 waitForPageReady
进行等待。这仅支持最低限度的稳定性检查。因此,在实际用例中,需要设计更准确的稳定性检查方法。
storycap 通过使用 CDP 监控 Stories 在浏览器中渲染时的各种指标来实现稳定拍照。storycap-testrun 遵循 storycap 的策略,执行准确检查渲染内容稳定性的屏幕截图捕获。此外,它还提供了一种机制,通过验证多个捕获的屏幕截图图像的哈希值是否相同来检查渲染内容的稳定性。
此外,它还提供了用于避免不稳定测试的启发式工具,例如 Masking 和 Removal,这些可以在每个 Story 的 Parameters 中指定。
特性
- 对渲染内容进行高稳定性检查
- 精确等待 Play Function
- 使用 Hooks 在截图前后进行自定义
- 遮罩不稳定元素
- 移除不稳定元素
- 跳过不稳定元素
局限性
- 无法捕获多个视口
- 这是
@storybook/test-runner
的一个局限性。可以根据需要通过在多个视口中运行测试来解决。
- 这是
- 不支持
:hover
、:focus
、点击等变体状态。- 虽然这是 storycap 支持的一个方便的功能,但为了避免影响在
postVisit
中执行的其他进程,此处不支持此功能。
- 虽然这是 storycap 支持的一个方便的功能,但为了避免影响在
要求
- Node.js >= 18
@storybook/test-runner
>= 0.x
安装
通过 npm 安装
$ npm install --save-dev storycap-testrun
入门
请事先设置好 @storybook/test-runner
。
通过在 postVisit
中调用 screenshot
函数,您可以立即开始使用它。
// .storybook/test-runner.ts
import type { TestRunnerConfig } from '@storybook/test-runner';
import { screenshot } from 'storycap-testrun';
const config: TestRunnerConfig = {
async postVisit(page, context) {
await screenshot(page, context, {
/* options */
});
},
};
export default config;
[!IMPORTANT] 由于
screenshot
函数内部自动执行稳定性检查,因此不需要waitForPageReady
等待函数。
$ test-storybook
然后,只需适当地运行 @storybook/test-runner
。
默认情况下,屏幕截图图像保存在 __screenshots__
目录中。
TypeScript 设置
通过导入 ScreenshotParameters
并为您使用的框架合并类型,您可以为每个 Story 中指定的参数启用类型检查。
import type { ScreenshotParameters } from 'storycap-testrun';
// Replace it with the framework you are using.
declare module '@storybook/react' {
interface Parameters {
screenshot?: ScreenshotParameters;
}
}
API
screenshot(page, context, options)
page: Page
- 在
postVisit
中传入的 Playwright page 实例。
- 在
context: TestContext
- 在
postVisit
中传入的@storybook/test-runner
的测试上下文。
- 在
options: ScreenshotOptions
- 请参阅选项部分。
- 返回值:
Promise<Buffer | null>
- 捕获的屏幕截图图像的缓冲区。如果指定了
skip: true
,则返回null
。
- 捕获的屏幕截图图像的缓冲区。如果指定了
选项
可以在 screenshot
函数中作为第三个参数指定的选项。
output.dry
类型: boolean
默认值: false
如果指定为 true
,执行 screenshot
函数时将不会保存图像。这在处理返回的 Buffer 时很有用。
output.dir
类型: string
默认值: path.join(process.cwd(), '__screenshots__')
指定保存屏幕截图图像的根目录。
output.file
类型: string | ((context: TestContext) => string)
默认值: path.join('[title]', '[name].png')
指定每个 Story 的屏幕截图图像的文件名。
指定 string
时,可以使用以下模板
[id]
: Story ID[title]
: Story 的标题[name]
: Story 的名称
flakiness.metrics.enabled
类型: boolean
默认值: true
指定为 true
时,它会监控与 Story 渲染相关的几个指标并执行稳定性检查。
[!警告]
由于此过程依赖于 CDP,因此仅适用于 Chromium 浏览器。如果在非 Chromium 浏览器中启用,将显示警告。
flakiness.metrics.retries
类型: number
默认值: 1000
指标监控期间的重试次数。它会继续监控指定的帧数(1 帧 = 16 毫秒),并确保指标稳定。
flakiness.retake.enabled
类型: boolean
默认值: true
它计算屏幕截图图像的哈希值,并通过确保图像没有变化来检查渲染内容的稳定性。
[!提示]
对于 Chromium,通常仅启用flakiness.metrics.enabled
就足够了。启用此选项意味着至少捕获两次屏幕截图,因此如果导致性能下降,建议禁用它。
flakiness.retake.interval
类型: number
默认值: 100
在尝试再次捕获屏幕截图之前的间隔(毫秒)。第二次捕获会立即执行以进行哈希检查。
flakiness.retake.retries
类型: number
默认值: 10
重复捕获屏幕截图直到图像哈希值相同的次数。建议使用 3 或更大的值以达到重试的效果。
hooks
类型: ScreenshotHook[]
默认值: []
用于在屏幕截图捕获前后中断进程的 Hooks。请指定一个实现了以下接口的对象。
export type ScreenshotHook = {
setup?: TestHook;
preCapture?: TestHook;
postCapture?: (
page: Page,
context: TestContext,
image: ScreenshotImage,
) => Promise<void>;
};
每个 Hook 在以下生命周期中执行
方法 | 描述 |
---|---|
setup |
screenshot 函数执行后立即执行 |
preCapture |
waitForPageReady 执行后 |
postCapture |
捕获屏幕截图后,保存图像之前 |
Masking 和 Removal 等内置功能是使用 Hooks 实现的。
fullPage
类型: boolean
默认值: true
请参阅 Page | Playwright。
omitBackground
类型: boolean
默认值: false
请参阅 Page | Playwright。
scale
类型: 'css' | 'device'
默认值: 'device'
请参阅 Page | Playwright。
参数
这些是每个 Story 可以指定的参数。
// Button.stories.tsx
const meta: Meta<typeof Button> = {
component: Button,
parameters: {
screenshot: {
/* parameters... */
},
},
};
export default meta;
skip
类型: boolean
默认值: false
跳过屏幕截图捕获。在您想使用 @storybook/test-runner
进行测试但禁用屏幕截图捕获的情况下很有用。
delay
类型: number
默认值: 无
在捕获屏幕截图之前的延迟(毫秒)。在完成基本稳定性检查后等待。
mask
类型: string | { selector: string; color: string }
默认值: 无
使用矩形遮罩与 CSS 选择器对应的元素。对于每次渲染内容必然不同的元素很有用。
remove
类型: string
默认值: 无
移除与 CSS 选择器对应的元素。
更新日志
请参阅 CHANGELOG.md。