giovedì 12 settembre 2013

Il DBB per il test della componente "Server" - parte 2


Prosecuzione del post sul BDD per il test del server

Il BDD - behavior-driven development (continua)

Definito lo scenario con cucumber, come abbiamo fatto nel post precedente, è necessario definire i test di validazione delle features, che si concentreranno sul "consumo" dei webservice e non sulla tecnica di programmazione.

I punti focali di questi test sono che:
  1. possiamo farli prima di iniziare a (o a far) codificare
  2. sono indipendenti dal linguaggio con cui sarà realizzato il progetto.
Per la definizione degli step possiamo partire dagli snippet generati automaticamente da cucumber (sul sito vi sono vari tutoriarl che illustrano come codificare gli step).
In questo caso, volendo scrivere un test di controllo su come un client esterno possa consumare i servizi esposti, non verrà verificata la logica dei modelli, ma il funzionamento dei controller. 

Ad esempio nel nostro case avremo:


Given(/^a user "(.*?)" with password "(.*?)"$/) do |user, password|
 @username=user
 @password= password
end

When(/^he logs whit username and password$/) do
  header 'Accept', 'application/json' 
  header 'Content-Type', 'application/json'
  params={username: @username, password: @password}
  post 'users/sign_in', params.to_json
  page = JSON.parse(last_response.body)
  @token=page["auth_token"]
  @token.should_not == nil
end

Then(/^he should navigate page "(.*?)" and see (\d+) records$/) do |arg1, arg2|
  get arg1, {auth_token: @token}
  page = JSON.parse(last_response.body)
  page.size.should == arg2.to_i
end
 
Then(/^he should navigate page "(.*?)"$/) do |arg1|
  get arg1, {auth_token: @token}
end

Then(/^he should see olny his documents$/) do 
  get "my_documents", {auth_token: @token}
  last_response.status.should == 200 #HTTP status OK
  page = JSON.parse(last_response.body)
  page.map{|u| u["user"]["customer_name"]}.compact.uniq.should include(@user.customer_name)
end

Then(/^he shouldn't navigate page "(.*?)"$/) do |arg1|
   get arg1, {auth_token: @token}
   last_response.status.should == 403 #HTTP status forbidden
end

Questo test verificherà - indipendentemente dalla modalità di realizzazione - che il nostro server risponda a: 
- un servizio di login
- un servizio di risposta agli indirizzi customers, operators, settings, documents, che verifichi il tocken ed il profilo dell'untente , eventualmente restituendo uno stato di fobidden e che restituisca una array di record
- un servizio denominato "my_documents"

Naturalmente alcuni di questi test, come ad esempio l'autenticazione con username e password, presuppongono che il sistema sia stato popolato. Basta predisporre un passo di popolazione dell'ambiante di test, attraverso una delle 2 modalità che preferiamo (ed in funzione di cosa dobbiamo testare):

A) utilizzo degli script di avvio di cucumber, in particolare dello svript env.rb, in cui, in questo caso ho aggiunto il blocco
    Before do
      User.create(:username=>"operator1", :password=>"test1234", :role=>"operator", :email=>"operator1@mail.local")#this code is run before each scenario
      User.create(:username=>"operator2", :password=>"test1234", :role=>"operator", :email=>"operator2@mail.local")#this code is run before each scenario
      User.create(:username=>"operator3", :password=>"test1234", :role=>"operator", :email=>"operator3@mail.local")#this code is run before each scenario
      cust1=User.create(:username=>"customer1", :password=>"test1234", :role=>"customer", :customer_name=>"azienda1", :email=>"customer1@mail.local")#this code is run before each scenario
      cust2=User.create(:username=>"customer2", :password=>"test1234", :role=>"customer", :customer_name=>"azienda2", :email=>"customer2@mail.local")#this code is run before each scenario
      cust1.documents.create(document_type: "F24_init")
      cust1.documents.create(document_type: "Bilancio_init")
      cust2.documents.create(document_type: "F24_init")
      cust2.documents.create(document_type: "Bilancio_init")
    end

B) scrittura di scenari di popolazione, che utilizzeremo per i test sui servizi.


Abbiamo quindi simulato - evitando di farlo manualmente ogni volta -
- l'apertura della finestra di login
- l'inserimento di user e password "amministrative"
- la navigazione (manuale, mancando al momento i link) di 4 pagine e il conteggio de record
- il logout
- l'inserimento di user e password "utente"
- la navigazione (manuale, mancando al momento i link) di 5 pagine e il conteggio de record

Considerando che al progredire di un progetto i dati da immettere per verificare quanto abbiamo codificato aumentano esponenzialmente... siamo ancora sicuri che scrivere test in questo modo sia una perdita di tempo?