Come fare BDD per CRUD?

3

Voglio capire come Behaviour Driven Development (BDD) può essere applicato alla costruzione di CRUD applicazioni.

Ho letto molto sull'argomento, ma non capisco come dovrei applicarlo. Imparo meglio con l'esempio, quindi ho creato un'applicazione mini CRUD e vorrei che qualcuno lo completasse aggiungendo i test. L'applicazione è un semplice modulo di registrazione. L'utente compila il modulo con la sua email, quindi il server lo salva nel database.

Q1. Quale comportamento dovrei testare?

Q2. Quale parte devo testare?

Ovviamente, voglio che il mio utente sia in grado di registrare la sua email. Quindi è questo il comportamento che dovrei testare? Inoltre, posso testare l'interfaccia utente? Verifica che l'email sia realmente nel database dopo la registrazione? E come faccio a testare tutto questo?

link

HTML

<h1>Registration Form</h1>
Email
<input type="text" id="email" />
<button type="button" onclick="client.register();">
  Register
</button>
<div id="error"></div>

JavaScript

/**
 * The client represents the code that runs in the browser
 */
var client = {
    register: function () {
    var email = document.getElementById('email').value;
    ajaxPost(server.register, {email: email}, function(result){
        if(result.error){
        document.getElementById('error').innerHTML = result.error;
      } else {
        document.getElementById('error').innerHTML = '';
        alert('Registration successful!');
      }
    });
  }
};

/**
 * The server represents the code that runs on the server
 */
var server = {
    /**
   * The only method the client can call
   */ 
    register: function (model) {
    var error = server.validate(model);
    if(error) return {error: error};
    else
    {
        server.saveRegistration(model.email);
      return {success: true};
    }
  },

  validate:  function (model) {
    if(!model.email) return 'An email is required';
    if(!framework.isValidEmail(model.email)) return 'This is not a valid email';
    if(server.emailExists(model.email)) return 'This email already exist';
  },

  emailExists: function(email){
    return SqlDatabase.some(x => x === email);
  },

  saveRegistration: function(email){
    SqlDatabase.push(email);
  }
};

/**
 * This is a real SQL database!
 */ 
var SqlDatabase = [];


/**
 * THe framework used by the server code.
 * This code was not created by me
 */ 
var framework = {
    isValidEmail: function(email) {
    return email && email.indexOf('@') !== -1;
  }
};

/**
 * A utility function to simulate an ajax request in this example
 * You can ignore it
 */
function ajaxPost(url, data, callback){
    var result = url(data);
  callback(result);
}
    
posta Gudradain 25.08.2018 - 05:34
fonte

4 risposte

7

I built a mini CRUD application and I would like for someone to complete it by adding the tests

Se stai facendo BDD dovresti aver definito il comportamento richiesto prima . poi ho scritto i test, poi ho creato l'app.

Quindi il comportamento sarebbe presumibilmente qualcosa di simile a:

When a user is on the register page
and types their email in the email field
and presses the register button
then the email should be saved to the database

È quindi possibile automatizzare ogni riga, ad esempio con il webdriver, mettere tutto insieme in un test, eseguire in un framework BDD (Cucumber?), che carica la pagina, inserisce l'email, fa clic sul pulsante e controlla il database per iscrizione. Se è presente il test passa.

Ora puoi scrivere la tua pagina web. man mano che aggiungi funzionalità, ogni linea del comportamento diventerà verde.

Quando l'app è completa, tutti i test sono verdi.

I presunti benefici dell'approccio sono che ..

  1. Poiché il comportamento è scritto in "plain english", il cliente può scrivere i test.
  2. Poiché i test vengono eseguiti rispetto all'app effettiva, l'interfaccia utente anziché l'unità una volta che sono verdi, l'app corrisponde alle specifiche, che è stata scritta dal cliente, quindi è impossibile avere i bug corretti! ??
  3. Poiché ogni fase del test diventa rossa o verde, sai quanto più devi fare prima di aver completato tutto il tempo.

Ovviamente ci sono alcuni difetti in là. Direi che l'approccio si riduce alla "semplice inglese", descrizione del test su più linee dei test dell'interfaccia utente.

Che non è affatto male avere, ma non è drasticamente diverso da altri approcci.

    
risposta data 25.08.2018 - 20:37
fonte
5

Requisiti

Tipicamente definirai il comportamento prima di scrivere il codice. Questi iniziano come requisiti di alto livello un po 'vaghi:

  • gli utenti non registrati dovrebbero essere in grado di registrarsi
  • gli utenti registrati dovrebbero essere in grado di accedere
  • gli utenti registrati dovrebbero essere in grado di recuperare la loro password
  • gli account utente registrati devono essere bloccati dopo X tentativi falliti di accesso
  • gli utenti non registrati non dovrebbero essere in grado di utilizzare il recupero della password per rubare la password di qualcun altro
  • quando un utente registrato effettua il login, dovrebbe avere accesso agli oggetti di loro proprietà

Comportamenti

Da questi requisiti possiamo definire comportamenti molto specifici. Ogni requisito finirà per essere implementato come uno o più comportamenti.

Ad esempio, se stai creando un'app Web, il primo punto elenco potrebbe comportare i seguenti comportamenti concreti:

  • quando non sono registrato e visito il sito, dovrei vedere un link che mi consente di registrarmi
  • quando faccio clic sul link "registrati" dovrei essere indirizzato al modulo di registrazione
  • quando compilo il modulo con informazioni valide, dovrebbe creare un account per me
  • quando sono nel modulo di registrazione, ci dovrebbe essere un modo per contattare l'assistenza clienti per aiuto

Test degli scenari

Questi comportamenti possono essere raffinati in scenari specifici nel tuo framework di test. Ad esempio:

Given I am an unregistered user
When I go to the home page
Then I am presented with a link to the registration page
So that I can become a registered user

Gli scenari precisi che crei potrebbero essere diversi per front-end diversi. Ad esempio, potresti avere diversi scenari per utenti ipovedenti, utenti mobili, utenti desktop, utenti web, utenti API, ecc.

Sommario

Si inizia con requisiti vaghi come "l'utente non registrato dovrebbe essere in grado di registrarsi", perfezionare tale comportamento con un utente specifico ("quando vado alla pagina di destinazione dovrei vedere un collegamento per registrarsi"), e da che è possibile generare scenari di test specifici per diversi dispositivi, ecc. Per un requisito si possono avere diversi comportamenti, e per ogni comportamento si possono avere diversi scenari di test.

    
risposta data 13.10.2018 - 23:10
fonte
3

