Token导航 LogoToken导航

Agent Skill · 开发

fosmvvm-serverrequest-test-generator(fosmvvm 服务器请求测试生成器)

用于辅助测试设计、自动化测试、用例整理和回归验证。它适合让 Agent 编写单元测试、端到端测试、测试计划或根据失败日志定位问题。使用时需要确认项目测试框架、运行命令和夹具数据,避免为了通过测试而改坏真实逻辑;涉及浏览器或外部服务时,应区分本地模拟、测试环境和生产环境。

fosmvvm-serverrequest-test-generator 是开发类 Agent Skill,可用宿主为 OpenClaw,通过ClawHub获取,权限为需要联网;许可证为 MIT-0,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 2,079。

总安装 20,784周安装 849GitHub Stars 2下载 6,724核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT-0
版本
2.0.6

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:fosmvvm-serverrequest-test-generator(fosmvvm 服务器请求测试生成器)
来源仓库:https://github.com/foscomputerservices/fosmvvm-serverrequest-test-generator
安装命令:
openclaw skills install fosmvvm-serverrequest-test-generator
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 OpenClaw 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

ClawHubOpenClaw
openclaw skills install fosmvvm-serverrequest-test-generator

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

使用 VaporTesting 生成 ServerRequest 测试代码,并进行类型化请求/响应验证和 CRUD 操作的自动路由。

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 OpenClaw;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 openclaw skills install fosmvvm-serverrequest-test-generator;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

fosmvvm-serverrequest-test-generator 怎么安装?

在终端执行 openclaw skills install fosmvvm-serverrequest-test-generator。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

fosmvvm-serverrequest-test-generator 支持哪些 AI 工具?

公开资料标注支持 OpenClaw。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

fosmvvm-serverrequest-test-generator 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

fosmvvm-serverrequest-test-generator 是免费的吗?

来源标注的许可证是 MIT-0。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

fosmvvm-serverrequest-test-generator 用的人多吗?

公开数据是累计安装 20,784 次,近一周安装 849 次,下载 6,724 次,GitHub 2 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

fosmvvm-serverrequest-test-generator 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 专注 OpenClaw 一种宿主,触发方式和使用习惯不用来回切换。
  • 许可证明确为 MIT-0,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 OpenClaw,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
fosmvvm-serverrequest-test-generator

fosmvvm 服务器请求测试生成器 · 本页

20,7842需要联网MIT-0通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

name
fosmvvm-serverrequest-test-generator
description
Generate ServerRequest tests using VaporTesting. Covers typed request/response validation for Show, Create, Update, and Delete operations.
homepage
https://github.com/foscomputerservices/FOSUtilities
metadata
{"clawdbot": {"emoji": "🧪", "os": ["darwin", "linux"]}}

FOSMVVM ServerRequest Test Generator

Generate test files for ServerRequest types using VaporTesting infrastructure.

Conceptual Foundation

For full architecture context, see FOSMVVMArchitecture.md | OpenClaw reference

ServerRequest testing uses VaporTesting infrastructure to send typed requests through the full server stack:

┌─────────────────────────────────────────────────────────────────────┐
│                    ServerRequest Test Flow                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Test Code:                                                          │
│    let request = MyRequest(query: .init(...))                        │
│    app.testing().test(request, locale: en) { response in }           │
│                                                                      │
│  Infrastructure handles:                                             │
│    • Path derivation from type name (MyRequest → /my)                │
│    • HTTP method from action (ShowRequest → GET)                     │
│    • Query/body encoding                                             │
│    • Header injection (locale, version)                              │
│    • Response decoding to ResponseBody type                          │
│                                                                      │
│  You verify:                                                         │
│    • response.status (HTTPStatus)                                    │
│    • response.body (R.ResponseBody? - typed!)                        │
│    • response.error (R.ResponseError? - typed!)                      │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

STOP AND READ THIS

Testing ServerRequests uses VaporTesting infrastructure. No manual URL construction. Ever.

┌──────────────────────────────────────────────────────────────────────┐
│          SERVERREQUEST TESTING USES TestingApplicationTester          │
├──────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  1. Configure Vapor Application with routes                           │
│  2. Use app.testing().test(request, locale:) { response in }          │
│  3. Verify response.status, response.body, response.error             │
│                                                                       │
│  TestingServerRequestResponse<R> provides TYPED access to:            │
│    • status: HTTPStatus                                               │
│    • headers: HTTPHeaders                                             │
│    • body: R.ResponseBody?     ← Auto-decoded!                        │
│    • error: R.ResponseError?   ← Auto-decoded!                        │
│                                                                       │
└──────────────────────────────────────────────────────────────────────┘

