logo

Testando suas API's com Frisby.js

Eu não sei vocês, mas eu só gosto de usar o SOAPUI para testes manuais e só automatizo tarefas nele quando é realmente necessário.

Tanto é que eu prefiro automatizar serviços SOAP usando bibliotecas java como jaxrs (que faz o import da assinatura lindamente e monta toda a estrutura de classes e métodos para você) mas para serviços REST eu estava na mão.. até agora :)

cut the crap..

Achei essa jóia chamada frisby.js que é pacote para node.js e trabalha junto com o maravilhoso jasmine.js para realizar testes de serviço REST.

Basicamente você precisa ter instalado no seu ambiente de teste:

node.js

jasmine-node

frisby

Se você não viveu debaixo de uma rocha nos últimos anos, deve saber que node.js é um application server baseado no google v8 para interpretar javascript no lado do servidor.

Para isso você precisa voltar a aprender javascript (o que não é tão dolorido assim) e entender como funciona a biblioteca do frisby e do jasmine.

for dummys

Se você é usuário de windows ou mac, pode começar por acessar o site http://nodejs.org/ e fazer o download da última versão estável e instalar na sua máquina no jeito clássico do windows NEXT, NEXT, FINISH.

Já para usuários linux, dependendo da sua distribuição, um apt-get install nodejs resolve.

Seria bom você adicionar um repositório privado para sempre pegar a última versão do node

sudo add-apt-repository ppa:chris-lea/node.js

Daqui pra frente, tudo será feito através de linha de comando no console, seja windows, mac ou linux (para delírio dos tester não técnicos de plantão..rs).

Para ter certeza que tudo está ok, veja as versões do nodejs e do npm (gerenciador de pacotes do nodejs que vem junto na brincadeira)

comandos para verificar status

