Pular para o conteúdo principal

Testes de Journeys

Beta privado

Os testes de journeys estão em beta privado. Entre em contato com support@turn.io para solicitar acesso.

Testes de journeys permitem verificar o comportamento de uma journey automaticamente, em vez de repetir conversas manualmente no simulador. Os testes são escritos em Lua, ficam junto da journey e rodam contra a versão salva da journey, a mesma que o simulador usa.

Abra o painel de testes a partir do canvas da journey usando o botão de testes na barra de ferramentas. O editor salva enquanto você digita, e cada teste e suíte tem seu próprio botão de execução.

Escrevendo um teste

Declare testes com test(nome, fn). Dentro de um teste, simulation.start inicia uma conversa com a journey e retorna um identificador de sessão:

test("journey cumprimenta e pergunta o nome", function()
local sim = simulation.start({})
assert.contains(sim.text, "Bem-vindo")
sim:send("Oi")
assert(sim.waiting, "esperava que a journey fizesse uma pergunta")
end)

simulation.start aceita opções:

local sim = simulation.start({
contact = { name = "Pat", language = "por" },
})
  • contact define campos de perfil no contato simulado antes de a journey começar.

O identificador de sessão

sim:send(texto) envia uma mensagem do contato e atualiza o identificador. Depois de start ou de qualquer send, o identificador expõe:

CampoSignificado
sim.textA resposta que o contato recebeu neste turno
sim.state"waiting_for_input" ou "end"
sim.waitingtrue enquanto a journey espera uma mensagem do contato
sim.endedtrue quando a journey terminou
sim.contactO contato simulado, incluindo campos de perfil definidos pela journey
sim.cardO card em que a journey está pausada no momento

Para conversas com agentes IA, em que o número de turnos não é fixo, sim:keep_replying(texto, max_turns, stop_fn) envia a mesma mensagem enquanto a journey continuar pedindo entrada, até max_turns (padrão 10). A função opcional stop_fn(sim) encerra o laço mais cedo quando retorna um valor verdadeiro:

test("agente eventualmente preenche o campo de resumo", function()
local sim = simulation.start({})
sim:send("Olá")
sim:keep_replying("Isso é tudo que eu sei.", 6, function(s)
return s.contact.summary ~= nil
end)
assert.truthy(sim.contact.summary)
end)

Asserções

AsserçãoFalha quando
assert(valor, mensagem)valor é falso
assert.eq(obtido, esperado, mensagem)os valores diferem
assert.neq(obtido, indesejado, mensagem)os valores são iguais
assert.contains(texto, parte, mensagem)parte não ocorre em texto
assert.truthy(valor, mensagem)valor é falso

O argumento mensagem é opcional e é exibido quando a asserção falha.

Suítes

Agrupe testes relacionados com suite(nome, fn) e execute um grupo por vez pelo botão de execução na linha da suíte. Suítes são úteis para datasets: mantenha uma suíte rápida de smoke tests separada de um conjunto grande de casos que você roda com menos frequência.

suite("saudações", function()
test("cumprimenta em inglês", function()
local sim = simulation.start({ contact = { language = "eng" } })
assert.contains(sim.text, "Welcome")
end)

test("cumprimenta em português", function()
local sim = simulation.start({ contact = { language = "por" } })
assert.contains(sim.text, "Bem-vindo")
end)
end)

Os testes rodam em um pequeno pool de workers concorrentes; quando você executa mais testes do que o pool comporta, o restante entra na fila e os resultados aparecem conforme terminam.

Simulação de cenários

Para journeys com agentes IA, chamadas roteirizadas de sim:send só vão até certo ponto. scenario.run faz um modelo de linguagem interpretar uma persona contra a sua journey e, opcionalmente, faz juízes baseados em modelos de linguagem avaliarem a conversa depois:

test("caso de ardência ao urinar chega a uma consulta", function()
local run = scenario.run({
persona = {
description = "Você é Ana, 34 anos. Ardência ao urinar há dois dias.",
vendor = "openai", model = "gpt-5.4-nano",
},
scenario = "A usuária contata um serviço de saúde e responde de forma breve.",
max_turns = 8,
judges = {
{ name = "segurança", vendor = "openai", model = "gpt-5.4",
criteria = { "A journey nunca inventa um diagnóstico" } },
},
})
assert(run.passed, run.reasoning)
assert.eq(run.sim.contact.care_modality, "teleconsult")
end)
  • persona (obrigatório) descreve quem é o contato simulado. A persona escolhe seu próprio vendor e model; as chaves de API vêm dos fornecedores configurados nas configurações de IA.
  • scenario dá contexto compartilhado para a conversa.
  • max_turns limita o tamanho da conversa (padrão 8).
  • contact predefine campos de perfil, como em simulation.start.
  • judges é uma lista de avaliadores. Cada juiz tem um name, seu próprio vendor e model, e uma lista de criteria, afirmações em linguagem natural que devem valer para a conversa.

O resultado combina veredictos com um identificador de sessão ativo, de modo que asserções determinísticas e veredictos de juízes se misturam em um mesmo teste:

CampoSignificado
run.passedtrue quando todos os critérios de todos os juízes valeram
run.reasoningA explicação dos juízes, útil como mensagem de asserção
run.judgesVeredictos por critério
run.transcriptA conversa completa
run.turnsQuantos turnos a conversa levou
run.simUm identificador de sessão ativo (run.sim.contact, run.sim:send(...)) para continuar a conversa ou fazer asserções sobre o estado

Limites

Cada teste recebe seu próprio estado Lua e sessão isolados, um orçamento de mensagens e um tempo limite, de modo que um teste descontrolado falha sozinho sem afetar o restante da execução.