23 mai tests

Transcription

23 mai tests
Strasbourg Node.js
Tests en Javascript et TDD
Pas de tests
=
des bugs
Pourquoi tester ?
● Un bug en prod =
○
○
○
○
Context switching
Analyse plus complexe
Stress et fatigue
Dépréciation de l’image
Types de tests
● Tests manuels : exploratoires, usabilité, UAT
● Tests automatisés : unitaires, intégration
● Tests manuels et automatisés : cas nominaux et
nouvelles fonctionnalités
● Tests techniques : sécurité, charge, robustesse
=> Tous ces types de tests sont utiles
Pourquoi tester automatiquement ?
● Plus rapides que les tests manuels
● Pour améliorer le “time to market”
● Pour livrer plus rapidement et sereinement
Quelle stratégie de tests ?
● Cycle en V ?
○
○
○
○
tests en fin de projet
feedback sur problèmes de qualité trop tardif
tests de bout en bout, complexes et coûteux
on est en retard, on peut déscoper les tests
● Ce n’est pas au développeur de tester ?
○ dé-responsabilisation
○ perte de temps sur les problèmes évidents
LA bonne stratégie de tests
● Au coeur de l’équipe de développement
● Les tests sont faits au plus tôt
● Les tests les plus pertinents sont automatisés
Pyramide des tests
Quels outils en Node.js ?
● Exécuter le test
○ Mocha
● Simuler le comportement
○ Nock : les mocks http
○ Rewire : ré-écriture de comportement
○ Sinon.js : les mocks
● Vérifier les résultats du test
○ Chai
Mocha
test.js
describe('Array', function() {
describe('#indexOf()', function () {
it('should return -1 when the value is not present',
function () {
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});
Mocha
$ mocha test.js
dans la console
Array
#indexOf()
✓ should return -1 when the value is not present
1 passing (11ms)
Mocha : gestion de l’asynchrone
describe('User', function() {
describe('#save()', function() {
it('should save without error', function(done) {
var user = new User('Luna');
user.save(function(err) {
if (err) throw err;
done();
});
});
});
});
Mocha : hooks
before(function() {
console.log(‘Debut de la suite de tests’);
});
// ou after, beforeEach, afterEach
Mocha : inclusion / exclusion
● describe.only, describe.skip
● it.only, it.skip
● Exemple d’exclusion de test :
it.skip('should save without error', function(done) {
// ...
});
Chai / should
chai.should();
foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.length(3);
tea.should.have.property('flavors').with.length(3);
Chai / expect
var expect = chai.expect;
expect(foo).to.be.a('string');
expect(foo).to.equal('bar');
expect(foo).to.have.length(3);
expect(tea).to.have.property('flavors')
.with.length(3);
Chai / assert
var assert = chai.assert;
assert.typeOf(foo, 'string');
assert.equal(foo, 'bar');
assert.lengthOf(foo, 3)
assert.property(tea, 'flavors');
assert.lengthOf(tea.flavors, 3);
Tester avec Nock
nock(baseUrl)
.get(‘/employees/count’)
.reply(200, {count:1986});
Nock : simuler une erreur
nock(baseUrl)
.get(‘/employees/count’)
.reply(500, {error:’unexpected error’});
Nock : simuler un timeout
nock(baseUrl)
.get(‘/employees/count’)
.delayConnection(2000)
.delay(3000)
.reply(200, {count:1986});
Nock : interdire les connexions
nock.disableNetConnect()
Nock : vérifier les appels
var countScope = nock(baseUrl)
.get(‘/employees/count’)
.reply(200, {count:1986});
// …
countScope.isDone();
Nock : recorder
dans le test
nock.recorder.rec();
dans la console
<<<<<<-- cut here -->>>>>>
nock('http://localhost:3000')
.get('/employees/count')
.reply(200, {"count":1200}, { 'xpowered-by': 'Express', 'contenttype': 'application/json;
charset=utf-8', 'content-length':
'14',connection: 'keep-alive' });
<<<<<<-- cut here -->>>>>>
Rewire : code à tester
var fs = require("fs"),
path = "/somewhere/on/the/disk";
lib/myModule.js
function readFile(cb) {
console.log("Reading from file system ...");
fs.readFile(path, "utf8", cb);
}
exports.readFile = readFile;
Rewire : le test
var rewire = require("rewire");
var myModule = rewire("../lib/myModule.js");
myModule.__set__("path", "/dev/null");
myModule.__get__("path"); // = '/dev/null'
myModule.readFile(function (err, data) {
console.log(data);
});
test/myModule.test.js
Sinon.js
var myAPI = {
method: function () {
}
};
var mock = sinon.mock(myAPI);
mock.expects("method").once().returns(42);
console.log(myAPI.method());
Test Driven Development
Test, Code, Refactor
1.
2.
3.
4.
Ecrire un test en échec
Faire en sorte que le test passe
Refactoring
Recommencer
TDD : pourquoi ?
●
●
●
●
●
Prise de recul avant de coder
Feedback immédiat
Code testable, lisible et propre
Bonne couverture de tests
On se concentre sur des problèmes simples à chaque
itération
● Impact positif sur la productivité
Quelques stats
● Etude d’IBM sur l’impact de la productivité
○ Temps de développement plus long : 15-30%
○ Moins de bugs : 40-90%
● Importance du “clean code” par Uncle Bob
○ 90% de temps à lire du code
○ 10% de temps à écrire du code
Atelier Poker Hands
Règles de l’atelier Poker Hands
● Se poser la bonne question à chaque étape :
○ Test : quel est le prochain cas à tester ?
○ Code : quelle est l’implémentation la plus simple ?
○ Refactor : Est-il possible de faire du refactoring?
● Soignez le code des tests
● Ne grillez pas les étapes

Documents pareils