What You Must NEVER Do

// ❌ WRONG - manual URL construction
let url = URL(string: "http://localhost:8080/my_request?query=value")!
let response = try await URLSession.shared.data(from: url)

// ❌ WRONG - string path with method
try await app.test(.GET, "/my_request") { response in }

// ❌ WRONG - manual JSON encoding/decoding
let json = try JSONEncoder().encode(requestBody)
let decoded = try JSONDecoder().decode(ResponseBody.self, from: data)

// ❌ WRONG - constructing TestingHTTPRequest manually
let httpRequest = TestingHTTPRequest(method: .GET, url: "/path", headers: headers)
try await app.testing().performTest(request: httpRequest)

What You Must ALWAYS Do

// ✅ RIGHT - Use TestingApplicationTester.test() with ServerRequest
let request = MyShowRequest(query: .init(userId: userId))
try await app.testing().test(request, locale: en) { response in
    #expect(response.status == .ok)
    #expect(response.body?.viewModel.name == "Expected Name")
}

// ✅ RIGHT - Test multiple locales
for locale in [en, es] {
    try await app.testing().test(request, locale: locale) { response in
        #expect(response.status == .ok)
        // Localized values are automatically handled
    }
}

// ✅ RIGHT - Test error responses
let badRequest = MyShowRequest(query: .init(userId: invalidId))
try await app.testing().test(badRequest, locale: en) { response in
    #expect(response.status == .notFound)
    #expect(response.error != nil)
}

The path is derived from the ServerRequest type. HTTP method comes from the action. Headers are automatic. You NEVER write URL strings or decode JSON manually.


When to Use This Skill

  • Testing any ServerRequest implementation
  • Verifying server responses for CRUD operations
  • Testing error handling and edge cases
  • Multi-locale response verification
  • Integration testing between client request types and server controllers

If you're about to write URLSession, app.test(.GET, "/path"), or manual JSON decoding, STOP and use this skill instead.

What This Skill Generates

FileLocationPurpose
{Feature}RequestTests.swiftTests/{Target}Tests/Requests/Test suite for ServerRequest
Test YAML (if needed)Tests/{Target}Tests/TestYAML/Localization for test ViewModels

Project Structure Configuration

PlaceholderDescriptionExample
{Feature}Feature or entity name (PascalCase)Idea, User, Dashboard
{Target}Server test targetWebServerTests, AppTests
{ViewModelsTarget}Shared ViewModels SPM targetViewModels
{WebServerTarget}Server-side targetWebServer, AppServer
{ResourceDir}YAML resource directoryTestYAML, Resources

Key Types

TestingServerRequestResponse<R>

Wraps HTTP response with typed access:

PropertyTypeDescription
statusHTTPStatusHTTP status code (.ok, .notFound, etc.)
headersHTTPHeadersResponse headers
bodyR.ResponseBody?Typed response body (auto-decoded)
errorR.ResponseError?Typed error (auto-decoded)

TestingApplicationTester Extension

func test<R: ServerRequest>(
    _ request: R,
    locale: Locale = en,
    headers: HTTPHeaders = [:],
    afterResponse: (TestingServerRequestResponse<R>) async throws -> Void
) async throws -> any TestingApplicationTester

Convenience Locales

Available on TestingApplicationTester:

  • en - English
  • enUS - English (US)
  • enGB - English (UK)
  • es - Spanish

Test Structure

Basic Test Suite

import FOSFoundation
@testable import FOSMVVM
import FOSTesting
import FOSTestingVapor
import Foundation
import Testing
import Vapor
import VaporTesting

@Suite("MyFeature Request Tests")
struct MyFeatureRequestTests {
    @Test func showRequest_success() async throws {
        try await withTestApp { app in
            let request = MyShowRequest(query: .init(id: validId))

            try await app.testing().test(request, locale: en) { response in
                #expect(response.status == .ok)
                #expect(response.body?.viewModel != nil)
            }
        }
    }

    @Test func showRequest_notFound() async throws {
        try await withTestApp { app in
            let request = MyShowRequest(query: .init(id: invalidId))

            try await app.testing().test(request, locale: en) { response in
                #expect(response.status == .notFound)
            }
        }
    }
}

private func withTestApp(_ test: (Application) async throws -> Void) async throws {
    try await withApp { app in
        // Configure routes
        try app.routes.register(collection: MyController())
        try await test(app)
    }
}

Testing Different Request Types

