Pular para o conteúdo
Skillpedia
Testes280 mil · #126

swift-protocol-di-testing

Faz seu agente criar código Swift mais fácil de testar. Ele usa protocolos para isolar partes do código, permitindo simular dependências como rede ou arquivos.

O que ela faz

Esta ferramenta ajuda a tornar seu código Swift mais fácil de testar. Ela permite que você crie versões "falsas" (mocks) de partes do seu programa que interagem com o mundo exterior, como o sistema de arquivos ou a internet, para que você possa testar seu código sem realmente mexer com essas coisas.

Quando usar

  • ✓Quando você está escrevendo código Swift que salva ou lê arquivos.
  • ✓Quando você precisa testar como seu código reage a erros de rede.
  • ✓Ao criar partes do seu aplicativo que precisam funcionar em diferentes situações, como no app principal e nos testes.

Exemplo do que pedir para a IA

“Como posso testar meu código que salva dados em um arquivo sem realmente salvar um arquivo?”

Quer saber mais? Abra as seções abaixo.

Como usar

O jeito mais fácil: copie a mensagem abaixo e cole no Claude, ChatGPT, Cursor ou outra IA. Ela lê a skill e segue as instruções.

Link da skill

https://github.com/affaan-m/ECC/blob/main/pi/core/skills/swift-protocol-di-testing/SKILL.md

Mensagem pronta para colar

Use esta skill para me ajudar: https://github.com/affaan-m/ECC/blob/main/pi/core/skills/swift-protocol-di-testing/SKILL.md Leia o arquivo SKILL.md desse link e siga as instruções dele na minha tarefa.
Como funciona

Você define pequenas "regras" (protocolos) para as interações externas. Depois, cria implementações reais para o uso normal e implementações "falsas" para os testes. Seu código usa essas regras, e nos testes você diz para ele usar as versões falsas.

Instalação

Jeito mais fácil: copie o link da skill e cole no Claude, ChatGPT ou Cursor pedindo para seguir as instruções.

No terminal (Claude Code, Codex, Cursor), na pasta do projeto:

npx skills add affaan-m/ECC --skill swift-protocol-di-testing

Ou baixe só o arquivo:

curl -L https://raw.githubusercontent.com/affaan-m/ECC/main/pi/core/skills/swift-protocol-di-testing/SKILL.md -o SKILL.md
Conteúdo técnico (SKILL.md)

Tradução do texto original do autor no GitHub. Os comandos e códigos estão como no original.

Injeção de Dependência Baseada em Protocolos em Swift para Testes

Padrões para tornar o código Swift testável, abstraindo dependências externas (sistema de arquivos, rede, iCloud) por trás de protocolos pequenos e focados. Permite testes determinísticos sem I/O.

Quando Ativar

  • Escrevendo código Swift que acessa o sistema de arquivos, rede ou APIs externas
  • Necessidade de testar caminhos de tratamento de erros sem acionar falhas reais
  • Construindo módulos que funcionam em diferentes ambientes (app, teste, preview SwiftUI)
  • Projetando arquitetura testável com concorrência Swift (atores, Sendable)

Padrão Central

1. Defina Protocolos Pequenos e Focados

Cada protocolo lida com exatamente uma preocupação externa.

// File system access
public protocol FileSystemProviding: Sendable {
    func containerURL(for purpose: Purpose) -> URL?
}

// File read/write operations
public protocol FileAccessorProviding: Sendable {
    func read(from url: URL) throws -> Data
    func write(_ data: Data, to url: URL) throws
    func fileExists(at url: URL) -> Bool
}

// Bookmark storage (e.g., for sandboxed apps)
public protocol BookmarkStorageProviding: Sendable {
    func saveBookmark(_ data: Data, for key: String) throws
    func loadBookmark(for key: String) throws -> Data?
}

2. Crie Implementações Padrão (Produção)

public struct DefaultFileSystemProvider: FileSystemProviding {
    public init() {}

