Técnicas de prueba basada en estado

Una técnica de prueba utilizada habitualmente es analizar los diferentes estados abstractos que puede tener una clase. El estado de un objeto se suele definir como una restricción en los valores de sus atributos. Según el estado del objeto, las llamadas a algunos métodos pueden ser válidas o no, o es posible que cambie el comportamiento del método.

En general, la utilización de técnicas de prueba basada en estado implica el proceso siguiente:

  1. Definir los pasos.
  2. Definir las transiciones entre estados.
  3. Definir los casos de prueba.
  4. Definir los valores de prueba para cada estado.

Para ver cómo funciona este proceso, tengamos en cuenta la clase MoneyBag de JUnit.

class MoneyBag implements IMoney {
     private Vector fMonies= new Vector(5); 
     public IMoney add(IMoney m) {
         return m.addMoneyBag(this);
     }
     public IMoney addMoney(Money m) {
         return MoneyBag.create(m, this);
  } 
  public IMoney addMoneyBag(MoneyBag s) {
     return MoneyBag.create(s, this); 
  }
  void appendMoney(Money aMoney) {
     if (aMoney.isZero()) return;
     IMoney old= findMoney(aMoney.currency());
     if (old == null) {
           fMonies.addElement(aMoney);
           return;
     }
     fMonies.removeElement(old);
     IMoney sum= old.add(aMoney);
     if (sum.isZero())
           return;
     fMonies.addElement(sum);
  }
  private Money findMoney(String currency) {
     for (Enumeration e=fMonies.elements();e.hasMoreElements();)
     {
          Money m= (Money) e.nextElement();
          if (m.currency().equals(currency))
              return m;
     }
     return null;
  }
  private boolean contains(Money m) {
     Money found= findMoney(m.currency());
     if (found == null) return false;
     return found.amount() == m.amount();
     }
  } 

Definir estados

El primer paso en la utilización de técnicas de prueba basada en estado es definir los estados. En la segunda línea del código, se puede ver que la clase MoneyBag puede tener de 0 a 5 objetos Money.

private Vector fMonies= new Vector(5); 

A partir de este análisis, puede crear un modelo de estado con los estados siguientes:

En este ejemplo, puede definir las restricciones siguientes en el atributo fMonies, como se muestra en la tabla siguiente:

Estado Restricción
EmptyBag fMonies.size()==0
PartiallyFullBag (fMonies.size()>0) && (fMonies.size()<5)
FullBag fMonies.size()==5

Aunque no siempre es necesario definir estos estados formalmente, puede ser útil al definir datos de prueba o si desea comprobar el estado del objeto durante un caso concreto.

Definir transiciones entre estados

El paso siguiente es definir las transiciones posibles entre estados y determinar qué desencadena una transición de un estado a otro. En general, cuando se prueba una clase, se desencadena una transición al invocar un método. Por ejemplo, la transición del estado EmptyBag al estado PartiallyFullBag se desencadena mediante una llamada a appendMoney.

Por tanto, algunas transiciones posibles podrían definirse del modo siguiente:

En resumen, para cada estado identificado, se deben listar:

Definir casos de prueba

Las pruebas suelen consistir en casos prácticos en los que se prueba el objeto siguiendo un itinerario determinado a través de la máquina de estado. Dado que el número de itinerarios posibles en la máquina de estado es normalmente infinito, no es práctico probar cada posible itinerario. En su lugar, asegúrese de realizar las tareas siguientes:

Siempre que sea posible, compruebe el estado del objeto que se prueba en todo el caso práctico para garantizar que el modelo de estado teórico definido sea realmente el implementado por la clase que se prueba. Tras finalizar estas transiciones, puede probar su robustez llamando a métodos de forma aleatoria y comprobando que nunca se violen las constantes de las clases. Por ejemplo, la clase MoneyBag siempre debe ser un conjunto de objetos Money que nunca sean de la misma moneda.

Puede utilizar el patrón de prueba basado en caso que acompaña al producto para crear casos de prueba.

Definir valores de prueba para cada estado

Finalmente, debe elegir valores de prueba para cada estado individual. Elija valores de prueba exclusivos y no vuelva a utilizar valores que ya haya empleado previamente en otras pruebas. Esta estrategia proporciona una mayor diversidad en la suite de pruebas e incrementa las posibilidades de detectar errores. Para obtener información detallada sobre la definición de valores de prueba adecuados, consulte Definir datos de prueba.

Conceptos relacionados
Estrategias de prueba
Subsistemas Java

Tareas relacionadas
Probar métodos Java
Probar clases Java

Condiciones de uso | Comentarios
(C) Copyright IBM Corporation 2000, 2004. Reservados todos los derechos.