Request TypeHTTP MethodWhat to Test
ShowRequestGETQuery params, response body, localization
ViewModelRequestGETViewModel population, all localized fields
CreateRequestPOSTRequestBody validation, created entity, ID response
UpdateRequestPATCHRequestBody validation, updated entity, response
DeleteRequestDELETEEntity removal, status code

How to Use This Skill

Invocation: /fosmvvm-serverrequest-test-generator

Prerequisites:

  • ServerRequest type understood from conversation context
  • Test scenarios identified (success paths, error paths, validation)
  • Controller implementation exists or is being created
  • VaporTesting infrastructure understood

Workflow integration: This skill is used when testing ServerRequest implementations. The skill references conversation context automatically—no file paths or Q&A needed. Typically follows fosmvvm-serverrequest-generator.

Pattern Implementation

This skill references conversation context to determine test structure:

Request Analysis

From conversation context, the skill identifies:

  • ServerRequest type (from prior discussion or server implementation)
  • Request protocol (ShowRequest, CreateRequest, UpdateRequest, etc.)
  • ResponseBody type (ViewModel or simple structure)
  • ResponseError type (custom errors or EmptyError)

Test Scenario Planning

Based on operation semantics:

  • Success paths (valid input, expected output)
  • Error paths (not found, validation failure, business logic errors)
  • Localization (if ResponseBody has localized fields)
  • Multi-locale (testing across supported locales)

Infrastructure Detection

From project state:

  • Existing test patterns (similar test files in codebase)
  • Localization setup (YAML fixtures needed)
  • Database requirements (seed data for tests)

Test File Generation

  1. Test suite conforming to VaporTesting patterns
  2. One @Test function per scenario
  3. withTestApp helper for application setup
  4. Route registration
  5. Request invocations using app.testing().test()

Context Sources

Skill references information from:

  • Prior conversation: Test requirements, scenarios discussed
  • ServerRequest: If Claude has read ServerRequest code into context
  • Controller: From server implementation
  • Existing tests: From codebase analysis of similar test files

Common Scenarios

Testing ViewModelRequest with Localization

@Test func viewModelRequest_multiLocale() async throws {
    try await withTestApp { app in
        let request = DashboardViewModelRequest()

        // Test English
        try await app.testing().test(request, locale: en) { response in
            #expect(response.status == .ok)
            let vm = try #require(response.body)
            #expect(try vm.pageTitle.localizedString == "Dashboard")
        }

        // Test Spanish
        try await app.testing().test(request, locale: es) { response in
            #expect(response.status == .ok)
            let vm = try #require(response.body)
            #expect(try vm.pageTitle.localizedString == "Tablero")
        }
    }
}

Testing CreateRequest with Validation

@Test func createRequest_validInput() async throws {
    try await withTestApp { app in
        let request = CreateIdeaRequest(requestBody: .init(
            content: "Valid idea content"
        ))

        try await app.testing().test(request, locale: en) { response in
            #expect(response.status == .ok)
            #expect(response.body?.id != nil)
        }
    }
}

@Test func createRequest_invalidInput() async throws {
    try await withTestApp { app in
        let request = CreateIdeaRequest(requestBody: .init(
            content: ""  // Empty content should fail validation
        ))

        try await app.testing().test(request, locale: en) { response in
            #expect(response.status == .badRequest)
            #expect(response.error != nil)
        }
    }
}

Testing UpdateRequest

@Test func updateRequest_success() async throws {
    try await withTestApp { app in
        // First create an entity
        let createRequest = CreateIdeaRequest(requestBody: .init(content: "Original"))
        var createdId: ModelIdType?
        try await app.testing().test(createRequest, locale: en) { response in
            createdId = response.body?.id
        }

        // Then update it
        let updateRequest = UpdateIdeaRequest(requestBody: .init(
            ideaId: try #require(createdId),
            content: "Updated content"
        ))

        try await app.testing().test(updateRequest, locale: en) { response in
            #expect(response.status == .ok)
            #expect(response.body?.viewModel.content == "Updated content")
        }
    }
}

Testing DeleteRequest

@Test func deleteRequest_success() async throws {
    try await withTestApp { app in
        // Create, then delete
        let deleteRequest = DeleteIdeaRequest(requestBody: .init(ideaId: existingId))

        try await app.testing().test(deleteRequest, locale: en) { response in
            #expect(response.status == .ok)
        }

        // Verify deleted (should return not found)
        let showRequest = ShowIdeaRequest(query: .init(ideaId: existingId))
        try await app.testing().test(showRequest, locale: en) { response in
            #expect(response.status == .notFound)
        }
    }
}

