生成 ViewModel 测试,支持编解码往返、版本稳定性及多语言翻译验证。
FOSMVM ViewModel 测试生成器. 遵循 FOSMVM 测试模式的 ViewModels 测试文件.是一项面向实际任务的技能,主要用于Conception Foundation.;Conception Freaty. 完整的架构背景,参见 FOSMVVMARCHITECTure.md QOpenCla。
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;
涉及批量任务时,还应保存进度,避免中断后重复操作。该技能适合用于一次性任务,也可以接入自动化工作流,与其他技能或上层代理配合完成更完整的业务链路;在组合使用时,应明确每一步的输入输出关系,并避免不同步骤之间出现参数冲突。
依据 FOSMVVM 测试模式,为 ViewModel 生成测试文件。
如需完整架构背景,请参阅
FOSMVVMArchitecture.md|OpenClaw 参考文档
FOSMVVM 中的 ViewModel 测试需验证以下三个关键方面:
@LocalizedString 属性在所有受支持的语言环境中均具备对应值LocalizableTestCase 协议提供了基础设施,可在单次调用中完成上述三项验证。
@LocalizedSubs 替换行为| 文件 | 位置 | 用途 |
|---|---|---|
{Name}ViewModelTests.swift |
Tests/{Target}Tests/Localization/ |
遵循 LocalizableTestCase 协议的测试套件 |
{Name}ViewModel.yml |
Tests/{Target}Tests/TestYAML/ |
测试所用 YAML 翻译文件(按需) |
对绝大多数 ViewModel,仅需一行代码即可实现完整覆盖:
@Test func dashboardViewModel() throws {
try expectFullViewModelTests(DashboardViewModel.self)
}
该调用将验证:
该方式足以满足绝大多数 ViewModel 测试需求。
当需测试特定格式行为(如替换、复合字符串)时,可添加语言环境专属断言:
@Test func greetingWithSubstitution() throws {
try expectFullViewModelTests(GreetingViewModel.self)
// 验证特定替换行为
let vm: GreetingViewModel = try .stub()
.toJSON(encoder: encoder(locale: en))
.fromJSON()
#expect(try vm.welcomeMessage.localizedString == "Welcome, John!")
}
此为可选操作,仅在需要验证特定格式技术时使用。
测试套件需遵循 LocalizableTestCase 协议以接入测试基础设施:
import FOSFoundation
@testable import FOSMVVM
import FOSTesting
import Foundation
import Testing
@testable import {ViewModelsTarget}
@Suite("My ViewModel Tests")
struct MyViewModelTests: LocalizableTestCase {
let locStore: LocalizationStore
init() throws {
self.locStore = try Self.loadLocalizationStore(
bundle: {ViewModelsTarget}.resourceAccess,
resourceDirectoryName: ""
)
}
}
{ViewModelsTarget}.resourceAccess 是在创建 ViewModels SPM target 时(通过 FOSResourceAccessor 构建工具插件)定义的资源访问器。
| 属性/方法 | 用途 |
|---|---|
locStore |
必需 —— 本地化存储对象 |
locales |
可选 —— 待测试的语言环境(默认:en、es) |
encoder(locale:) |
创建支持本地化的 JSONEncoder |
en、es、enGB、enUS |
语言环境常量 |
| 方法 | 适用场景 |
|---|---|
expectFullViewModelTests(_:) |
主要方法 —— 完整 ViewModel 测试 |
expectTranslations(_:) |
仅验证本地化翻译 |
expectFullFieldValidationModelTests(_:) |
测试 FieldValidationModel 类型 |
expectFullFormFieldTests(_:) |
测试 FormField 实例 |
expectCodable(_:encoder:) |
仅执行 Codable 往返序列化测试 |
expectVersionedViewModel(_:encoder:) |
仅验证版本稳定性 |
每个含 @LocalizedString 属性的 ViewModel 均需提供 YAML 条目:
@ViewModel
public struct DashboardViewModel: RequestableViewModel {
@LocalizedString public var pageTitle // 需要 YAML 条目
@LocalizedString public var emptyMessage // 需要 YAML 条目
public let itemCount: Int // 无需 YAML
}
# DashboardViewModel.yml
en:
DashboardViewModel:
pageTitle: "Dashboard"
emptyMessage: "No items yet"
es:
DashboardViewModel:
pageTitle: "Tablero"
emptyMessage: "No hay elementos todavía"
当 ViewModel 包含子 ViewModel 时,整个层级中的所有类型均需提供 YAML 条目:
@ViewModel
public struct BoardViewModel: RequestableViewModel {
@LocalizedString public var title
public let cards: [CardViewModel] // 子 ViewModel
}
@ViewModel
public struct CardViewModel {
@LocalizedString public var cardTitle
}
BoardViewModel 与 CardViewModel 均需 YAML 条目(可置于同一文件或独立文件中)。
若测试文件中定义了用于特定场景的私有 ViewModel 结构体,则这些类型同样需要 YAML 条目:
// 在测试文件中
private struct TestParentViewModel: ViewModel {
@LocalizedString var title
let children: [TestChildViewModel]
}
private struct TestChildViewModel: ViewModel {
@LocalizedString var label
}
请为这些私有类型在测试专用 YAML 文件中添加对应条目。
调用方式:
/fosmvvm-viewmodel-test-generator
前置条件:
@LocalizedString、@LocalizedSubs 等)工作流集成:
本技能在为 ViewModel 补充测试覆盖率时使用。技能会自动引用对话上下文 —— 无需提供文件路径或问答交互。通常紧随 fosmvvm-viewmodel-generator 使用。
本技能通过引用对话上下文确定测试结构:
根据对话上下文,技能识别出:
@LocalizedString 属性)@LocalizedSubs)校验完整性:
@LocalizedString 属性)生成包含以下内容的测试套件:
LocalizableTestCase 协议expectFullViewModelTests()技能参考的信息来源包括:
完整文件模板详见 reference.md。
@Test func dashboardViewModel() throws {
try expectFullViewModelTests(DashboardViewModel.self)
}
@Test func boardViewModels() throws {
try expectFullViewModelTests(BoardViewModel.self)
try expectFullViewModelTests(ColumnViewModel.self)
try expectFullViewModelTests(CardViewModel.self)
}
var locales: Set{ [en, es, enGB] } // 覆盖默认设置 @Test func multiLocaleViewModel() throws { try expectFullViewModelTests(MyViewModel.self) // 将测试 en、es 和 en-GB }
@Test func greetingSubstitutions() throws {
try expectFullViewModelTests(GreetingViewModel.self)
let vm: GreetingViewModel = try .stub(userName: "Alice")
.toJSON(encoder: encoder(locale: en))
.fromJSON()
#expect(try vm.welcomeMessage.localizedString == "Welcome, Alice!")
}
@Test func parentWithChildren() throws {
// 测试父 ViewModel 并验证子 ViewModel 可被编码/解码
try expectFullViewModelTests(ParentViewModel.self)
// 可选:验证特定子项值
let vm: ParentViewModel = try .stub()
.toJSON(encoder: encoder(locale: en))
.fromJSON()
#expect(try vm.children[0].label.localizedString == "Child 1")
}
FOSLocalizableError: _pageTitle -- Missing Translation -- en
原因:@LocalizedString 属性缺失 YAML 条目。
修复:在 YAML 文件中添加该属性:
en:
MyViewModel:
pageTitle: "Page Title" # 添加此项
原因:ViewModel 未使用支持本地化的 encoder 进行编码。
修复:确保使用 encoder(locale:) 或 expectFullViewModelTests()。
原因:YAML 值虽存在,但可能存在拼写错误或内容错误。
修复:添加精确值断言进行校验:
let vm = try .stub().toJSON(encoder: encoder(locale: en)).fromJSON() #expect(try vm.title.localizedString == "Expected Value")
| 概念 | 规范 | 示例 |
|---|---|---|
| 测试套件 | {Feature}ViewModelTests |
DashboardViewModelTests |
| 测试文件 | {Feature}ViewModelTests.swift |
DashboardViewModelTests.swift |
| YAML 文件 | {ViewModelName}.yml |
DashboardViewModel.yml |
| 测试方法 | {viewModelName}() 或具描述性名称 |
dashboardViewModel() |
FOSMVVMArchitecture.md — 测试支持 — 架构概览fosmvvm-viewmodel-generator — 用于创建 ViewModelfosmvvm-fields-generator — 用于表单验证测试reference.md — 完整文件模板| 版本 | 日期 | 变更内容 |
|---|---|---|
| 1.0 | 2025-01-02 | 初始版本 |
| 1.1 | 2026-01-19 | 更新 LocalizableTestCase 示例,采用 {ViewModelsTarget}.resourceAccess 模式。 |
| 1.2 | 2026-01-24 | 升级为上下文感知方案(移除文件解析/问答流程)。技能直接引用对话上下文,不再提问或接收文件路径。 |
相关专题
热门下载
相关下载
精品课程
共6课时 | 54.7万人学习
共89课时 | 134.1万人学习
共49课时 | 82.6万人学习
最新文章