Agent SkillsDanielSuo117/velocitai › page-load-assertion

page-load-assertion

GitHub

定义页面加载断言方法is_page_loaded(),提供A/B/C/D/E五种验证模式及决策树。通过验证关键元素渲染而非HTTP状态,确保页面正常加载,涵盖单元素、组合验证、激活态及白屏检测等场景。

zh/skills/page-load-assertion/SKILL.md DanielSuo117/velocitai

Trigger Scenarios

页面断言 is_page_loaded page loaded 页面加载验证

Install

npx skills add DanielSuo117/velocitai --skill page-load-assertion -g -y
More Options

Non-standard path

npx skills add https://github.com/DanielSuo117/velocitai/tree/main/zh/skills/page-load-assertion -g -y

Use without installing

npx skills use DanielSuo117/velocitai@page-load-assertion

指定 Agent (Claude Code)

npx skills add DanielSuo117/velocitai --skill page-load-assertion -a claude-code -g -y

安装 repo 全部 skill

npx skills add DanielSuo117/velocitai --all -g -y

预览 repo 内 skill

npx skills add DanielSuo117/velocitai --list

SKILL.md

Frontmatter
{
    "name": "page-load-assertion",
    "description": "is_page_loaded() 四种验证模式与调用层级。触发:页面断言、is_page_loaded、page loaded、页面加载验证。"
}

Page Load Assertion — 页面加载断言方法论

核心思路

页面"正常"的判断不是检查 HTTP 状态码,而是验证用户能看到的关键元素确实渲染出来了。通过每个 PageObject 的 is_page_loaded() 方法统一实现。


is_page_loaded() 的四种验证模式

按严格程度从低到高:

模式 A:单元素验证(最简单)

检查该页面独有的标志性容器是否可见。适用于结构简单、一个元素就能区分的页面:

PAGE_CONTAINER = "css=.feature-container"    # P3

def is_page_loaded(self) -> bool:
    return self.is_visible(self.PAGE_CONTAINER)

模式 B:双元素 AND 组合(推荐默认)

容器 + 内容 双重验证,确保"页面骨架到位 + 数据渲染完成":

PAGE_CONTAINER = "css=.feature-container"    # P3
PAGE_TITLE = "text=欢迎使用"                  # P1

def is_page_loaded(self) -> bool:
    return self.is_visible(self.PAGE_CONTAINER) and self.is_visible(self.PAGE_TITLE)

模式 C:多元素 + 激活态验证(最严格)

在结构和内容基础上,还验证当前 UI 状态(如某个 tab 处于 active)。适用于承担"起点状态判断"语义的页面:

PAGE_TITLE = "css=span.page-title"                                    # P3
TAB_BAR = "css=ul.tab-bar"                                            # P3
DEFAULT_TAB_ACTIVE = "css=ul.tab-bar li.tab.active >> text=默认Tab"    # P3+P1

def is_page_loaded(self) -> bool:
    return (
        self.is_visible(self.PAGE_TITLE)
        and self.is_visible(self.TAB_BAR)
        and self.is_visible(self.DEFAULT_TAB_ACTIVE)
    )

注意:状态类 selector(.active / aria-selected 等)必须配 text 锁定,否则切换 tab 后 .active 跟随新激活对象漂移。

模式 D:委托给语义方法

把验证逻辑提取为有业务含义的方法名,便于 setup fixture 中单独调用:

def is_page_loaded(self) -> bool:
    return self.is_login_success()

def is_login_success(self) -> bool:
    return self.is_visible(self.SUCCESS_FLAG) and self.is_visible(self.NAV_LIST)

模式选择决策树

新页面需要 is_page_loaded()
│
├─ 页面结构简单,一个独有容器即可区分?
│  └─ 是 → 模式 A(单元素)
│
├─ 需要确认内容也渲染到位?
│  └─ 是 → 模式 B(容器 + 内容,推荐默认)
│
├─ 该页面是复位 fixture 的起点,需要判断 UI 状态?
│  └─ 是 → 模式 C(多元素 + 激活态)
│
├─ 验证逻辑在 setup 中也需要单独调用?
│  └─ 是 → 模式 D(委托给语义方法)
│
└─ 容器可能存在但内容未渲染(SPA 子 Tab 切换 / 异步加载)?
   └─ 是 → 模式 E(JS evaluate 检查子元素数量)

验证元素的选择原则

原则 说明
选该页面独有的元素 不选通用 header/footer,选只有这个页面才有的容器或文本
优先选结构性容器 .feature-container.detail-wrapper,页面骨架不易变
文本元素锁定业务语义 text=欢迎使用,确认内容渲染到位
状态类 selector 配 text .active 会随操作漂移,必须加 >> text=具体文本 锁定
不选动态数据 具体数字、用户名等因数据变化导致断言不稳定

断言目标的三级稳定性

核心原则:优先选模板级文本(页面框架固定标题),禁止选数据级内容(动态计数、日期)。多视图场景中每个断言目标须同时满足「模板级 + 视图独占」。

完整规则与反例/正例 → assertion-patterns.md "断言目标稳定性"章节。