Testing ShowRequest with Query Parameters

@Test func showRequest_withQuery() async throws {
    try await withTestApp { app in
        let request = UserShowRequest(query: .init(
            userId: userId,
            includeDetails: true
        ))

        try await app.testing().test(request, locale: en) { response in
            #expect(response.status == .ok)
            #expect(response.body?.user.details != nil)
        }
    }
}

Testing ServerRequestError Localizations

Why Error Localization Testing is Different

Unlike ViewModels, ServerRequestError types:

  • Are often enums, not structs
  • Do not conform to Stubbable or RetrievablePropertyNames
  • Cannot use expectTranslations(ErrorType.self) like ViewModels

This means you must manually test each error case individually.

The Pattern

Use LocalizableTestCase.expectTranslations(_ localizable:) on each error's Localizable property:

@Suite("MyError Localization Tests")
struct MyErrorLocalizationTests: LocalizableTestCase {
    let locStore: LocalizationStore

    init() throws {
        self.locStore = try Self.loadLocalizationStore(
            bundle: Bundle.module,
            resourceDirectoryName: "TestYAML"
        )
    }

    @Test func errorMessages_simpleErrors() throws {
        // Test each error case individually
        let serverFailed = MyError(code: .serverFailed)
        try expectTranslations(serverFailed.message)

        let appFailed = MyError(code: .applicationFailed)
        try expectTranslations(appFailed.message)
    }

    @Test func errorMessages_withSubstitutions() throws {
        // For errors with associated values, test with representative values
        let quotaError = QuotaError(code: .quotaExceeded(requested: 100, maximum: 50))
        try expectTranslations(quotaError.message)
    }
}

Testing Error Messages in Integration Tests

When testing the full request/response cycle, verify error messages resolve:

@Test func createRequest_validationError_hasLocalizedMessage() async throws {
    try await withTestApp { app in
        let request = CreateIdeaRequest(requestBody: .init(content: ""))

        try await app.testing().test(request, locale: en) { response in
            #expect(response.status == .badRequest)
            let error = try #require(response.error)

            // Verify the message resolved (not empty or pending)
            #expect(!error.message.isEmpty)

            // Optionally verify specific text for English locale
            #expect(try error.message.localizedString.contains("required"))
        }
    }
}

Why Not Stubbable?

Stubbable works well for ViewModels because:

  • ViewModels are structs with many properties
  • A single stub() provides a complete test instance

ServerRequestError types are often enums where:

  • Each case may have different associated values
  • Each case may have a different localized message
  • A single stub() can't cover all cases

You must enumerate and test each error case explicitly.

Checklist for Error Localization Tests

  • [ ] Test each enum case for simple errors
  • [ ] Test representative associated values for parameterized errors
  • [ ] Verify messages resolve (not empty) for all configured locales
  • [ ] Verify substitution placeholders are replaced in LocalizableSubstitutions

Troubleshooting

"Route not found" Error

Cause: Controller not registered in test app.

Fix: Register the controller before testing:

try app.routes.register(collection: MyController())

Response body is nil but status is .ok

Cause: JSON decoding failed silently.

Fix: Check that ResponseBody type matches server response exactly. Use response.headers to verify Content-Type.

Localization not applied

Cause: Locale not passed to encoder.

Fix: The test(_:locale:) method handles this automatically. Ensure you're passing the locale parameter.

"Missing Translation" in Response

Cause: YAML localization not loaded.

Fix: Initialize localization store in test app setup:

try app.initYamlLocalization(
    bundle: Bundle.module,
    resourceDirectoryName: "TestYAML"
)

Naming Conventions

ConceptConventionExample
Test suite{Feature}RequestTestsIdeaRequestTests
Test file{Feature}RequestTests.swiftIdeaRequestTests.swift
Test method (success){action}Request_successshowRequest_success
Test method (error){action}Request_{errorCase}showRequest_notFound
Test method (validation){action}Request_{validationCase}createRequest_emptyContent
Test helperwithTestAppwithTestApp { app in }
Locale constanten, es, enUS, enGBlocale: en


File Templates

See reference.md for complete file templates.


See Also


Version History

VersionDateChanges
1.12025-01-20Add ServerRequestError localization testing guidance
1.22026-01-24Update to context-aware approach (remove file-parsing/Q&A). Skill references conversation context instead of asking questions or accepting file paths.
1.02025-01-05Initial skill

平台分布

OpenClaw

73.01%
按下载量换算4,909

安全审计

VirusTotal

通过

ClawScan

通过

Static analysis

未展示

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills