Ejemplo de pruebas unitarias en Java
Las métricas de los requerimientos no funcionales deben tener un soporte lógico que permita cuantificarlos, pues un requerimiento no cuantificable es un requerimiento que no podrá tener pruebas de aceptación.
De acuerdo con lo anterior es importante programar código para automatizar las pruebas, y es por esto que continuación se describe un ejemplo de las pruebas utilizando una librería en JAVA llamada JUNIT, que corresponde a pruebas unitarias en Java.
Este ejemplo consiste en un software para manejar las referencia bibliográficas de una biblioteca con los siguientes requerimientos:
- Adicionar una nueva referencia que consista en un identificador entero, el nombre del autor y un mensaje asociado a la referencia.
- Consultar una referencia buscándola por el identificador.
- Consultar las referencias que correspondan a un autor, buscándolas por nombre del autor.
- Consultar todas las referencias de la biblioteca.
- Actualizar una referencia buscándola por el identificador y permitiendo cambiar el nombre del autor y el mensaje.
- Remover una referencia buscándola para eliminarla por identificador.
A continuación se presenta el código que permite responder a estos requerimientos y el cual tiene dos clases: Quote y QuoteService. La clase Quote presenta primero los atributos y posteriormente los métodos, y tendrá tres atributos que se definen en la problemática: id objeto de tipo Integer; nombre del autor de tipo String, y mensaje de tipo String.
Los métodos de la clase son tres constructoras: la constructora implícita, que no tiene parámetros; la constructora con el identificador, y la constructora con los valores que se le van a asignar a los tres atributos.
Los modificadores para cada atributo que corresponden al get y set del identificador, nombre del autor y mensaje.
Finalmente, tres métodos que sobrescriben los métodos básicos para trabajar de forma eficaz y eficiente elementos de un conjunto; el método equals verifica el id y si ya fue creado o no; el método hashcode que corresponde a una función matemática basada en números primos y el identificador para indexar elementos en un conjunto en posiciones únicas, y finalmente el método toString que retorna un String para que sean desplegados en forma legible los datos del objeto por consola.
public class Quote
{
private Integer id;
private String author;
private String message;
public Quote() {
}
public Quote(Integer id) {
super();
this.id = id;
}
public Quote(Integer id, String author, String message) {
super();
this.id = id;
this.author = author;
this.message = message;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Quote other = (Quote) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "Quote [id=" + id + ", author=" + author + ", message=" + message + "]";
}
}
La clase QuoteServiceAPI tiene un atributo que define el grupo de objetos de la clase Quote. Los métodos de la clase son:
- Un método para adicionar un elemento al conjunto: el método recibe como parámetro los valores que se le van a asignar a los atributos de los objetos que corresponden al identificador, nombre del autor y al mensaje.
- Un método para actualizar una referencia: el parámetro corresponde a la referencia actualizada. En este objeto el identificador es el criterio para seleccionar la referencia a actualizar con los otros valores del parámetro que son el nombre del autor y el mensaje.
- Un método para remover una referencia: el parámetro corresponde al identificador de la referencia a eliminar.
Por último, tres métodos de consulta:
- Uno de consulta de una referencia buscándola por identificador;
- otro para buscar una o varias referencias por nombre de autor,
- y finalmente, otro que retorna todas las referencias de la biblioteca.
public class QuoteServiceAPI {
public static List quotes = new ArrayList
();
public Quote addQuote(Integer id, String author, String message) {
//Check for already exists
int index = quotes.indexOf(new Quote(id));
if (index != -1)
return null;
Quote q = new Quote(id, author, message);
quotes.add(q);
return q;
}
public Quote updateQuote(Quote q) {
int index = quotes.indexOf(q);
if (index == -1)
return null;
Quote currentQuote = quotes.get(index);
currentQuote.setAuthor(q.getAuthor());
currentQuote.setMessage(q.getMessage());
return q;
}
public void removeQuote(Integer id) {
int index = quotes.indexOf(new Quote(id));
if (index != -1)
quotes.remove(index);
}
public List getQuotes() {
return quotes;
}
public List getQuotesByAuthor(String author) {
List results = new ArrayList
();
for (Quote quote : quotes) {
if (quote.getAuthor().indexOf(author) != -1) {
results.add(quote);
}
}
return results;
}
public Quote getQuote(Integer id) {
int index = quotes.indexOf(new Quote(id));
if (index != -1)
return quotes.get(index);
return null;
}
}
Teniendo en cuenta la lógica anterior, a continuación se describen las pruebas unitarias, de integración, de sistema y de aceptación, que se describen en las clases QuoteTest y QuoteSeriveAPITest.
En QuoteTest se tiene ejemplo de pruebas unitarias en este contexto corresponden a la comprobación de los métodos, en este contexto los métodos como el de probar el get del identificador es un ejemplo, debido a que de forma general se crea para estas pruebas un método donde se crea para todas las pruebas sobre Quote un objeto y se asignan unos valores, en este contexto la ejecución automatizada de las pruebas usa métodos como assertTrue del api de JUNIT donde dependiendo de la condición si es verdadera pasa la prueba, si es assertEquals el método de JUNIT prueba cuando dos String’s son iguales.
En esta misma clase se tienen métodos de pruebas de integración como en el método de setAuthor, donde se crea un objeto de la clase Quote y se llama un método para asignar un valor y después se llama el otro método para leer el valor y comprobar si es igual al asignado con anterioridad.
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
public class QuoteTest {
private static Quote q = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
q = new Quote();
q.setAuthor("juan");
q.setId(new Integer("1"));
q.setMessage("ejemplo");
}
@Test
public void testHashCode() {
assertTrue (q.hashCode()==32);
}
@Test
public void testGetId() {
assertEquals(q.getId().toString(),"1");
}
@Test
public void testSetId() {
Quote qe = new Quote();
qe.setId(new Integer("12"));
assertEquals (qe.getId().toString(),"12");
}
@Test
public void testGetAuthor() {
assertEquals(q.getAuthor(), "juan");
}
@Test
public void testSetAuthor() {
Quote qe = new Quote();
qe.setAuthor("juan pablo");
assertEquals(qe.getAuthor(), "juan pablo");
}
@Test
public void testGetMessage() {
assertEquals(q.getMessage(), "ejemplo");
}
@Test
public void testSetMessage() {
Quote qe = new Quote();
qe.setMessage("cambio");
assertEquals(qe.getMessage(),"cambio");
}
@Test
public void testEqualsObject() {
Quote q2 = new Quote(new Integer(2));
Quote q3 = new Quote(new Integer(2));
assertTrue (q2.equals(q3));
}
@Test
public void testToString() {
assertEquals (q.toString(),"Quote [id=1, author=juan, message=ejemplo]");
}
}
En la siguiente figura se muestra un ejemplo del reporte de pruebas con JUNIT de la clase QuoteTest:
(Para ampliar la imagen haga clic sobre ella)
Finalmente se aplican las pruebas de sistema y de aceptación. Para este tipo de pruebas se utiliza la clase QuoteService, en la que se hacen pruebas de sistema, como crear, actualizar, remover y consultar. Por otra parte, las pruebas de aceptación son las elegidas para determinar el cumplimiento de la especificación del requerimiento. Una de estas pruebas consiste en adicionar dos referencias y consultarlas.
import static org.junit.Assert.*;
import java.util.ArrayList;
import org.junit.BeforeClass;
import org.junit.Test;
public class QuoteServiceAPITest {
private static QuoteServiceAPI qsa = null;
private static Quote base = null;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
qsa = new QuoteServiceAPI();
base = qsa.addQuote(new Integer(0), new String("pablo"), new String("ejemplo"));
Quote base1 = qsa.addQuote(new Integer(3), new String("juan"), new String(" otro ejemplo"));
}
@Test
public void testAddQuote() {
Quote nuevo = qsa.addQuote(new Integer(1),new String("juan"), new String("mensaje"));
assertEquals (nuevo.getAuthor(),"juan");
}
@Test
public void testUpdateQuote() {
base.setMessage("cambio");
Quote act = qsa.updateQuote(base);
assertEquals (base.getMessage(),"cambio");
}
@Test
public void testRemoveQuote() {
qsa.removeQuote(new Integer("0"));
assertNull (qsa.getQuote(new Integer("0")));
}
@Test
public void testGetQuote() {
assertEquals (qsa.getQuote(new Integer("3")).getAuthor(),"juan");
}
@Test
public void testGetQuotes() {
ArrayList todos = (ArrayList
) qsa.getQuotes();
assertTrue (todos.size()==2);
}
@Test
public void testGetQuotesByAuthor() {
ArrayList todos = (ArrayList
) qsa.getQuotesByAuthor("juan");
assertTrue (todos.size()==2);
}
}
Finalmente, la ejecución de las pruebas en reporte determina si se aprobaron o no. A continuación se muestra una imagen de la prueba de QuoteServiceAPITest.
(Para ampliar la imagen haga clic sobre ella)