    public func containerURL(for purpose: Purpose) -> URL? {
        FileManager.default.url(forUbiquityContainerIdentifier: nil)
    }
}

public struct DefaultFileAccessor: FileAccessorProviding {
    public init() {}

    public func read(from url: URL) throws -> Data {
        try Data(contentsOf: url)
    }

    public func write(_ data: Data, to url: URL) throws {
        try data.write(to: url, options: .atomic)
    }

    public func fileExists(at url: URL) -> Bool {
        FileManager.default.fileExists(atPath: url.path)
    }
}

3. Crie Implementações Mock para Testes

public final class MockFileAccessor: FileAccessorProviding, @unchecked Sendable {
    public var files: [URL: Data] = [:]
    public var readError: Error?
    public var writeError: Error?

    public init() {}

    public func read(from url: URL) throws -> Data {
        if let error = readError { throw error }
        guard let data = files[url] else {
            throw CocoaError(.fileReadNoSuchFile)
        }
        return data
    }

    public func write(_ data: Data, to url: URL) throws {
        if let error = writeError { throw error }
        files[url] = data
    }

    public func fileExists(at url: URL) -> Bool {
        files[url] != nil
    }
}

4. Injete Dependências com Parâmetros Padrão

O código de produção usa os padrões; os testes injetam mocks.

public actor SyncManager {
    private let fileSystem: FileSystemProviding
    private let fileAccessor: FileAccessorProviding

    public init(
        fileSystem: FileSystemProviding = DefaultFileSystemProvider(),
        fileAccessor: FileAccessorProviding = DefaultFileAccessor()
    ) {
        self.fileSystem = fileSystem
        self.fileAccessor = fileAccessor
    }

    public func sync() async throws {
        guard let containerURL = fileSystem.containerURL(for: .sync) else {
            throw SyncError.containerNotAvailable
        }
        let data = try fileAccessor.read(
            from: containerURL.appendingPathComponent("data.json")
        )
        // Process data...
    }
}

5. Escreva Testes com Swift Testing

import Testing

@Test("Sync manager lida com contêiner ausente")
func testMissingContainer() async {
    let mockFileSystem = MockFileSystemProvider(containerURL: nil)
    let manager = SyncManager(fileSystem: mockFileSystem)

    await #expect(throws: SyncError.containerNotAvailable) {
        try await manager.sync()
    }
}

@Test("Sync manager lê dados corretamente")
func testReadData() async throws {
    let mockFileAccessor = MockFileAccessor()
    mockFileAccessor.files[testURL] = testData

    let manager = SyncManager(fileAccessor: mockFileAccessor)
    let result = try await manager.loadData()

    #expect(result == expectedData)
}

@Test("Sync manager lida com erros de leitura graciosamente")
func testReadError() async {
    let mockFileAccessor = MockFileAccessor()
    mockFileAccessor.readError = CocoaError(.fileReadCorruptFile)

    let manager = SyncManager(fileAccessor: mockFileAccessor)

    await #expect(throws: SyncError.self) {

…
Perguntas frequentes

O que são 'protocolos' neste contexto?

São como contratos que definem o que uma parte do código pode fazer, sem dizer exatamente como ela faz. Isso permite trocar a implementação real por uma falsa para testes.

O que é 'injetar dependências'?

É o ato de fornecer as partes que seu código precisa (como o acesso a arquivos) de fora, em vez de o código criá-las por conta própria. Isso facilita a troca por versões falsas para testes.

Por que usar 'mocks'?

Mocks são versões falsas de partes do seu código. Eles permitem simular situações específicas (como erros ou dados específicos) para testar seu código de forma controlada e confiável, sem depender do ambiente real.

Detalhes

Descrição original do autor

Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing. Use when Swift code needs testing and file system, network, or external APIs must be mocked.

repo: affaan-m/ECC

Popularidade

Estrelas no GitHub
280 mil
Posição no ranking
#126
Licença
MIT
Atualizada em
15/10/2026

Essa skill é útil?

0

Entre para votar.

Comentários

  • …

Mais skills deste repositório

Skills parecidas