模式 E:白屏检测 + 空数据 vs 有数据 三态判断

SPA 应用中,容器 div 可能存在于 DOM 且 is_visible 返回 true,但内部组件未挂载(白屏)。此时模式 A/B 的 is_visible(容器) 会误判为正常。

页面内容区有三种状态,必须分别处理

页面内容区状态
│
├─ 白屏(渲染失败)
│  内容区子元素数 = 0,组件未挂载
│  → 判定:❌ 测试失败,报"内容区域未渲染,疑似白屏"
│
├─ 空数据(无业务数据但渲染正常)
│  内容区子元素数 > 0,但无业务数据项
│  通常有空状态提示(图片 + "暂无数据"/"还没有收藏题哦"等文案)
│  → 判定:✅ 渲染正常,页面确实没有业务数据
│
└─ 有数据(正常渲染)
   内容区子元素数 > 0,且有业务数据项
   → 判定:✅ 渲染正常

实现模板

# 定位符
CONTENT_CONTAINER = "css=<内容主容器>"                 # 页面骨架容器
EMPTY_STATE = "css=<空状态提示元素>"                    # 空状态组件(图片+文案)
DATA_ITEM = "css=<业务数据项>"                          # 单个数据条目

def get_content_render_state(self) -> str:
    """返回内容区渲染状态:'blank' / 'empty' / 'loaded'。"""
    return self.page.evaluate("""() => {
        const container = document.querySelector('<内容主容器选择器>');
        if (!container) return 'blank';
        const contentArea = container.querySelector('<内容区域选择器>');
        if (!contentArea || contentArea.children.length === 0) return 'blank';
        return 'loaded';
    }""")

def is_content_rendered(self) -> bool:
    """白屏检测:容器存在但内容区无子元素 → False。
    空数据和有数据都算渲染成功 → True。"""
    return self.get_content_render_state() != 'blank'

def has_data_items(self) -> bool:
    """是否有业务数据(排除空状态)。"""
    return self.get_element_count(self.DATA_ITEM) > 0

用例中的三态断言

# 第一层:渲染检测(白屏 vs 已渲染)
is_rendered = page_obj.is_content_rendered()
if not is_rendered:
    assert False, "内容区域未渲染,疑似白屏"

# 第二层(可选):空数据 vs 有数据
# 根据业务预期决定是否需要进一步区分
if page_obj.has_data_items():
    # 有数据 → 可以进一步验证数据内容
    pass
else:
    # 空数据 → 记录到报告,不视为失败
    allure.attach("该Tab当前无业务数据(空状态)", ...)

⚠️ 陷阱

错误做法 问题 正确做法
innerText.length > N 判断白屏 空状态提示文案可能很短,被误判为白屏 children.length > 0
空数据等同于失败 无收藏/无错题是合理的业务状态 白屏才失败,空数据只记录
只检查容器 is_visible 容器 div 可能存在但子组件未挂载 JS evaluate 检查子元素

适用场景

  • 同一容器内切换多个子 Tab,部分 Tab 可能无业务数据
  • 异步加载组件可能因接口超时未渲染
  • 页面骨架先渲染、内容延迟加载的 SPA 路由

调用层级

  1. class setup:登录后 assert home.is_page_loaded(), "首页加载失败"
  2. function resetif not self.home.is_page_loaded(): click_nav_home(); assert ...
  3. 用例体:每次跳转后 assert target.is_page_loaded(), "<页面>加载失败"

规则约束

  1. 每个 PageObject 必须实现 is_page_loaded()——返回 bool,放在类的最后一个方法
  2. is_page_loaded() 内部只用 is_visible() 组合,不抛异常

Version History

  • 6d28887 Current 2026-07-05 20:21

Same Skill Collection

skills/add-regression-point/SKILL.md
skills/architecture/SKILL.md
skills/browser-config/SKILL.md
skills/case-round-trip/SKILL.md
skills/gen-page-test/SKILL.md
skills/locator-replacer/SKILL.md
skills/page-load-assertion/SKILL.md
skills/quick-debug/SKILL.md
skills/save-verify-strategy/SKILL.md
skills/test-runner/SKILL.md
zh/skills/add-regression-point/SKILL.md
zh/skills/architecture/SKILL.md
zh/skills/browser-config/SKILL.md
zh/skills/case-round-trip/SKILL.md
zh/skills/gen-page-test/SKILL.md
zh/skills/locator-replacer/SKILL.md
zh/skills/quick-debug/SKILL.md
zh/skills/save-verify-strategy/SKILL.md
zh/skills/test-runner/SKILL.md
en/skills/SKILL.md
skills/code-review-graph/SKILL.md
skills/SKILL.md
skills/wait-strategy/SKILL.md
zh/skills/code-review-graph/SKILL.md
zh/skills/SKILL.md
zh/skills/wait-strategy/SKILL.md

Metadata

Files
0
Version
6d28887
Hash
b0bfe0fc
Indexed
2026-07-05 20:21

trang chủ - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-08 23:39
浙ICP备14020137号-1 $bản đồ khách truy cập$