概念定义
DOM 断言验证结构与行为;渲染结果——用户真正看到的——是另一个面。视觉回归逐像素 diff 那个面,把不可见的样式回归变成可评审的工件。
工作机制
浏览器按受控视口、主题与动画状态渲染目标,捕获确定性截图;diff 算法与基线比较并容忍渲染噪声。组件隔离消除页面级 flaky;整页捕获抓集成级联破坏。失败产出供人判读的 diff 图。
使用场景
令牌变更会波及全身的设计系统、跨断点的响应式布局、主题与暗色模式、以及“外观即产品”的营销页。截图要覆盖真实支持的断点矩阵而不是单一桌面视口。
常见误区
它是功能测试的补充不是替代:页面可以看起来一模一样而什么都不干,也可以功能完好而面目全非。严格像素比较在字体光栅与 GPU 差异上必 flaky——感知阈值加稳定环境才是手艺;基线失败即自动更新等于把套件变成无评审的变更记录仪。单视口整页快照会错过移动断点上的回归,显式捕获断点矩阵。
代码示例
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::Duration;
#[derive(Clone)]
struct FakeClock {
millis: Arc<AtomicU64>,
}
impl FakeClock {
fn new() -> Self {
Self {
millis: Arc::new(AtomicU64::new(0)),
}
}
fn now(&self) -> Duration {
Duration::from_millis(self.millis.load(Ordering::SeqCst))
}
fn advance(&self, delta: Duration) {
self.millis
.fetch_add(delta.as_millis() as u64, Ordering::SeqCst);
}
}
struct Token {
expires_at: Duration,
}
impl Token {
fn issue(clock: &FakeClock, ttl: Duration) -> Self {
Self {
expires_at: clock.now() + ttl,
}
}
fn expired(&self, clock: &FakeClock) -> bool {
clock.now() >= self.expires_at
}
}
fn main() {
let clock = FakeClock::new();
let token = Token::issue(&clock, Duration::from_secs(60));
clock.advance(Duration::from_secs(59));
println!("expired at 59s: {}", token.expired(&clock));
clock.advance(Duration::from_secs(1));
println!("expired at 60s: {}", token.expired(&clock));
}