Se o npm não tiver vindo junto com o pacote (isso pode acontecer para usuários linux, outro apt-get install npm resolve

setup!

O sistema de pacotes do node.js funciona em 2 níveis: Global e Local.
Para nosso projeto de teste com frisby.js precisamos de pelo menos o Jasmine-node a nivel global pois precisamos do nome reservado que ele gera.

npm install -g jasmine-node

versão do jasmine-node

Se der tudo certo você vai conseguir ver a versão do jasmine-node da mesma forma que viu a versão do nodejs e do npm.

A documentação do frisby pede para instalar ele globalmente, o que não custa nada:

npm install -g frisby

Agora você tem tudo que precisa para começar um projeto de teste das suas API's REST...

Ué, mas como eu faço para escrever meus códigos?

Você pode usar papel de pão, notepad do windows, nano do linux, vim, notepad++, sublime.. ou qualquer IDE por ai em que você possa escrever javascript.

Eu prefiro o sublime text v3 http://www.sublimetext.com/3 que não é free, mas só te lembra disso a cada 5 processos de salvar

Mão na massa de verdade

Crie uma pasta que vai conter seu projeto de teste e depois crie um arquivo de teste chamado package.json que vai conter as informações basicas do seu projeto e suas dependências (Todo projeto em node precisa do package.json)

{
"name": "rest_test",
"author": "Leonardo Galani",
"main": "meu_projeto_de_teste_spec.js",
"version": "0.0.1",
"dependencies": {
    "frisby": "latest",
    "jasmine-node": "latest"
    }
}

Percebeu que existe um paramêtro chamado main no package.json? esse é arquivo principal do seu projeto, mas isso não quer dizer que todos seus testes tem que ficar neste arquivo. Ele existe mais para que o NPM entenda qual arquivo deva executar quando você chamar npm start coisa que não iremos fazer para nossos testes.

Atenção: Todos os arquivos de teste devem conter o final _spec.js pois só assim o jasmine-node vai entender o que executar.

A documentação base usa a API do twitter e tem alguns exemplos com a API do facebook... mas tem coisas que precisa autenticar e tem gente que não pode acessar o Twitter ou o Facebook do trabalho, sendo assim eu desenvolvi uma API ridícula para para mostrar o funcionando do frisby.

o endereço da API é esse aqui --> http://apifrisbypost.keeptesting.com.br/user
(não adianta sair fazendo teste de stress, invasão que não vai rolar.. é coisa simples e o forever reinicia a aplicacão de tempos em tempos... :P )

Bom.. vamos criar o arquivo meu_projeto_de_teste_spec.js na pasta e começar com essa linha:

var frisby = require('frisby');

É padrão do node instanciar as libs que vamos usar desta forma.

Para nosso exemplo de teste, irei fazer um processo de POST e GET e se você não estiver muito familiarizado com os métodos HTTP, sugiro que leia esse post: http://pt.stackoverflow.com/questions/9419/quais-s%C3%A3o-os-m%C3%A9todos-de-requisi%C3%A7%C3%A3o-http-e-qual-%C3%A9-a-diferen%C3%A7a-entre-eles

Depois de instanciar o frisby, vamos fazer nosso teste de POST

frisby.create('Criando Novo Usuário')
  .post('http://apifrisbypost.keeptesting.com.br/user'
    ,{ email: 'leo@leonardo.com.br'}
    ,{ json: true }
    ,{ headers: { 'Content-Type': 'x-www-form-urlencoded' }})
  .expectStatus(200)
  .expectHeaderContains('content-type', 'application/json')
  .expectJSONTypes({
    _id: String,
    email: String
  })
  .expectJSON({
    email: "leo@leonardo.com.br"
  })
.toss();

Não se assuste.. é mais simples do que parece..

Antes de continuar, você tem que estar familiarizado com a idéia de estado/contexto (http://www.dofactory.com/javascript/state-design-pattern) e o conceito de corrente do javascript, coisa que o jquery faz bem (http://www.w3schools.com/jquery/jquery_chaining.asp).

Para entender melhor esse teste vou cortar em blocos o código em cada ponto da corrente e fazer alguns comentários.

Começamos então por criar o teste própriamente dito:

frisby.create('Criando Novo Usuário')

Depois definimos como será o método HTTP e qual o endereço:

  .post('http://apifrisbypost.keeptesting.com.br/user'

Dentro do método post eu estou utilizando os paramêtros url, corpo do request , identifição se é um JSON, header { Content Type do Request }

,{ email: 'leo@leonardo.com.br'}
,{ json: true }
,{ headers: { 'Content-Type': 'x-www-form-urlencoded' }})

Depois disso começa minha primeira validação para esse request:

.expectStatus(200)

HTTP 200 quer dizer que o request foi feito com sucesso e que o serviço está funcionando, mas não quer dizer que o request foi processado.

Use essa validação para saber se o serviço está disponível.

Minha segunda validação é para verificar o header e neste caso estou validando se o retorno do serviço está no formato JSON:

.expectHeaderContains('content-type', 'application/json')

A terceira validação se refere ao formato do json retornado pelo serviço e os tipos de cada paramêtro:

.expectJSONTypes({
    _id: String,
    email: String
  })

(Restify tem os ID's criados automaticamente em memoria como strings.. não pergunte por que.. eu não quero saber agora...rs).

A última validação deste teste é para verificar o conteúdo do json de retorno:

  .expectJSON({
    email: "leo@leonardo.com.br"
  })

Bem simples né?

Para fechar o método e mandar o frisby utilizar esse teste, o método .toss() deve ser invocado no final do cenário de teste.

Outro Exemplo

Fizemos o POST agora faremos o GET:

frisby.create('Buscando Usuário Criado')
    .get('http://apifrisbypost.keeptesting.com.br/user/1')
    .expectStatus(200)
    .expectHeaderContains('content-type', 'application/json')
    .expectJSONTypes({
        _id: String,
        email: String
    })
    .expectJSON({
        email: "leo@leonardo.com.br",
    })
.toss();

A única diferença desse teste é que ele usa o método GET para pegar o usuário que eu acabei de criar e não tem nenhum paramêtro no método além da própria URL (com o paramêtro).

Ok.. você criou um usário e como vc vai saber o ID criado? Não da para usar json de retorno como parametro para um próximo teste?

Dá sim :)

Para isso que existe o método afterJSON() que dentro de um teste, ele usa o json de retorno e chama outro teste.

Segue exemplo desses 2 testes combinados:

frisby.create('Criando Outro Usuário')
  .post('http://apifrisbypost.keeptesting.com.br/user', { email: 'leo@keeptesting.com.br' },{ json: true }, { headers: { 'Content-Type': 'x-www-form-urlencoded' }})
  .expectStatus(200)
  .expectHeaderContains('content-type', 'application/json')
  .expectJSONTypes({
    _id: String,
    email: String
  })
  .expectJSON({
    email: "leo@keeptesting.com.br",
  })
  .afterJSON(function(json) {
    // Agora posso juntar o teste dp GET
    frisby.create('Validando usuário Criado')
      .get('http://apifrisbypost.keeptesting.com.br/user/' + json._id)
      .expectJSON({
        email: "leo@keeptesting.com.br",
    })
    .toss()
  })
.toss();

PS: Para cada request, o método .toss() deve ser chamado

Executando seus testes

Para executar os testes basta chamar o jasmine-node e o nome do arquivo de teste ou \nomeDaPasta onde os testes se encontram:

resultado<em>jasmine</em>node.jpg

Espero que eu tenha sido claro.
Erros de pt-br estão sendo revisados e corrigidos.. e caso vocês tenham alguma sugestão, dúvida ou critica sobre o post, mande nos comentários :)


Sobre o Autor: Leonardo Galani é Agile Tester, dev, gamer, dj and etc. Mantém o fórum http://agiletesters.com.br | http://leonardobg.com.br (profile)| http://lazytester.com (blog em inglês)
http://br.linkedin.com/in/leonardogalani/

comments powered by Disqus