Translate

quinta-feira, 12 de novembro de 2020

Como testar uma Rails API com Rspec

 

Primeiramente, será apresentado como criar uma API Rest usando Rails 5.0 a partir da API de clima disponível no site https://openweathermap.org/api. Em seguida, será instalado o pacote RSpec de Rails para que seja possível executar os testes dessa API.

Pré-requisitos

Criando uma API Rest com Ruby on Rails

Para criar uma API com Rails é necessário que seja feita a instalação completa do Rails 5.0 na sua máquina.

No terminal entrar na pasta do seu workspace e digitar o comando para criar um novo projeto de API em rails:

C:/workspace>rails new climateapi --api
Observe que esse projeto difere dos outros projetos por haver o termo ‘api

Com a aplicação criada, entrar na pasta do projeto criado e digitar o comando para instalar todas as bibliotecas do projeto.

C:/workspace/climateapi>bundle install
Caso ocorra algum erro referente ao sqlite, basta alterar no arquivo /climateapi/Gemfile.
gem 'sqlite3', '< 1.4'
gem 'rack-cors'

Em seguida, executar novamente o comando ‘bundle install’.

Na pasta config adicionar ao arquivo application.rb a configuração do Cors, que autoriza essa API ser utilizada por outros sistemas. 

#adicionar esse trecho do código
config.middleware.insert_before 0, "Rack::Cors" do .. end
require_relative 'boot'
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module Climatempoapi
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
# Skip views, helpers and assets when generating a new resource.
config.api_only = true
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource(
'*',
headers: :any,
methods: [:get, :patch, :put, :delete, :post, :options]
)
end
end
end
end

Na pasta controllers /climateapi/app/controllers/api/v1 criar o arquivo clima_controller.rb

module Api
module V1
    class ClimaController < ApplicationController
def show
@host = 'http://api.openweathermap.org/data/2.5/'
@key = 'SUA_API_KEY'
city = params[:city]
@weather_city = api_request_city_weather(@host, city, @key)
puts @weather_city
render json: @weather_city
end
private
# GET API city weather from Open weather map
def api_request_city_weather(host, city, key)
require 'net/http'
require 'net/https'
require 'open-uri'
require 'json'
url_weather = host + 'weather?q=' + city + '&appid=' + key
uri = URI.parse(url_weather)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
response = http.request(request)
content = JSON.parse(response.body)
return content
end
end
end
end

Na pasta config /climateapi/config alterar o arquivo routes.rb

Rails.application.routes.draw do
namespace 'api' do
namespace 'v1' do
resources :weather, param: :city
end
end
end

Executar o comando no terminal para criar as rotas

C:/workspace/climateapi>rails routes
Controller#Action
api_v1_weather_index GET /api/v1/weather(.:format) api/v1/weather#index
POST /api/v1/weather(.:format) api/v1/weather#create
api_v1_weather GET /api/v1/weather/:city(.:format) api/v1/weather#show
PATCH /api/v1/weather/:city(.:format) api/v1/weather#update
PUT /api/v1/weather/:city(.:format) api/v1/weather#update
DELETE /api/v1/weather/:city(.:format) api/v1/weather#destroy

Em seguida, rodar a API para verificar se os dados em formato JSON foram recuperados da API Rest original.

C:/workspace/climateapi>rails s -b 0.0.0.0 -p 3050

Acessar a URL local no navegador e ver se exibe o resultado: http://localhost:3050/api/v1/weather/Aracaju

{
"coord": {
"lon": -37.07,
"lat": -10.91
},
"weather": [
{
"id": 802,
"main": "Clouds",
"description": "scattered clouds",
"icon": "03n"
}
],
"base": "stations",
"main": {
"temp": 298.15,
"feels_like": 299.58,
"temp_min": 298.15,
"temp_max": 298.15,
"pressure": 1012,
"humidity": 83
},
"visibility": 10000,
"wind": {
"speed": 4.6,
"deg": 100
},
"clouds": {
"all": 40
},
"dt": 1605072214,
"sys": {
"type": 1,
"id": 8322,
"country": "BR",
"sunrise": 1605081293,
"sunset": 1605126599
},
"timezone": -10800,
"id": 3471872,
"name": "Aracaju",
"cod": 200
}

Pronto! Sua API Rest em Ruby on Rails foi criada utilizando outro serviço de API disponível na internet.

Testando uma Rails API com Rspec

Agora que já temos uma Rails API criada, iremos instalar o rspec-rails e outras gems para que seja possível realizar os testes nessa API.

Abrir o arquivo Gemfile na raiz do mesmo projeto climateapi/Gemfile e incluir as seguintes gems na seção :test.

group :development, :test do

gem 'byebug', platform: :mri
gem 'rspec-rails', '~> 4.0.1'
gem 'factory_bot_rails'
end

Entrar na pasta do projeto criado e digitar o comando para instalar as novas bibliotecas do projeto.

C:/workspace/climateapi>bundle install

Em seguida executar o comando para geração da pasta climateapi/spec.

C:/workspace/climateapi>rails generate rspec:install

Entrar nessa pasta e criar um novo arquivo climateapi/spec/clima_spec.rb

require 'rails_helper'
describe "get weather route to Aracaju", :type => :request do
before {get '/api/v1/weather/Aracaju'}
it 'returns weather' do
expect(JSON.parse(response.body)['name']).to eq('Aracaju')
end
it 'returns status code 200' do
expect(response).to have_http_status(:success)
end
end

Em seguida, executar os testes utilizando o comando abaixo.

C:/workspace/climateapi>bundle exec rspec ./spec/weather_spec.rb

Observar que os testes passaram conforme o resultado esperado:

