2012-10-09 10 views
5

decir que tengo dos clases llamada Book y Library de la siguiente manera:¿Cómo tener una prueba atómica real en QUnit?

var Book = function(title, author) 
{ 
    this.title = title; 
    this.author = author; 
}; 

y

var Library = function() 
{ 
    var dbName = 'test'; 

    this.getLibrary = function() { 
     return JSON.parse(window.localStorage.getItem(dbName)); 
    }; 

    this.save = function(library) { 
     window.localStorage.setItem(dbName, JSON.stringify(library)); 
    }; 
} 

Library.prototype.addBook = function(book) { 
    var library = this.getLibrary(); 
    library.push(book); 

    this.save(library); 

    return library; 
}; 

Library.prototype.removeBook = function(book) { 
    var library = this.getLibrary(); 

    // Find and delete the right book 

    this.save(library); 

    return library; 
}; 

Mi pregunta es: ¿Cómo puedo Unidad a probar la clase Library usando QUnit a disfrutar de una auténtica atómica y prueba independiente?

Escribí esta función de prueba pero no me ha satisfecho. No parece ser muy atómico e independiente ya que mezcla varias funciones que creo deberían probarse de forma independiente. Me gustaría saber si hay una manera mejor o ya la estoy probando bien.

test("test", function() { 
    var library = new Library(); 

    deepEqual(library.getLibrary(), []); 

    // Add book1 
    var book1 = new Book("A book", "An author"); 
    deepEqual(library.addBook(book1), [book1]); 
    deepEqual(library.getLibrary(), [book1]); 

    // Add book2  
    book2 = new Result("A new book", "Another author"); 
    deepEqual(library.addBook(book2), [book2, book1]); 
    deepEqual(library.getLibrary(), [book2, book1]]); 

    // Remove book1 
    deepEqual(library.removeResult(book1), [book2]); 
    deepEqual(library.getLibrary(), [book2]); 

    // Remove book2 
    deepEqual(library.removeResult(book2), []); 
    deepEqual(library.getLibrary(), []); 
}); 

Respuesta

3

Evite escribir pruebas "omnibus" que dependen del estado interno de la unidad que está probando. Hacer pruebas de grano fino a determinados comportamientos y no estatales:

test("addBooksReturnsLibrary", function(){ 
    var l = new Library(); 
    l.addBook(new Book(...)); 
    l.addBook(new Book(...)); 
    var addBooksRetval = l.addBook(new Book(...)); 
    deepEqual(addBooksRetval, l.getLibrary(); 
}); 

test("libraryContainsAddedBook"), function() { 
    var l = new Library(); 
    var b = new Book(...); 
    l.addBook(b); 
    notEqual(-1, library.indexOf(b)); 
}); 

// etc and so forth 

El uso intensivo de deepEqual parece que es una prueba de olor más a menudo que no. Si necesita, por ejemplo, que los libros estén en la biblioteca en un orden específico, diría que es mejor probar específicamente las restricciones de ordenamiento.

+0

Buen punto. Pero el principal problema que tengo es que para probar el removeBook, por ejemplo, tengo que confiar en addBook. ¿Cómo puedo lidiar con esto? – user1730232

+1

@ user1730232 Sin embargo, eso no es un problema real. Agregar/eliminar funcionalidad no es ortogonal. Simplemente pruebe todos los casos: Eliminar sin agregar falla. Eliminar con agregar hojas 0 elementos. Etc. – Bringer128

+1

@ user1730232 Las operaciones de una sola clase no pueden ser completamente independientes. De hecho, sería un olor a código si lo fueran, una señal de que la clase tiene demasiadas responsabilidades. Si quiere ser * muy * formal sobre esto, supongo que podría hacer algún tipo de gráfico de sus pruebas para analizar las dependencias entre los comportamientos, y hacer que no consista en solo ciclos. Pero en general, probablemente pueda suponer que una implementación de clase es "sensata" y no codificada específicamente para pasar el conjunto de pruebas sin ser útil, y escribir pruebas para detectar regresiones, etc. en su lugar. – millimoose

Cuestiones relacionadas