2015-11-02 15 views
14

Il problema:aspettano() senza aspettative attuali

Recentemente, mentre la revisione la nostra base di codice di test esistente, ho notato una specie pericolosa di errore di battitura/errore quando expect() è stato utilizzato senza la parte "matching":

expect(page.filters.fromDateLabel.getText(), "After"); 

sono abbastanza sicuro toEqual() stata pensata per essere usata qui:

expect(page.filters.fromDateLabel.getText()).toEqual("After"); 

Th Il problema con questo è che jasmine non fallirebbe l'aspettativa in questo caso (beh, ovviamente perché nulla era effettivamente previsto). E questo ci porta a un problema più serio - nulla è stato effettivamente testato in un caso di test - stava passando senza aspettative. Stavamo diventando un falso senso di ciò che è stato testato.

la domanda:

voglio prendere questi errori il più velocemente possibile. Come pensi che dovrei gestire il problema?

Pensieri:

  • in qualche modo riescono un banco di prova se non ci fosse aspettative fatte in esso (non so se jasmine ha nulla di simile built-in)
  • "patch" la questione expect() e un avvertimento/genera un errore se nulla è stato chiamato da parte "aspettarsi"
  • analisi statica del codice uso - definire una regola personalizzata eslint
+2

La regola pelucchi sarebbe la mia preferenza come è il meno invasivo – Phil

+0

@Phil Sono d'accordo, questo è quello che sto pensando di provare prima, poiché sembra l'opzione più semplice - + abbiamo già definito una serie di regole eslint personalizzate. In generale, mi piace anche l'opzione n. 1 - probabilmente ha senso indicare allo sviluppatore e2e che non ha effettivamente controllato nulla in un test..grazie per il punto! – alecxe

+0

@Phil e sì, in un mondo ideale, cose come questa non dovrebbero accadere dal momento che uno sviluppatore che scrive un test deve vedere il test fallito e assicurarsi che controlli ciò che doveva essere controllato. Ma gli errori di battitura e gli errori capitano a tutti: voglio solo che queste cose vengano catturate "fresche" :) – alecxe

risposta

7

La regola ESLint personalizzata fornita nella risposta è ora una parte di eslint-plugin-jasmine 1.6.0:


Old Risposta:

Ecco un custom ESLint rule ho finito con:

module.exports = function (context) { 
    return { 
    // checking "expect()" arguments 
    CallExpression: function (node) { 
     if (node.callee.name === 'expect') { 
     if (node.arguments.length > 1) { 
      context.report(node, 'More than one argument passed to expect()') 
     } else if (node.arguments.length === 0) { 
      context.report(node, 'No arguments passed to expect()') 
     } 
     } 
    }, 

    // nothing called on "expect()" 
    'CallExpression:exit': function (node) { 
     if (node.callee.name === 'expect' && node.parent.type === 'ExpressionStatement') { 
     context.report(node, 'Nothing called on expect()') 
     } 
    } 
    } 
} 

Esso controlla per 3 cose:

  • più di 1 argomento passato alla expect()
  • senza argomenti vengono passati al expect()
  • non c'era nulla invitato expect()

Ecco il campione non valida expect() usi attualmente catture:

expect(page.filters.fromDateLabel.getText(), "After"); 
expect("After"); 
expect(); 

Per quanto riguarda l'opzione # 1, non v'è in realtà abbastanza un correlato e utile ESLint regola viene già attuata e open-source da [eslint-plugin-jasmine]:

1

Tendo a pensare che la route di analisi statica sia la migliore, ma se stai cercando un modo veloce e sporco, ecco un codice che afferra le aspettative restituite da tutte le chiamate a expect e crea un proxy che tiene traccia di qualcuna delle le proprietà di aspettativa sono stati mai usati:

var unusedExpectations = new Set(); 

var originalExpect = window.expect; // Should be empty after every spec 
var expect = function() { 
    var rawExpectation = originalExpect.apply(this, arguments); 
    unusedExpectations.add(rawExpectation); // Assume unused until used 

    // Traverse expectation and its prototypes, copying all properties to 
    // our proxy object. (Note that this becomes much simpler if you have 
    // ES6 Proxy in your environment.) 

    var proxy = {} 
    for(var proto = rawExpectation; proto; proto = proto.__proto__) { 
    Object.getOwnPropertyNames(proto).forEach(function(prop) { 
     if(Object.getOwnPropertyDescriptor(proxy, prop)) 
     return; 
     Object.defineProperty(
     proxy, prop, { 
      get: function() { 
      // Aha! Somebody used this expectation for _something_. 
      unusedExpectations.delete(rawExpectation); 
      return rawExpectation[prop]; 
      } 
     } 
    ); 
    }); 
    } 
    return proxy; 
} 

Metti che in un posto dove si nasconde Jasmine expect dalle vostre specifiche, e quindi:

beforeEach(function() { 
    unusedExpectations.clear(); 
}); 
afterEach(function() { 
    expect(unusedExpectations.size).toEqual(0); 
}); 

Avvertenze:

  1. Tipo di male.
  2. Non prenderà expect(foo).toBeFalsy; (parenti mancanti).
  3. Conta l'uso di qualsiasi proprietà, quindi non catturerà expect(foo).toString().

Ancora, funziona!

Uno potrebbe aggiungere codice per ispezionare la traccia dello stack ed estrarre la posizione del file offendente expect(), ma immagino che contrassegnare quale specifica abbia uno expect() non utilizzato è sufficiente.

+0

Questa è un'idea malvagia interessante! :) Lo proverò sicuramente in pratica! Ho anche pubblicato delle soluzioni all'opzione n. 1 e n. 3 - immagino di avere una sorta di immagine completa qui ora con tutti i diversi approcci. Grazie! – alecxe

Problemi correlati