fosmvvm-viewmodel-test-generator
Generate ViewModel tests with codable round-trip, versioning stability, and multi-locale translation verification.
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install clawskills:clawskills~foscomputerservices-fosmvvm-viewmodel-test-generatorcURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/clawskills%3Aclawskills~foscomputerservices-fosmvvm-viewmodel-test-generator/file -o foscomputerservices-fosmvvm-viewmodel-test-generator.md# FOSMVVM ViewModel Test Generator
Generate test files for ViewModels following FOSMVVM testing patterns.
## Conceptual Foundation
> For full architecture context, see [FOSMVVMArchitecture.md](../../docs/FOSMVVMArchitecture.md#testing-support) | [OpenClaw reference]({baseDir}/references/FOSMVVMArchitecture.md)
ViewModel testing in FOSMVVM verifies three critical aspects:
1. **Codable round-trip** - ViewModel encodes and decodes without data loss
2. **Versioning stability** - Structure hasn't changed unexpectedly
3. **Multi-locale translations** - All `@LocalizedString` properties have values in all supported locales
The `LocalizableTestCase` protocol provides infrastructure that tests all three in a single call.
---
## When to Use This Skill
- Creating tests for new ViewModels
- Adding test coverage to existing ViewModels
- Verifying localization completeness across locales
- Testing ViewModels with embedded/nested child ViewModels
- Verifying `@LocalizedSubs` substitution behavior
## What This Skill Generates
| File | Location | Purpose |
|------|----------|---------|
| `{Name}ViewModelTests.swift` | `Tests/{Target}Tests/Localization/` | Test suite conforming to `LocalizableTestCase` |
| `{Name}ViewModel.yml` | `Tests/{Target}Tests/TestYAML/` | YAML translations for test (if needed) |
---
## The Testing Pattern
### Standard Pattern (Most Tests)
For most ViewModels, a single line provides complete coverage:
```swift
@Test func dashboardViewModel() throws {
try expectFullViewModelTests(DashboardViewModel.self)
}
```
This verifies:
- Codable encoding/decoding
- Versioned ViewModel stability
- Translations exist for all locales (en, es by default)
**This is sufficient for the vast majority of ViewModel tests.**
### Extended Pattern (Specific Formatting Verification)
When testing specific formatting behavior (substitutions, compound strings), add locale-specific assertions:
```swift
@Test func greetingWithSubstitution() throws {
try expectFullViewModelTests(GreetingViewModel.self)
// Verify specific substitution behavior
let vm: GreetingViewModel = try .stub()
.toJSON(encoder: encoder(locale: en))
.fromJSON()
#expect(try vm.welcomeMessage.localizedString == "Welcome, John!")
}
```
This is optional - use only when verifying specific formatting techniques.
---
## LocalizableTestCase Protocol
Test suites conform to `LocalizableTestCase` to access testing infrastructure:
```swift
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: ""
)
}
}
```
The `{ViewModelsTarget}.resourceAccess` is the resource accessor defined when creating the ViewModels SPM target (via `FOSResourceAccessor` build tool plugin).
### What LocalizableTestCase Provides
| Property/Method | Purpose |
|-----------------|---------|
| `locStore` | Required - the localization store |
| `locales` | Optional - locales to test (default: en, es) |
| `encoder(locale:)` | Creates a localizing JSONEncoder |
| `en`, `es`, `enGB`, `enUS` | Locale constants |
### Testing Methods
| Method | Use When |
|--------|----------|
| `expectFullViewModelTests(_:)` | **Primary** - complete ViewModel testing |
| `expectTranslations(_:)` | Translation-only verification |
| `expectFullFieldValidationModelTests(_:)` | Testing FieldValidationModel types |
| `expectFullFormFieldTests(_:)` | Testing FormField instances |
| `expectCodable(_:encoder:)` | Codable round-trip only |
| `expectVersionedViewModel(_:encoder:)` | Versioning stability only |
---
## YAML Requirements
### ViewModels with @LocalizedString
Every ViewModel with `@LocalizedString` properties needs YAML entries:
```swift
@ViewModel
public struct DashboardViewModel: RequestableViewModel {
@LocalizedString public var pageTitle // Needs YAML entry
@LocalizedString public var emptyMessage // Needs YAML entry
public let itemCount: Int // No YAML needed
}
```
```yaml
# DashboardViewModel.yml
en:
DashboardViewModel:
pageTitle: "Dashboard"
emptyMessage: "No items yet"
es:
DashboardViewModel:
pageTitle: "Tablero"
emptyMessage: "No hay elementos todavía"
```
### Embedded ViewModels
When a ViewModel contains child ViewModels, all types in the hierarchy need YAML entries:
```swift
@ViewModel
public struct BoardViewModel: RequestableViewModel {
@LocalizedString public var title
public let cards: [CardViewModel] // Child ViewModel
}
@ViewModel
public struct CardViewModel {
@LocalizedString public var cardTitle
}
```
Both `BoardViewModel` and `CardViewModel` need YAML entries (can be in same or separate files).
### Private Test ViewModels
When tests define private ViewModel structs for testing specific scenarios, those also need YAML:
```swift
// In test file
private struct TestParentViewModel: ViewModel {
@LocalizedString var title
let children: [TestChildViewModel]
}
private struct TestChildViewModel: ViewModel {
@LocalizedString var label
}
```
Add entries to a test YAML file for these private types.
---
## How to Use This Skill
**Invocation:**
/fosmvvm-viewmodel-test-generator
**Prerequisites:**
- ViewModel structure understood from conversation context
- Localization properties identified (@LocalizedString, @LocalizedSubs, etc.)
- YAML localization files exist or will be created
- Child ViewModels identified (if any)
**Workflow integration:**
This skill is used when adding test coverage for ViewModels. The skill references conversation context automatically—no file paths or Q&A needed. Typically follows fosmvvm-viewmodel-generator.
## Pattern Implementation
This skill references conversation context to determine test structure:
### ViewModel Analysis
From conversation context, the skill identifies:
- **ViewModels to test** (from prior discussion or codebase)
- **Localization requirements** (@LocalizedString properties)
- **Child ViewModels** (embedded within parent)
- **Substitution behavior** (@LocalizedSubs needing specific verification)
### YAML Coverage Check
Verifies completeness:
- **ViewModel YAML entries** (all @LocalizedString properties)
- **Child ViewModel entries** (nested types)
- **Locale coverage** (en, es, or project-specific locales)
### Test File Generation
Creates test suite with:
- LocalizableTestCase conformance
- Localization store initialization
- expectFullViewModelTests() calls for each ViewModel
- Optional specific formatting tests (substitutions, compound strings)
### Context Sources
Skill references information from:
- **Prior conversation**: ViewModels discussed or recently created
- **ViewModel code**: If Claude has read ViewModel files into context
- **YAML files**: From codebase analysis of existing localizations
- **Test patterns**: From existing test files in project
---
## File Templates
See [reference.md](reference.md) for complete file templates.
---
## Common Scenarios
### Testing a Single Top-Level ViewModel
```swift
@Test func dashboardViewModel() throws {
try expectFullViewModelTests(DashboardViewModel.self)
}
```
### Testing Multiple Related ViewModels
```swift
@Test func boardViewModels() throws {
try expectFullViewModelTests(BoardViewModel.self)
try expectFullViewModelTests(ColumnViewModel.self)
try expectFullViewModelTests(CardViewModel.self)
}
```
### Testing with Custom Locales
```swift
var locales: Set<Locale> { [en, es, enGB] } // Override default
@Test func multiLocaleViewModel() throws {
try expectFullViewModelTests(MyViewModel.self)
// Tests en, es, AND en-GB
}
```
### Testing Substitution Behavior
```swift
@Test func greetingSubs