Front-End
Unit Testing
PARTE 2
WORKSHOP DE
Facundo Gaumet // Joel A. Villarreal Bertoldi
Córdoba, 4 de Mayo de 2017
¿Qué haremos?
+ COVERAGE
+ ASYNC TESTS
¿Comenzamos?
¿Qué es la cobertura?
Supongamos que se nos presenta la siguiente situación:
Dos proyectos, uno con el 95% de cobertura con tests, otro con 45%. Pagan por error encontrado. ¿En cuál te gustaría trabajar?
¿Qué tipo de cobertura?
TESTS UNITARIOS
TESTS DE ACEPTACIÓN
TESTS DE INTEGRACIÓN
Muchas herramientas miden la cobertura de sentencias, que también pueden conocerse como:
Muchas herramientas miden la cobertura de sentencias, que también pueden conocerse como:
COBERTURA DE SEGMENTOS
COBERTURA DE MÚLTIPLES CONDICIONES
COBERTURA DE RAMAS
var status = doSomething();
if (status === FATAL_ERROR) {
return 3;
}
// No errors, continue...
var status = doSomething();
if (status === FATAL_ERROR) {
return 3;
} else if (status === WARNING) {
// Recover from error.
}
// No errors, continue...
Podemos dividir el código testeado en tres categorías:
Podemos dividir el código testeado en tres categorías:
RIESGO ALTO
RIESGO MEDIO
RIESGO BAJO
class MyObject extends EventEmitter {
doSomething() {
// Alert we're going to something.
this.emit('beforeDoSomething');
// Effectively doing something.
this.x = this.x;
// Alert we've done something.
this.emit('afterDoSomething');
}
}
doSomething()
(call entry point)
event:beforeDoSomething
event:afterDoSomething
return;
this.x = this.x
¿Qué sucede en esta función?
¿Cómo probamos esto?
describe('MyObject', function() {
before(function() {
this.obj = new MyObject();
});
it('should trigger all events',
function() {
this.obj.doSomething();
}
);
});
No sirve ya que no tiene expectativas.
describe('MyObject', function() {
before(function() {
this.obj = new MyObject();
});
it('should trigger all events',
function() {
const result = this.obj.doSomething();
expect(result).to.equal(true);
}
);
});
No sirve ya que doSomething() no tiene retorno.
Además, el retorno no tiene relación con los eventos.
VAMOS PASO A PASO
describe('MyObject', function() {
before(function() {
this.obj = new MyObject();
});
it(
'should trigger "before" event',
function() {
this.obj.on('beforeDoSomething', function() {
expect('everything').to.be.ok;
});
this.obj.doSomething();
});
});
Capturando un evento con listeners
it('should trigger "before" event',
function(done) {
myObject.on('beforeDoSomething',
function() {
done();
}
);
myObject.doSomething();
});
Capturando un evento con listeners: CALLBACKS
doSomething()
(call entry point)
event:beforeDoSomething
event:afterDoSomething
return;
this.x = this.x
Callback Testing
done()
it('should trigger all events in the cycle',
function(done) {
let calledBefore = false;
myObject.on('beforeDoSomething',
() => { calledBefore = true; });
myObject.on('afterDoSomething',
() => { if (calledBefore) { done(); } });
myObject.doSomething();
});
Patrón de múltiples eventos con un callback
doSomething()
(call entry point)
event:beforeDoSomething
event:afterDoSomething
return;
this.x = this.x
Callback Testing
calledBefore = true
calledBefore ? done() : Error
it('should trigger all events in the cycle',
function() {
const test = new Promise((resolve, reject) => {
let before = false;
myObject.on('beforeDoSomething',
() => { before = true });
myObject.on('afterDoSomething',
() => before ? resolve : reject);
});
return test()
.then(() => ...)
.catch(() => ...);
});
Captura de eventos + Promise Pattern
doSomething()
(call entry point)
event:beforeDoSomething
event:afterDoSomething
return;
this.x = this.x
Promise-Based Testing
before = true
before ? resolve() : reject()
Captura de eventos + Async/Await Pattern
!
IMPLEMENTACIÓN
NO ESTABLE
Captura de eventos + Async/Await Pattern
class MyAsyncObject {
getItem(id) {
return request(`/items/${id}`);
}
}
Captura de eventos + Async/Await Pattern
it('should return an item with
the given ID', async function() {
const item = await myObj.getItem(1);
expect(item.id).to.equal(1);
});
Es sencillo conseguir un 100% de cobertura, pero lo difícil es probarlo todo.
Las herramientas de cobertura son útiles, siempre y cuando las usemos para fomentar el pensamiento lógico, no reemplazarlo.
¿Preguntas?
¡Muchas gracias!
Front-end Unit Testing Workshop, 2ª Parte
By Joel Alejandro Villarreal Bertoldi
Front-end Unit Testing Workshop, 2ª Parte
Con Facundo Gaumet. Se presentarán nociones de testing asíncrono en tres patrones (callback, promise, async/await) y de test coverage.
- 996