{"coord"=>{"lon"=>-37.07, "lat"=>-10.91}, "weather"=>[{"id"=>802, "main"=>"Clouds", 
"description"=>"scattered clouds", "icon"=>"03n"}], "base"=>"stations", 
"main"=>{"temp"=>298.15, "feels_like"=>299.58, "temp_min"=>298.15, "temp_max"=>298.15, 
"pressure"=>1012, "humidity"=>83}, "visibility"=>10000, "wind"=>{"speed"=>4.6, "deg"=>100}, 
"clouds"=>{"all"=>40}, "dt"=>1605073980, "sys"=>{"type"=>1, "id"=>8322, "country"=>"BR", 
"sunrise"=>1605081293, "sunset"=>1605126599}, "timezone"=>-10800, "id"=>3471872, 
"name"=>"Aracaju", "cod"=>200}


Finished in 1.55 seconds (files took 5.51 seconds to load)
2 examples, 0 failures

Fiz este artigo originalmente no Medium do GTSW:

https://medium.com/gtsw/como-testar-uma-rails-api-com-rspec-596d4ce39988

quinta-feira, 22 de outubro de 2020

É importante um testador de software saber programar?

Iniciei minha carreira como estagiária, no cargo de Desenvolvedora Java WEB. Acredito que isso tenha sido o ponta pé inicial para eu entender como seria o mundo real fora da universidade. Antes desse estágio, tudo era muito complexo e os projetos da universidade não pareciam ser suficientes para alguém realmente usar.

O estágio me ajudou a compreender mais as disciplinas do curso de computação. Após 2 anos como desenvolvedora Jr, surgiu a oportunidade de atuar como Líder do time de Controle de Qualidade da empresa, apesar de não ter experiência no assunto, apenas a teoria durante a graduação, aceitei, foi a melhor coisa que me aconteceu.

Durante esses anos de carreira como Analista de Qualidade, alguns estagiários me perguntavam se era necessário saber programar para ser testador. A resposta era “não”, mas gostava de deixar claro que isso não deveria ser um motivo para eles não aprenderem a programar.

Saber programar foi essencial para minha carreira como testadora de software. Pois podia prever possíveis erros nos sistemas baseados na minha experiência. Conseguia até perceber em qual camada da arquitetura do sistema os erros encontrados ocorriam. Isso tornou meus roteiros de teste mais robustos e eficientes, já que sabia que uma falha na interface poderia ocasionar erros na camada de negócio e virse versa.

Em resumo, ter conhecimento de programação pode ajudar o testador a:

  1. Entender a arquitetura do sistema
  2. Criar casos de teste baseados em lógica de programação
  3. Realizar consultas no banco de dados
  4. Identificar camada da aplicação onde a falha ocorre
  5. Realizar testes automáticos
  6. Realizar atividade de revisão de código
  7. Criar scripts de teste com Polimorfismo, permitindo o reuso de código
  8. Configurar ambiente de integração contínua
  9. Realizar controle de versão dos scripts de teste
  10. Usar objetos Mock nos scripts de teste 

Além dos motivos acima, precisamos entender que quando decidimos seguir a carreira de TI, teremos que nos atualizar constantemente. É importante estarmos sempre atentos às novas tecnologias, aos novos frameworks, às novas linguagens de programação, aos novos dispositivos, etc. Ao longo desse tempo, percebi que o teste de software tem evoluído em conjunto com as novas tecnologias.

Montei um breve histórico dessa evolução dos testes nos últimos 15 anos, que pode ser observado na tabela abaixo:



Histórico da evolução dos sistema x testes de software em 15 anos. 

Fonte dos dados históricos: Web Apps, Mobile Apps, Mock Testing, Deep Learning, SeleniumHq, JMeter, Web API, API Testing, WebServices, Microservices, Mockito, SprintBoot, Postman, Appium, Docker, CI/CD, Cypress, ReactJS, VueJS, AngularJS, Jest, Flutter Mobile.

Ao observar a evolução dos testes, na tabela acima, percebemos que cada vez mais há ferramentas de automação para testes de software, que atendem a diferentes contextos. A necessidade de automação dos testes cresce proporcionalmente à medida que novas versões dos sistemas são lançadas continuamente em processos ágeis. Isso torna cada vez mais inviável realizar, manualmente, testes de regressão nos sistemas, para garantir que o sistema continuará funcionando durante sua evolução ou manutenção.

Os testes de regressão possuem menor custo quando automatizados em maior quantidade nos níveis de testes unitários e em menor quantidade nos testes de sistema. A proporção de testes pode ser baseada na Pirâmide de Teste, sugerida por Mike Cohn.

Pirâmide de Teste para guiar a automação dos testes.

Fonte: Fowler, M. The practical test pyramid. 2018 https://martinfowler.com/articles/practical-test-pyramid.html

Um aspecto importante da pirâmide de teste é que os testes não precisam ser duplicados ou triplicados em cada camada. À medida que os testes das camadas inferiores da pirâmide já cobrem grande parte das funcionalidades do sistema, não é necessário refazer os mesmos testes nas camadas superiores.

Apesar da pirâmide de teste ser referente aos testes automatizados, os testes manuais ainda serão necessários. Pois, há cenários subjetivos que não são passíveis de automação. Alguns fatores que podem evidenciar falhas no sistema são: baixa conectividade, usabilidade, sequência de passos no sistema, entre outros.

Uma recomendação para quem está na área de testes de software é aprender técnicas de automação de testes e estudar também os novos frameworks de programação (Reativa, Mobile, API, etc). Dessa forma, esse testador terá um diferencial no mercado, além disso poderá criar casos de teste mais robustos e com maior chance de encontrar defeitos, que é o principal objetivo do seu trabalho.