Skip to content

mgdelacroix/testing-en-javascript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Testing en Javascript

Definiciones

Test end-to-end: prueban sobre el DOM de la web definitiva.

Herramientas

Contenido de package.json

{
  "name": "js-testing-workshop",
  "version": "0.0.0",
  "devDependencies": {
    "chai": "^1.9.1",
    "chai-jquery": "^1.2.3",
    "karma": "^0.12.16",
    "karma-chai": "^0.1.0",
    "karma-chrome-launcher": "^0.1.4",
    "karma-html2js-preprocessor": "^0.1.0",
    "karma-mocha": "^0.1.4",
    "karma-sinon": "^1.0.3",
    "mocha": "^1.20.1",
    "sinon": "^1.10.2"
  }
}
  • chai: aserciones
  • chai-jquery: syntax sugar para chai
  • sinon: mocks
  • mocha: bloques sintácticos para TDD y BDD
  • karma: test runner

Configuración de Karma

images/karma.png

Ejecutamos el wizard de Karma

$ ./node_modules/karma/bin/karma init

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> mocha

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
>

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> test/**/*Spec.js
WARN [init]: There is no file matching this pattern.

>

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes


Config file generated at "/home/mgdelacroix/dev/kaleidos-summer-mondays/testing-en-javascript/karma.conf.js".

Editamos el fichero karma.conf.js y añadimos algunos frameworks:

frameworks: ['mocha', 'chai', 'sinon']

Modificamos el bloque file para que quede así:

files: [
    'js/**/*.js',
    'spec/**/*Spec.js'
]

Lanzar los tests de Karma

Si tenemos chromium, tendremos que crear un enlace simbólico para que karma sea capaz de abrirlo:

$ sudo ln -s /usr/bin/chromium /usr/local/bin/google-chrome

Lanzamos los tests desde el directorio del proyecto:

$ ./node_modules/karma/bin/karma start

Anatomía de un test

Para escribir cada especificación creamos un bloque describe que tiene esta pinta:

describe('definition', function() {
    beforeEach(function() {
    })

    afterEach(function() {
    })

    it('definition', function(){
    })
}

Dentro de los bloques beforeEach y afterEach podemos settear variables para utilizar dentro de los it en this:

describe('definition' function() {
    beforeEach(function() {
        this.myValue = 40;
    })

    it('I am 40', function() {
        expect(this.myValue).to.be.equal(40);
    })
})

images/chai.png

Utilizamos chai para las aserciones:

expect(this.myValue).to.be.equal(40);

Si queremos ejecutar un solo bloque describe, podemos añadirle .only, y si queremos ignorarlo, .skip.

// solo se ejecutará este bloque
describe.only('', function() {})

// este bloque no se ejecutará
describe.skip('', function() {})

Sinon

images/sinon.png

Sirve para utilizar mocks.

Spy

No reemplaza el comportamiento, y sobre él podemos hacer comprobaciones para ver si se ha llamado y como.

Después de utilizar spies tenemos que restaurar el comportamiento por defecto de los objetos espiados.

sinon.spy(jQuery, 'post');
    
// doStuff

expect(jQuery.post.called).to.be.true;
expect(jQuery.post.calledOnce).to.be.true;
expect(jQuery.post.calledWith(user)).to.be.true;
    
jQuery.post.restore();

Si en lugar de usar sinon.spy utilizamos this.spy, Sinon ya sabe que tiene que restaurar el comportamiento, así que no tendremos que hacerlo nosotros.

this.spy(jQuery, 'post');
    
// doStuff
   
expect(jQuery.post.called).to.be.true;
expect(jQuery.post.calledOnce).to.be.true;
expect(jQuery.post.calledWith(user)).to.be.true;

Stub

Reemplaza el comportamiento.

// stub
test.getLastName = sinon.stub();
test.getLastName.withArgs("Juan Froilan").returns("Froilan");

// doStuff

// comprobar expectativas

Mock

Igual que el stub pero tiene unas expectativas de comunicación, que si no se cumplen falla el test.

// mock

// expectativas

// doStuff

// verificar expectativas
mock.verify();

La diferencia que he podido extraer entre mock y stub es que en el caso del mock, creas el mock, defines las expectativas y al final del test las verificas (mock.verify()). En el caso de stub, creas el stub, lo usas y al final compruebas el comportamiento usando expect.

Un buen ejemplo del párrafo anterior son los test de “ejecutar funciones al añadir usuarios” del fichero userManagerSpec.js

Fake timer

Controla el tiempo, pudiendo adelantarlo (por ejemplo).

// do something with a 5 secs timer

this.clock.tick(6000);

// verify the result of something

Fake server

Creamos un servidor falso para hacer peticiones.

this.server = sinon.fakeServer.create();

this.server.respondWith("GET", "/myapp/users.json",
                       [200, { "Content-Type": "application/json"},
                       JSON.stringify(userList)]);

send();

this.server.respond();

// expect ...

Kaleidos Summer Mondays

This course is part of the Kaleidos Summer Mondays initiative. Thanks to Kaleidos for giving us the time and resources to make it possible.

Thanks to juanfran for preparing and giving this course.

images/kaleidos.png

About

Kaleidos Summer Mondays Course

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages