Advanced Guides
Integração de Testes Automatizados no Cloud do Back4App
36 min
como integrar testes nas suas funções de código cloud do parse introdução este é um guia escrito por https //github com/considine , nosso escritor convidado e desenvolvedor principal na https //koptional com/ o tutorial cobre como configurar testes automatizados para o seu código cloud do back4app vamos falar brevemente sobre como mover parte do seu código cliente do parse para a nuvem, e depois sobre como integrar seu projeto a um ecossistema de testes você também pode conferir o projeto de exemplo https //github com/back4app/template cloud code unit test diretamente para uma versão funcional objetivos esperamos combinar os aspectos robustos e escaláveis dos testes automatizados com o ambiente parse amigável para desenvolvedores ao aproveitar o cloud code, talvez um recurso subestimado do parse, os desenvolvedores podem continuar a iterar rapidamente seu código e ter confiança de que o software funcionará como esperado desenvolvimento orientado a testes https //en wikipedia org/wiki/test driven development é um campo imenso; em vez de falar filosoficamente sobre testes, vamos passar por uma implementação e discutir algumas estratégias (como stubbing, por exemplo) pré requisitos para completar este tutorial, você precisa um aplicativo no back4app siga o tutorial criar novo app para aprender como criar um aplicativo no back4app back4app command line configurado com o projeto siga o tutorial configurando o cloud code para aprender como configurar o código em nuvem para um projeto npm instalado na sua linha de comando nota esta biblioteca usará o https //www promisejs org/ , que não deve ser muito complicado vamos criar um backend básico de mídia social ok! imagine um aplicativo de mídia social que inclui um modelo de perfil para acompanhar o modelo de usuário para alguns aplicativos, você pode colocar informações de perfil no modelo de usuário, embora em muitos casos isso não seja eficiente; você frequentemente precisará separar as preocupações de autorização/autenticação do conteúdo do usuário e, assim, manter dois modelos diferentes neste tutorial, implementaremos um recurso que gerencia a criação de usuários e perfis dessa forma, colocando uma carga mínima no cliente vamos começar! 1\ definindo nossas funções isso assume que você tem um projeto back4app criado e a ferramenta de linha de comando instalada (veja os pré requisitos) para exemplos de código frontend, este guia se referirá à sintaxe do sdk javascript do parse para simplicidade quando alguém se inscreve neste aplicativo, um perfil deve ser criado e vinculado ao objeto do usuário a função de inscrição em muitas aplicações parse, você criará o usuário com a seguinte sintaxe 1 var user = new parse user(); 2 user set("username", "my name"); 3 user set("password", "my pass"); 4 user set("email", "email\@example com"); no nosso caso, gostaríamos também de inicializar um perfil e apontá lo para o objeto usuário parse server 3 x 1 try { 2 await user signup(null, {usemasterkey true}); 3 let profile = parse object extend("profile"); 4 let profile = new profile({ 5 firstname params firstname, 6 lastname params lastname, 7 user user 8 }) 9 return profile save(null, {usemasterkey true}); 10 } catch (err){ 11 return (err message); 12 } parse server 2 x 1 user signup(null, { 2 success function (newuser) { 3 var profile = parse object extend("profile"); 4 var profile = new profile(); 5 profile set("firstname", "john"); 6 profile set("lastname", "smith"); 7 profile set("user", newuser); 8 profile save(); 9 }, 10 error function (err) { 11 // handle error 12 } 13 }) você poderia encurtar essa sintaxe para algo como isto parse server 3 x 1 let user = new parse user({ 2 username params username, 3 password params password, 4 email params email 5 }); 6 7 try { 8 await user signup(null, {usemasterkey true}); 9 let profile = parse object extend("profile"); 10 let profile = new profile({ 11 firstname params firstname, 12 lastname params lastname, 13 user user 14 }) 15 return profile save(null, {usemasterkey true}); 16 } catch (err){ 17 return (err message); 18 } parse server 2 x 1 var user = new parse user({ 2 username params username, 3 password params password, 4 email params email 5 }); 6 user signup(null) 7 then((newuser) => { 8 var profile = parse object extend("profile"); 9 var profile = new profile({ 10 "firstname" "john", 11 "lastname" "smith", 12 "user" newuser 13 }); 14 return profile save(); 15 }) infelizmente, isso ainda envolve fazer duas solicitações separadas ao parse server, o que é ineficiente para um frontend; é prudente evitar fluxos de comunicação cliente servidor de múltiplas etapas quando possível além disso, em relação à segurança, o código acima está colocando o processo de criação nas mãos de um cliente, o que nunca é inteligente gostaríamos de evitar que a integridade dos nossos dados dependesse de um cliente completar corretamente todas as etapas de um fluxo eles poderiam, por exemplo, enviar uma solicitação personalizada que cria um usuário sem perfil, corrompendo os dados persistentes do aplicativo por que não fazer tudo isso em um passo usando código em nuvem? isso pode evitar o inchaço do código do frontend e garantir que o cliente não esteja fazendo trabalho desnecessário/inseguro! aqui está o que queremos fazer em vez disso do cliente para se inscrever 1 parse cloud run('signupuser', 2 { 3 username 'myname', 4 password "mypass", 5 email "email\@example com", 6 firstname "john", 7 lastname "smith" } 8 ) then(function(newuser) { 9 10 }); parse também define para http //docs parseplatform org/cloudcode/guide/#beforesave triggers gatilhos, permitindo a criação do perfil quando o usuário se inscreve no entanto, ao usar uma função, podemos passar intuitivamente os atributos firstname e lastname que o perfil usará função de inscrição de código em nuvem vamos começar! mova se para o diretório do seu projeto que está sincronizado com o back4app (veja os pré requisitos se você não souber o que isso significa) vamos assumir a seguinte estrutura no nosso caso, ao inicializar, escolhemos ‘nuvem’ como nosso nome de diretório seu diretório pode ser chamado como você quiser parse server 3 x main js 1 parse cloud define("signuserup", async(request) => { 2 // make sure the necessary parameters are passed first 3 let params = request params; 4 if (!params username || !params email || !params password || !params firstname || !params lastname) 5 throw new error("missing parameters need username, email, password, firstname, & lastname"); 6 7 // execute the signup flow 8 let user = new parse user({ 9 username params username, 10 password params password, 11 email params email 12 }); 13 14 try { 15 await user signup(null, {usemasterkey true}); 16 let profile = parse object extend("profile"); 17 let profile = new profile({ 18 firstname params firstname, 19 lastname params lastname, 20 user user 21 }) 22 return profile save(null, {usemasterkey true}); 23 } catch (err){ 24 return (err message); 25 } 26 }); parse server 2 x main js 1 parse cloud define("signuserup", function(request, response) { 2 // make sure the necessary parameters are passed first 3 var params = request params; 4 if (!params username || !params email || !params password || !params firstname || !params lastname) 5 return response error("missing parameters need username, email, password, firstname, & lastname"); 6 7 // execute the signup flow 8 var user = new parse user({ 9 username params username, 10 password params password, 11 email params email 12 }); 13 user signup(null, {usemasterkey true}) 14 then((newuser) => { 15 var profile = parse object extend("profile"); 16 var profile = new profile({ 17 firstname params firstname, 18 lastname params lastname, 19 user newuser 20 }) 21 return profile save(null, {usemasterkey true}); 22 }) 23 then((prof) => response success(prof)) 24 catch((e) => { 25 response error(e message); 26 }) 27 }); você pode notar a opção ‘usemasterkey’ sendo passada; isso permite que o código da nuvem supere quaisquer funções ou acls que possam estar em vigor como o cliente não toca neste código, não há risco de eles sequestrarem nosso servidor no entanto, por favor, tenha cuidado com esta flag! caso não esteja óbvio por que isso pode ser preferível a colocar essa funcionalidade no código do cliente, aqui estão algumas vantagens descarrega a computação para o servidor em vez do dispositivo define explicitamente a funcionalidade de um processo mais fácil criar funções à prova de falhas dá ao cliente uma interface intuitiva isso previne a possibilidade de que um cliente ‘faça metade’ de um processo 2\ refatorando nossa estrutura de diretórios ótimo, criamos duas funções em nuvem obviamente, poderíamos testar essas funções executando as e verificando o painel do parse, mas isso não é escalável ou eficiente em vez disso, queremos criar testes automatizados especificamente para os métodos que podem ser executados continuamente portanto, vamos separar um pouco nosso código vamos mover as funções que criamos em main js para um novo arquivo chamado cloud functions js (no mesmo diretório) então, vamos importar essas funções para o main e vinculá las às definições de função em nuvem a ideia é desacoplar as funções da interface em nuvem para que possamos testá las sem enviar requisições http de forma ineficiente isso fará muito sentido à medida que criamos a suíte de testes criar o arquivo de funções você pode estar ciente de que pode usar ‘require’ no node js para puxar funções, objetos e variáveis de outros arquivos assim, definiremos funções correspondentes à função em nuvem do parse que criamos na etapa 1 um ponto que pode ser confuso é que as funções que estamos definindo serão funções de retorno , que podem ser conectadas à definição da nuvem do parse pode parecer estranho usar uma função para retornar uma função, mas isso nos dará o poder de trocar servidores parse mais tarde, quando estivermos escrevendo nossos testes você pode ter notado que pode usar o objeto parse em seu código em nuvem, sem nunca precisar defini lo ou importá lo isso se deve ao servidor que executa esse código adicionando o parse automaticamente no entanto, se quisermos executar testes nas funções localmente, não temos uma instância disponível na verdade, gostaríamos de fornecer nossa própria instância que corresponda a um servidor de teste do parse, onde não há problema em dados serem criados ou excluídos então, cada função aceitará ‘parse’ como um parâmetro e retornará as funções em nuvem parse server 3 x cloud functions js 1 // cloud functions js 2 module exports signupuser = function(parse) { 3 return async(request) => { 4 // copied from main js 5 // make sure the necessary parameters are passed first 6 let params = request params; 7 if (!params username || !params email || !params password || !params firstname || !params lastname) 8 throw new error("missing parameters need username, email, password, firstname, & lastname"); 9 10 // execute the signup flow 11 let user = new parse user({ 12 username params username, 13 password params password, 14 email params email 15 }); 16 17 try { 18 await user signup(null, {usemasterkey true}); 19 let profile = parse object extend("profile"); 20 let profile = new profile({ 21 firstname params firstname, 22 lastname params lastname, 23 user user 24 }) 25 return profile save(null, {usemasterkey true}); 26 } catch (err){ 27 return (err message); 28 } 29 } 30 } parse server 2 x cloud functions js 1 // cloud functions js 2 module exports signupuser = function(parse) { 3 return function (request, response) { 4 // copied from main js 5 // make sure the necessary parameters are passed first 6 var params = request params; 7 if (!params username || !params email || !params password || !params firstname || !params lastname) 8 return response error("missing parameters need username, email, password, firstname, & lastname"); 9 // execute the signup flow 10 var user = new parse user({ 11 username params username, 12 password params password, 13 email params email 14 }); 15 user signup(null, {usemasterkey true}) 16 then((newuser) => { 17 var profile = parse object extend("profile"); 18 var profile = new profile({ 19 firstname params firstname, 20 lastname params lastname, 21 user newuser 22 }) 23 return profile save(null, {usemasterkey true}); 24 }) 25 then((prof) => response success(prof)) 26 catch((e) => { 27 response error(e message); 28 }) 29 } 30 } no main js, remova tudo antes importe a função em nuvem e vincule a função à definição da função em nuvem assim 1 // main js 2 var cloudfunctions = require(" /cloud functions"); 3 // note that we are injecting the parse instance, which is automatically supplied in the 4 // context of parse cloud code, but not on local tests 5 parse cloud define("signuserup", cloudfunctions signupuser(parse)); ótimo! não mudamos a funcionalidade desde o passo 1, mas desacoplamos a função do código em nuvem no próximo passo, criaremos um teste unitário! 3\ criar a suíte de testes para nossa suíte de testes, usaremos jasmine https //jasmine github io/ , o popular framework de testes no entanto, nosso código até agora é completamente agnóstico em relação aos nossos testes, então você pode usar qualquer framework ou plataforma que preferir vamos instalar o jasmine e o jasmine node (uma integração do jasmine com nosso ambiente node js) agora vamos instalar duas bibliotecas que nossa suíte de testes usará ela usará o sdk parse para se conectar a um servidor parse falso e a biblioteca de eventos para simular o objeto de requisição agora, usando a ferramenta jasmine, vamos inicializar nosso diretório de testes se preferir, você pode instalar o jasmine globalmente com $ npm install g jasmine $ npm install g jasmine , então você pode inicializar com este $ jasmine init $ jasmine init este guia assumirá que você não instala o jasmine globalmente, embora seja recomendado se você o fizer, pode substituir todas as instâncias de ‘/node modules/jasmine/bin/jasmine js’ por simplesmente ‘jasmine’ isso deve criar um diretório chamado spec, que inclui uma pasta de suporte contendo informações de configuração para o jasmine por padrão, o jasmine sabe procurar arquivos que terminam com a extensão “ spec js”, então nomearemos nossos testes de acordo crie o arquivo para nosso primeiro teste unitário adicione um diretório de utilitários com dois arquivos que ajudarão em nossos testes finalmente, crie um arquivo de constantes no mesmo diretório a utilidade para este arquivo será explicada mais tarde aqui está como seu diretório deve parecer agora 4\ troca por um servidor parse de teste testando com o parse como nossos métodos envolvem um servidor parse, queremos ser capazes de testar essa interação existem duas maneiras de fazer isso a podemos "stub" o objeto parse sdk, definindo um objeto que implementa a mesma interface em seguida, basta passar esse objeto como parâmetro para nossos métodos em nuvem isso pode parecer algo assim 1 var parsestub = { 2 // make sure all used methods and properties are defined 3 user function () { 4 // constructor function 5 this set = function (key, val) { 6 // logic here to implement the parse object set 7 } 8 } 9 } 10 signupuser(parsestub); // returns cloud function that we can test b outra abordagem é configurar um verdadeiro parse server que servirá apenas para dados de teste isso envolverá a camada http lenta que o parse usa, mas também nos permitirá testar os dados no banco de dados em nossos testes, precisaríamos importar o parse sdk e configurá lo com um servidor de teste os dois lugares que podem ser stubados ao testar o código em nuvem a ) stub um parse sdk que não fará requisições http, ou b ) trocar por uma implementação de banco de dados de teste nenhuma dessas abordagens é a resposta "certa" depende do que você está tentando testar stubando a interface para o parse sdk (mesmo apenas as partes que estamos usando) é muito trabalho além disso, vamos testar a persistência de dados após salvar neste exemplo, então usaremos a segunda abordagem vamos criar um servidor parse de teste no back4app obter o id da aplicação e a chave mestra e salvá los em nosso arquivo de constantes inicializar o parse sdk em nosso arquivo de especificação, para que nosso teste use o servidor de teste você é bem vindo para executar um parse server https //github com/parse community/parse server local para seus testes nós simplesmente criaremos outro aplicativo back4app em nosso painel se você precisar de um lembrete sobre como provisionar outro servidor back4app, vá até o tutorial criar novo app https //www back4app com/docs/get started/new parse app chame seu aplicativo como quiser, embora possa ser sábio usar algo como testbackend então, basta pegar o id da aplicação e a chave mestra do painel > configurações do app > segurança & chaves agora salve esses tokens no nosso arquivo de constantes assim 1 // /spec/constants js 2 // paste in your app id and master key where the strings are 3 module exports = { 4 application id "paste your application key here", 5 master key "paste your master key here" 6 } não coloque o id do aplicativo e a chave mestre do seu aplicativo de produção!!! estaremos deletando dados, e fazer isso pode fazer você perder dados 5\ utilitários de teste funções em nuvem são passadas como parâmetros nos objetos de requisição e resposta do express o servidor cria automaticamente esses parâmetros quando são executados na nuvem, então para nossos ambientes de teste devemos criar duplicatas este caso é mais fácil quando uma função em nuvem é chamada, dados são passados; no nosso caso, o perfil e as informações do usuário são passadas cada argumento que é fornecido é acessível a partir da propriedade request params então, se chamarmos uma função em nuvem como 1 // client code, calling parse function 2 parse cloud run('fakefunction', 3 { 4 data1 'i am data1', 5 data2 { 6 prop "nested property" 7 } 8 } 9 ); então a propriedade request params conterá os dados passados 1 // server code, running the parse function 2 console log(request params); 3 // { 4 // data1 'i am data1', 5 // data2 { 6 // prop "nested property" 7 // } 8 // } simples o suficiente, para nossos testes, ao chamar nossa função em nuvem, o primeiro argumento deve ser da forma 1 { 2 params { 3 username 'testuser', 4 firstname "john", 5 // the rest of the arguments 6 } 7 } assim, não precisamos criar um objeto simulado especial neste caso o objeto de resposta permite que o código em nuvem envie uma resposta http ao cliente representando um sucesso ou uma falha gostaríamos de saber como é chamado ao invocar a função em nuvem abaixo está um objeto simulado https //msdn microsoft com/en us/library/ff650441 aspx que permitirá que nosso teste determine se a invocação foi bem sucedida ou não se isso for confuso, não se preocupe, apenas coloque o em seu arquivo /spec/utils/response stub js 1 // /spec/utils/response stub js 2 const eventemitter = require('events'); 3 / 4 wrapper around response stub simplifies testing cloud functions that 5 employ a response parameter 6 / 7 function responsestub () { 8 this responselistener = new eventemitter(); 9 this responsestub = {}; 10 / 11 success method that cloud functions expect 12 / 13 this responsestub success = (resp) => { 14 this responselistener emit("success", resp); 15 } 16 / 17 error method that cloud functions expect 18 / 19 this responsestub error = (resp) => { 20 this responselistener emit("error", resp); 21 } 22 / 23 listens for errors and successes from stub and returns promise that resolves or rejects accordingly 24 / 25 this resolver = new promise((resolve, reject) => { 26 this responselistener on("success", (resp) => resolve(resp)); 27 this responselistener on("error", (err) => reject(err)); 28 }); 29 } 30 31 / 32 reeturns stub to feed to cloud function 33 / 34 responsestub prototype getstub = function () { 35 return this responsestub; 36 } 37 38 / 39 returns promise that will indicate the success or failure 40 / 41 responsestub prototype oncomplete = function () { 42 return this resolver; 43 } 44 45 module exports = responsestub; em resumo, esta função construtora em javascript fornecerá uma maneira para nosso teste passar um objeto de resposta que indica pela resolução / rejeição da promise se a função em nuvem teria retornado um sucesso ou um erro limpando o banco de dados obviamente, não queremos que nosso banco de dados parse de teste mantenha o que é acumulado durante um teste vamos definir uma utilidade para limpar tabelas de banco de dados, que pode ser chamada antes (ou depois) dos casos de teste adicione o seguinte a ‘spec/utils/purge parse table js’ 1 // spec/utils/purge parse table js 2 / 3 removes all rows from the parse database 4 @param {string} tablename the name of the parse table to be purged 5 @return {promise} promise to destroy each item in the table 6 / 7 module exports = function (parse) { 8 return (tablename) => { 9 var tablequery; 10 if (tablename === "user") 11 tablequery = new parse query(parse user); 12 else tablequery = new parse query(tablename); 13 return tablequery find({usemasterkey true}) then((items) => { 14 var destroyqueue = \[]; 15 for (var i=0; i\<items length; i++) { 16 destroyqueue push(items\[i] destroy({usemasterkey true})); 17 } 18 return promise all(destroyqueue) catch((e) => {console log("error destroying " + e message)}); 19 }); 20 } 21 } depois de definir esta função, é um bom momento para lembrá lo de garantir que seu spec/utils/constants js esteja configurado para seu aplicativo parse de teste, não para seu aplicativo parse de produção isso irá deletar dados, então, por favor, confirme que este é o banco de dados vazio que você criou acima esta função aceita nosso sdk parse configurado e retorna outra função a função retornada aceita um nome de tabela e remove todos os dados da tabela parse correspondente novamente, a ideia de retornar uma função pode parecer estranha, mas permite que o teste especifique o endpoint parse e, em seguida, faça referência a uma função que limpará a tabela daquele endpoint parse incrível! agora vamos escrever nosso teste! 6\ teste se a função em nuvem enviará um erro se os parâmetros adequados não forem passados a função em nuvem depende de certos parâmetros serem incluídos e deve falhar se, por exemplo, o ‘firstname’ não for enviado vamos ter certeza estaremos editando nosso arquivo de teste (finalmente!) spec/signup user spec js aqui está o que precisa acontecer antes das definições de teste importe o sdk parse nodejs importe nossas constantes e configure o sdk parse para apontar para nosso servidor de teste importe nossa função em nuvem importe nossa utilidade “purge table” importe o objeto mock de resposta que criamos o seguinte será suficiente 1 // hook into your testing server 2 var parse = require('parse/node'); 3 var constants = require(" /constants"); 4 // head over to your parse dash board for your test server, and grab your keys swap out the strings with the place holders below 5 parse initialize(constants application key, null, constants master key); 6 // if you are running a localhost parse server, set the serverurl accordingly 7 parse serverurl = 'https //parseapi back4app com' 8 var signupuser = require(" /cloud/cloud functions") signupuser(parse); 9 var purgetable = require(" /utils/purge parse table")(parse); 10 var responsestub = require(" /utils/response stub"); agora vamos adicionar os casos de teste a introdução ao jasmine https //jasmine github io/2 1/introduction pode ajudar a entender melhor a estrutura, mas ela se parece com isso (retirada da introdução) assim, os blocos describe encapsulam suítes de teste, e os blocos ‘it’ representam casos e expectativas ao passar um parâmetro para os blocos ‘it’, você pode executar testes de forma assíncrona o teste não será concluído até que o parâmetro seja invocado assim isso é útil, pois um de nossos testes usará http, portanto, deve ser executado de forma assíncrona dessa maneira, já que usar http é um procedimento não bloqueante no nodejs além disso, jasmine permite blocos especiais dentro de suítes que podem ser executados em diferentes pontos do ciclo de vida do teste queremos deletar todas as tabelas antes de cada teste, então executaremos o código de purgação no bloco beforeeach chega de conversa, vamos adicionar um pouco de código! coloque o código abaixo no seu spec/signup user spec js, abaixo das importações que já adicionamos 1 //spec/signup user spec js 2 // imports above 3 describe("signupuser", ()=> { 4 beforeeach((done) => { 5 /// purge the user and profile tables, and then proceed 6 promise all(\[purgetable("user"), purgetable("profile")]) 7 catch((e) => fail(e)) 8 then(() => done()); 9 }); 10 it ("should reject a request to signup that does not contain all the parameters", (done) => { 11 var responsestub = new responsestub(); 12 responsestub oncomplete() 13 then(() => fail("should have failed due to invalid parameters")) 14 catch((e) => {}) 15 then(() => done()); 16 17 signupuser({ params {}}, responsestub getstub()); 18 19 }); 20 }); incrível, nosso primeiro teste está feito no bloco beforeeach, purgamos as tabelas de usuário e perfil então o primeiro caso de teste é acionado ele verifica se passar parâmetros inválidos para a função signupuser faz com que a função envie um erro ele usa o stub de resposta para garantir que a função foi rejeitada no final como ‘signupuser’ falhará, o bloco ‘then’ inicial no stub não deve ser invocado se for, então nosso teste falha! vá em frente e execute o teste usando o seguinte você deve ver a seguinte saída 7\ um teste sobre persistência de dados espero que você tenha mais um teste em você! vamos verificar que quando nossa função em nuvem é executada corretamente, nosso banco de dados estará como esperado um perfil existirá, com uma referência a um objeto usuário, ambos com os atributos esperados adicione o seguinte bloco ao nosso bloco de suíte ‘describe’ existente 1 //spec/signup user spec js 2 // inside describe 3 it ("should signup a user, and also create a profile that contains a reference to the user", (done) => { 4 var responsestub = new responsestub(); 5 var stub = responsestub getstub(); 6 signupuser({ 7 params { 8 firstname "john", 9 lastname "smith", 10 email "jsmith\@example com", 11 username "jsmith1", 12 password "secretcatchphrase1" 13 }, 14 }, 15 stub 16 ); 17 responsestub oncomplete() 18 then((resp) => { 19 var profileq = new parse query("profile"); 20 profileq equalto("lastname", "smith"); 21 return profileq find({usemasterkey true}); 22 }) 23 // check to make sure the profile we retrieve is valid 24 then((profiles) => { 25 if (profiles length === 0) throw new error("no profile's found"); 26 expect(profiles\[0] get('firstname')) tobe("john"); 27 // get the corresponding user 28 return profiles\[0] get("user") fetch({usemasterkey true}) 29 }) 30 // check to make sure the user is what we expect 31 then((user) => { 32 expect(user getusername()) tobe("jsmith1"); 33 }) 34 catch((e) => { 35 console log(e) 36 fail(e); 37 }) 38 then(() => done()); 39 }); ok, isso é muito, então vamos passar pelo que ocorre instanciamos um objeto de simulação de resposta, como no primeiro caso de teste em seguida, executamos signupuser com um par de solicitações contendo válidos parâmetros, bem como a simulação de resposta (linhas 6 16) em seguida, este código escuta o método oncomplete do objeto simulado, que retornará uma promise a promise será rejeitada se um response error for chamado, e será resolvida se um response success for chamado quaisquer rejeições farão com que a cadeia de promises pule para o bloco catch portanto, o método fail é colocado no bloco catch, pois o teste deve falhar se a promise for rejeitada a resposta da promise deve resolver para o objeto perfil uma vez que ela se resolve, iremos consultar um perfil com o mesmo sobrenome que criamos (linhas 19 21) então o teste confirma que o ‘firstname’ do perfil é o mesmo que passamos (linhas 25 26) o próximo bloco busca o objeto usuário associado ao perfil os ponteiros de objeto parse buscam separadamente, daí a necessidade de outro bloco promise finalmente, o código confirma que o usuário correspondente tem o nome de usuário que foi passado para a função signupuser então o teste termina vá em frente e execute a suíte mais uma vez vá em frente e execute o teste usando o seguinte você deve ver a seguinte saída incrível! nós escrevemos algum código em nuvem e integramos um framework de testes conclusão se você se perdeu em algum momento, ou apenas quer o código para este exemplo, vá até o repositório do github https //github com/back4app/template cloud code unit test siga as instruções para baixar e executar se algo não estiver claro, ou não funcionar, por favor, entre em contato comigo pelo meu gmail, jackconsidine3 espero que você tenha gostado deste tutorial e adquirido algum conhecimento!