Pular para o conteúdo

Testar um esquema

Sem HTTP, sem servidor — e o teste que pega a quebra de contrato antes do cliente.

Um esquema se testa sem rede: Lavra.executar recebe o texto da consulta e devolve o resultado. O servidor é outra camada, e ela tem os próprios testes.

dataforge
adopt Arcane.Lavra as Lavra
adopt Arcane.Crucible as Crucible

record Produto:
    id: Integer
    nome: String
    preco: Float

action montar():
    esq := Lavra.esquema("loja")
    Lavra.tipo(esq, Produto)
    Lavra.busca(esq, "produto", "Produto",
        args := {"id": "Integer!"},
        resolve := lambda r, a, c => (
            Produto(1, "café", 32.9) given a["id"] is 1 otherwise void))
    Lavra.conferir(esq)
    yield esq

crucible "o esquema da loja":

    trial "devolve o produto que existe":
        r := Lavra.executar(montar(), "busca:\n    produto(id: 1):\n        nome")
        expect r["dados"]["produto"]["nome"] is "café"

    trial "o que nao existe e VOID, e nao erro":
        r := Lavra.executar(montar(), "busca:\n    produto(id: 99):\n        nome")
        expect r["dados"]["produto"] is void
        expect len(r["erros"]) is 0

    trial "um campo que nao existe e recusado ANTES de executar":
        r := Lavra.executar(montar(), "busca:\n    produto(id: 1):\n        naoExiste")
        expect len(r["erros"]) is 1

    trial "o argumento obrigatorio que falta e recusado":
        r := Lavra.executar(montar(), "busca:\n    produto:\n        nome")
        expect len(r["erros"]) is 1

Crucible.run()

Validar sem executar#

Lavra.validar responde "esta consulta é legal neste esquema?" sem chamar resolvedor nenhum. É o que permite guardar as consultas do aplicativo no repositório e conferir todas num teste — a quebra aparece no CI, e não no aplicativo de quem já atualizou.

dataforge
adopt Arcane.Lavra as Lavra

record Produto:
    id: Integer
    nome: String

esq := Lavra.esquema("loja")
Lavra.tipo(esq, Produto)
Lavra.busca(esq, "produto", "Produto",
    args := {"id": "Integer!"}, resolve := lambda r, a, c => void)
Lavra.conferir(esq)

// as consultas que o aplicativo usa, guardadas no repositório
CONSULTAS := {
    "tela_produto": "busca:\n    produto(id: 1):\n        nome",
    "tela_antiga": "busca:\n    produto(id: 1):\n        descricao",
}

quebradas := []
cycle nome in sorted(keys(CONSULTAS)):
    erros := Lavra.validar(esq, CONSULTAS[nome])
    given len(erros) > 0:
        quebradas.append(nome)

assert quebradas is ["tela_antiga"]
out $"quebrada(s) pelo esquema atual: {quebradas}"

O esquema como texto, num instantâneo#

texto_do_esquema devolve a superfície inteira. Guardá-la num instantâneo faz qualquer mudança de contrato aparecer no diff do commit — inclusive a que ninguém pretendia:

dataforge
adopt Arcane.Lavra as Lavra

record Produto:
    id: Integer
    nome: String

esq := Lavra.esquema("loja")
Lavra.tipo(esq, Produto)
Lavra.busca(esq, "produtos", "[Produto!]!", resolve := lambda r, a, c => [])
Lavra.conferir(esq)

texto := Lavra.texto_do_esquema(esq)
assert "busca:" in texto and "tipo Produto:" in texto
out texto