Credo che tu abbia due domande separate qui. Uno è: come si può applicare BDD a un'app CRUD e il secondo è: come posso utilizzare BDD per creare una semplice app di registrazione.

  1. BDD non si presta a determinati contesti e uno di questi è la creazione di un'app CRUD pura. Per sua natura, CRUD ha quattro operazioni ben definite (per i dati del cliente forniti) e queste sono solitamente piuttosto banali. Non esiste un comportamento complesso o un linguaggio di dominio speciale. Quindi, se vuoi essere pedante - usa il vecchio TDD, o semplicemente usa una semplice libreria CRUD di cui ti fidi.

  2. Un'app di registrazione, anche se semplice, non è necessariamente un'app CRUD (e se inizi a pensarla come un'app CRUD potresti limitare la possibilità di estrarla in modo più efficace). Molto probabilmente (a seconda del business) si avrà una lingua di dominio (ad esempio Cliente, Membro, Registrazione, Limitato ecc.), Questi concetti di dominio si traducono nel codice dell'app e potrebbero potenzialmente avere un comportamento complesso.

A questo punto è importante ricordare che oltre a essere una metodologia per guidare lo sviluppo BDD è anche una forma di analisi dei requisiti. Scrivendo gli scenari di differenza che l'utente può attraversare, svilupperai anche (spesso insieme a uno stakeholder di qualche tipo) la lingua che descrive il comportamento.

Ad esempio: gli utenti del sistema potrebbero essere definiti membri (ad esempio un membro della biblioteca), l'azione che intraprendono potrebbe essere chiamata "registrazione" dall'azienda o potrebbe essere chiamata "registrazione" - è importante che questa lingua è concordata. Ci sono diversi modi in cui puoi inizialmente esplorare il comportamento della tua app (a.k.a "discovery") - la strategia più efficace che ho usato è "Event Storming" seguita da "Example Mapping". Il primo ti fornirà una sequenza temporale di comandi ed eventi, l'ultimo preciso esempio di usato.

In altre parole - non iniziare con Given / When / Then, invece estrai la timeline. Diciamo che hai una regola in cui i membri non possono prendere in prestito libri fino a 24 ore dopo la registrazione. È una regola che può essere chiarita in questo modo

A timeline:

  • Event: Jon Registered at 14:00 24/10/2018
  • Command: Jon try to borrow book "x" at 13:00 25/10/2018
  • (system logic: can book be loaned - no)
  • Outcome/Event: Jon told they cannot borrow yet

Alternate timeline:

  • Event: Jon Registered at 13:00 24/10/2018
  • Command: Jon borrow book "x" at 13:00 25/10/2018
  • (system logic: can book be loaned - yes)
  • Outcome/Event: Book "x" is loaned to Jon
  • Command: Jon return book "x" at 13:00 26/10/2018
  • (system logic: is book damaged? yes)
  • Outcome/Event: Book was "x" listed for repair 26/10/2018
  • Outcome/Command: Charge Jon £5

Ora puoi prendere sezioni della timeline e scriverle per l'automazione con uno strumento che analizza il formato Given / When / Then. Gli eventi diventano Givens, il comando diventa Whens e gli eventi di Risultato diventano Thens. Consente di prendere la prima timeline e la seconda parte della timeline alternativa.

Scenario: Not allowed to borrow a book - registration less than 24 hrs ago
    Given Jon Registered at 14:00 24/10/2018 
    When Jon tries to borrow book "x" at 13:00 25/10/2018   
    Then Jon should be told they cannot borrow any books yet
Scenario: allowed to borrow a book - registration more than 24 hrs ago
    Given Jon Registered at 13:00 24/10/2018 
    When Jon tries to borrow book "x" at 13:01 25/10/2018 
    Then book "x" should have been loaned to Jon at 13:01 25/10/2018 
Background:
    Given Jon Registered at 13:00 24/10/2018 

Scenario: Being charged for returning a book damaged and listing for repair
    Given Book "x" was loaned to Jon on 13:00 25/10/2018
    When Jon returns the book "x" at 13:00 26/10/2018   
    Then Book "x" should have been listed for repair at 13:05 26/10/2018
    And Jon should have been a £5 damage fee

Da qui è necessario automatizzare questi "scenari". Il passo Given imposterà il sistema in uno stato in cui Jon ha già ricevuto in prestito il libro (ad esempio nel database?), Il passo When eseguirà il comando (es. API? Web Form? Potrebbe essere necessario automatizzare un browser). Il passo Then controllerà che il libro sia stato elencato per la riparazione come risultato (ad es. Database di nuovo? O coda di messaggi?) E che al membro sia stata addebitata una multa. Potrebbero esserci feedback anche per il membro che vuoi far valere qui, il che potrebbe comportare anche la lettura dal browser). Seguire un approccio di tipo TDD in cui questo scenario fallirà inizialmente (poiché non è stata programmata alcuna logica aziendale).

    
risposta data 17.10.2018 - 13:05
fonte
1

Oltre alle preziose risposte di cui sopra, aggiungerei che durante la scrittura di test BDD per CURD, o in realtà per qualsiasi tipo di software, dovresti prendere in considerazione la scrittura di test positivi e negativi.

Questo è un esempio di test positivo descritto da @Bryan OaKley :

Given I am an unregistered user
When I go to the home page
Then I am presented with a link to the registration page
So that I can become a registered user

E qui ci sono esempi di test negativi:

Given I am registered but not an authenticated user
When I try to register myself with the same email I have registered with
I should get an error message that I am already registered
Given I am an authenticated user
When I go to the home page
I shouldn not be presented with a link to the registration page
risposta data 20.10.2018 - 12:35
fonte

Leggi altre domande sui tag