Referência da API de Testes
Referência da API de Testes
O SDK da Turn.io fornece utilitários de teste abrangentes através do módulo turn.test.*. Essas funções permitem que você simule chamadas HTTP, chamadas entre apps e operações assíncronas em seus testes.
Gerenciamento de Estado
turn.test.reset()
Limpa todo o estado de teste e redefine para um estado limpo. Isso é crítico para garantir que os testes não vazem estado uns para os outros.
before(function()
turn.test.reset() -- Comece cada teste limpo
end)
Após chamar reset(), os seguintes dados de teste estão disponíveis:
- 2 contatos de teste:
contact-1econtact-2 - 2 jornadas de teste:
journey-1ejourney-2
turn.test.set_config(key, value)
Define valores de configuração para teste. Útil para testar com diferentes configurações de app.
turn.test.set_config("api_key", "test-key-123")
turn.test.set_config("webhook_url", "https://test.example.com/webhook")
turn.test.get_config(key)
Recupera um valor de configuração de teste.
local api_key = turn.test.get_config("api_key")
assert(api_key == "test-key-123")
Testes de Configuração
turn.test.set_config(key, value) e turn.test.get_config(key)
Esses métodos permitem que você teste o comportamento do seu app com diferentes configurações sem precisar modificar a configuração real do app.
describe("com configurações diferentes", function()
it("deve usar a chave API de teste", function()
turn.test.reset()
turn.test.set_config("api_key", "test-key-abc")
-- Seu app agora verá esta configuração ao chamar turn.configuration.get()
local result = app:on_event({}, number, "some_event", {})
-- Verificar que usou a chave de teste
turn.test.assert_http_called({
headers = {Authorization = "Bearer test-key-abc"}
})
end)
end)
Simulação de Requisições HTTP
turn.test.mock_http(expected_request, mock_response)
Simula uma chamada HTTP para que seu app não faça requisições de rede reais durante os testes. Isso permite testar offline e garante velocidade e confiabilidade.
turn.test.mock_http(
{
method = "GET",
url = "https://api.example.com/data",
headers = {Authorization = "Bearer secret-key"} -- Opcional
},
{
status = 200,
body = json.encode({result = "success", data = [1, 2, 3]}),
headers = {["Content-Type"] = "application/json"} -- Opcional
}
)
Parâmetros:
expected_request(tabela): A requisição esperada contendomethod,urle opcionalmenteheadersebodymock_response(tabela): A resposta simulada contendostatus,bodye opcionalmenteheaders
Dica importante: Você deve simular requisições HTTP antes de chamar o código que faz a requisição. As simulações são correspondidas exatamente, então certifique-se de que a URL, método e outros detalhes correspondam.
turn.test.assert_http_called(expected_request)
Verifica que uma chamada HTTP foi feita com os parâmetros especificados.
turn.test.assert_http_called({
method = "POST",
url = "https://api.example.com/webhook",
body = json.encode({event = "test", data = "value"})
})
Esta é uma asserção poderosa que falha se:
- Nenhuma requisição HTTP foi feita
- A requisição não corresponde aos parâmetros esperados (método, URL, corpo, etc.)
turn.test.get_http_requests()
Retorna uma tabela de todas as requisições HTTP feitas durante o teste. Útil para depuração ou verificações mais complexas.
local requests = turn.test.get_http_requests()
for i, req in ipairs(requests) do
print(string.format("Requisição %d: %s %s", i, req.method, req.url))
if req.body then
print("Corpo:", req.body)
end
end
-- Verificação personalizada
assert(#requests == 2, "Deveria ter feito exatamente 2 requisições HTTP")
Simulação de Chamadas entre Apps
turn.test.mock_app_call(app_name, event_name, mock_response)
Simula uma chamada para outro app. Útil ao testar integração entre apps sem precisar ter o outro app instalado.
turn.test.mock_app_call(
"payment_app", -- Nome do app
"process_payment", -- Nome do evento
{ -- Resposta simulada
success = true,
transaction_id = "txn_123",
amount = 100
}
)
turn.test.assert_app_called(app_name, event_name, expected_data)
Verifica que seu app chamou outro app com dados específicos.
turn.test.assert_app_called(
"payment_app",
"process_payment",
{
amount = 100,
currency = "USD",
customer_id = "cust_456"
}
)
turn.test.get_app_calls()
Retorna todas as chamadas de app feitas durante o teste.
local calls = turn.test.get_app_calls()
for i, call in ipairs(calls) do
print(string.format("Chamada de app %d: %s.%s", i, call.app, call.event))
print("Dados:", json.encode(call.data))
end
Gerenciamento de Contatos e Jornadas
turn.test.get_contact(contact_id)
Obtém um contato de teste. Após turn.test.reset(), dois contatos estão disponíveis: "contact-1" e "contact-2".
local contact = turn.test.get_contact("contact-1")
-- {id = "contact-1", phone = "+1234567890", name = "Test Contact 1"}
turn.test.create_contact(contact_data)
Cria um contato de teste personalizado.
local contact = turn.test.create_contact({
name = "John Doe",
phone = "+1234567890",
custom_field = "valor personalizado"
})
turn.test.get_journey(journey_id)
Obtém uma jornada de teste. Após turn.test.reset(), duas jornadas estão disponíveis: "journey-1" e "journey-2".
local journey = turn.test.get_journey("journey-1")
turn.test.create_journey(journey_data)
Cria uma jornada de teste personalizada.
local journey = turn.test.create_journey({
name = "test_journey",
description = "Jornada de Teste"
})
turn.test.add_message(contact, text, direction)
Adiciona uma mensagem de teste a um contato.
local contact = turn.test.get_contact("contact-1")
turn.test.add_message(contact, "Olá!", "inbound")
turn.test.add_message(contact, "Oi! Como posso ajudar?", "outbound")
turn.test.clear_contacts(), turn.test.clear_journeys(), turn.test.clear_messages()
Limpa dados de teste específicos sem redefinir tudo.
turn.test.clear_contacts() -- Remove todos os contatos de teste
turn.test.clear_journeys() -- Remove todas as jornadas de teste
turn.test.clear_messages() -- Remove todas as mensagens de teste
Testes de Lease (Operações Assíncronas)
Ao testar operações assíncronas que usam turn.leases, você pode simular aquisição e liberação de leases.
turn.test.mock_lease_acquire(lease_name, callback)
Simula a aquisição de um lease e executa um callback.
it("deve processar lote de forma assíncrona", function()
turn.test.reset()
local lease_acquired = false
turn.test.mock_lease_acquire("process_batch", function(lease_id)
lease_acquired = true
return true -- Simula aquisição bem-sucedida
end)
app:on_event({}, number, "start_batch_process", {items = 100})
assert(lease_acquired == true, "Lease deveria ter sido adquirido")
end)
turn.test.assert_lease_released(lease_id)
Verifica que um lease foi liberado corretamente.
turn.test.assert_lease_released("lease_123")
Testes de Manifest
turn.test.load_manifest()
Carrega e analisa o arquivo manifest.json do seu app.
local manifest = turn.test.load_manifest()
assert(manifest.app.name == "my_app")
assert(manifest.app.version == "1.0.0")
turn.test.assert_manifest_has(field_path)
Verifica que o manifest tem um campo obrigatório.
turn.test.assert_manifest_has("app.name")
turn.test.assert_manifest_has("app.version")
turn.test.assert_manifest_has("app.description")
turn.test.validate_manifest()
Valida a estrutura completa do manifest.
local valid, errors = turn.test.validate_manifest()
assert(valid, "Validação do manifest falhou: " .. json.encode(errors))
Testes de Logger
turn.test.get_log_messages(level)
Recupera mensagens de log capturadas durante o teste, opcionalmente filtradas por nível de log. Útil para verificar se seu app registra mensagens apropriadas.
Parâmetros:
level(string, opcional): Filtrar por nível de log ("debug","info","warning","error"). Se omitido, retorna todas as mensagens de log.
Retorna um array de entradas de log, cada uma contendo:
level(string): O nível do logmessage(string): A mensagem de logtimestamp(number): Quando o log foi registrado
-- Obter todas as mensagens de log
local all_logs = turn.test.get_log_messages()
-- Obter apenas logs de erro
local errors = turn.test.get_log_messages("error")
for _, log in ipairs(errors) do
print(log.level .. ": " .. log.message)
end
-- Obter logs de aviso
local warnings = turn.test.get_log_messages("warning")
assert(#warnings == 0, "Esperado nenhum aviso")
turn.test.assert_logged(level, pattern)
Verifica se uma mensagem correspondente a um padrão Lua foi registrada no nível especificado. Retorna true se uma entrada de log correspondente foi encontrada, false caso contrário.
Parâmetros:
level(string): O nível de log a verificar ("debug","info","warning","error")pattern(string): Um padrão Lua para corresponder às mensagens de log
-- Verificar que mensagens específicas foram registradas
turn.logger.info("Processando pedido 12345")
turn.logger.error("Falha ao conectar à API de pagamento")
-- Verificar que mensagens foram registradas
assert(turn.test.assert_logged("info", "Processando pedido"))
assert(turn.test.assert_logged("error", "API de pagamento"))
-- Correspondência de padrões funciona com padrões Lua
assert(turn.test.assert_logged("info", "pedido %d+")) -- Corresponde a "pedido" seguido de dígitos
Exemplo: Testando Comportamento de Logging
describe("Processamento de pedido", function()
before(function()
turn.test.reset() -- Limpa logs capturados
end)
it("deve registrar etapas de processamento do pedido", function()
-- Processar um pedido (código do seu app)
App.on_event(app, number, "journey_event", {
function_name = "process_order",
args = {"ORD-123", 99.99}
})
-- Verificar que logging apropriado ocorreu
assert(turn.test.assert_logged("info", "Processando pedido ORD%-123"))
assert(turn.test.assert_logged("info", "Total do pedido: 99.99"))
-- Verificar que nenhum erro foi registrado
local errors = turn.test.get_log_messages("error")
assert(#errors == 0, "Esperado nenhum erro durante o processamento")
end)
it("deve registrar erros em entrada inválida", function()
App.on_event(app, number, "journey_event", {
function_name = "process_order",
args = {nil, -100}
})
-- Verificar que erro foi registrado
assert(turn.test.assert_logged("error", "Pedido inválido"))
end)
end)
Testes com Spy
turn.test.spy(func)
Cria um spy que envolve uma função e rastreia chamadas para fins de teste. Retorna uma tabela chamável que registra todas as invocações com seus argumentos. É compatível com Luerl e não requer módulos C ou a biblioteca debug.
Parâmetros:
func(função, opcional): A função para envolver. Se nil, cria um spy sem operação.
Retorna um objeto spy chamável com:
.calls(array): Lista de registros de chamadas, cada um com.vals(array de argumentos).call_count(número): Número total de vezes que o spy foi chamado
local turn = require("turn")
-- Criar um spy envolvendo uma função
local mock_client = {
get = turn.test.spy(function(self, resource_type, id)
return {
data = {
resourceType = resource_type,
id = id,
name = "Test Resource"
}
}
end)
}
-- Chamar a função espiada
local result = mock_client:get("Patient", "patient-123")
-- Verificar chamadas
assert(mock_client.get.call_count == 1, "Esperado que get seja chamado uma vez")
assert(#mock_client.get.calls == 1, "Esperado 1 registro de chamada")
assert(mock_client.get.calls[1].vals[2] == "Patient", "Esperado tipo de recurso Patient")
assert(mock_client.get.calls[1].vals[3] == "patient-123", "Esperado ID do paciente")
-- Verificar que o valor de retorno ainda funciona
assert(result.data.id == "patient-123", "Esperado que o spy retorne o resultado real")
Use spies para verificar chamadas de função em seus testes:
describe("Cliente de API", function()
local client
before(function()
turn.test.reset()
client = {
create = turn.test.spy(function(self, resource)
return { id = "new-123" }
end),
update = turn.test.spy(function(self, id, resource)
return { id = id, updated = true }
end)
}
end)
it("deve criar e atualizar recursos", function()
-- Executar operações
local created = client:create({ name = "Test" })
local updated = client:update("new-123", { name = "Updated" })
-- Verificar que create foi chamado
assert(client.create.call_count == 1, "Esperado que create seja chamado")
assert(client.create.calls[1].vals[2].name == "Test", "Esperado dados corretos")
-- Verificar que update foi chamado
assert(client.update.call_count == 1, "Esperado que update seja chamado")
assert(client.update.calls[1].vals[2] == "new-123", "Esperado ID correto")
end)
end)