Concepto: Fragmentos para simulación
En esta directriz se describe cómo crear un fragmento para simulación que se pueda utilizar como marcador de posición para componentes que todavía hay que desarrollar. Un fragmento para simulación es un componente que, en realidad, lo único que hace es declararse a sí mismo y a los parámetros de acepta. El fragmento para simulación contiene el código suficiente para poder ser compilado y enlazado con el resto de los componentes.
Relaciones
Elementos relacionados
Descripción principal

Introducción

Los componentes se prueban mediante el envío de entradas a la interfaz, hay que esperar a que el componente las procese y, a continuación, comprobar los resultados. En el curso de este proceso, es muy probable que un componente utilice otros componentes enviándole entradas y utilizando sus resultados.

Diagrama descrito en el texto adjunto.

Figura 1: Prueba de un componente que implementó

Los otros componentes pueden causar problemas a la prueba:

  1. Puede que todavía no se hayan implementado.
  2. Puede que tengan defectos que impidan que las pruebas funcionen o que le hagan perder mucho tiempo para descubrir que el error de la prueba no lo causó su componente.
  3. Dificultan la ejecución de pruebas cuando debe ejecutarlas. Si un componente es una base de datos comercial, es posible que su empresa no tengan las suficientes licencias flotantes para todo el mundo. También es posible que uno de los componentes sea hardware y sólo esté disponible en horas planificadas en un laboratorio diferente.
  4. Pueden ralentizar tanto el proceso de prueba que las pruebas no se ejecuten con la frecuencia necesaria. Por ejemplo, inicializar la base de datos puede tardar cinco minutos en cada prueba.
  5. Puede ser difícil conseguir que los componentes produzcan ciertos resultados. Por ejemplo, que todos los métodos que escriben en el disco manejen los errores de "disco lleno". ¿Cómo puede asegurarse de que el disco se llena justo en el momento en que se invoca el método?

Para evitar estos problemas, puede decidir utilizar componentes fragmento para simulación (también llamados objetos de simulacro). Los componentes de fragmento para simulación se comportan como componentes reales, por lo menos en cuanto a los valores que les envía el componente mientras responde a las pruebas. Estos componentes pueden ir todavía más allá: pueden ser emuladores generales que pretenden imitar fielmente la mayoría o todos los comportamientos del componente. Por ejemplo, suele ser una buena estrategia construir emuladores de software para hardware. Los emuladores se comportan igual que el hardware, pero son más lentos. Son útiles porque soportan una mejor depuración, hay más copias disponibles y se pueden utilizar antes de que termine el hardware.

Diagrama descrito en el texto adjunto.

Figura 2: Prueba de un componente que implementó apagando un componente del que depende

Los fragmentos para simulación tienen dos desventajas.

  1. Su compilación puede ser cara. (Sobre todo, en el caso de los emuladores). Son componentes de software, por lo que también necesitan mantenimiento.
  2. Pueden ocultar errores. Por ejemplo, suponga que el componente utiliza funciones trigonométricas, pero todavía no hay ninguna biblioteca disponible. Los tres guiones de prueba solicitan el seno de tres ángulos: 10 grados, 45 grados y 90 grados. Utilice la calculadora para obtener los valores correctos y, después, construya un fragmento para simulación para el seno que devuelva, respectivamente, 0,173648178, 0,707106781 y 1,0. Todo es correcto hasta que integra el componente con la biblioteca trigonométrica real, cuya función del seno toma los argumentos en radianes y, por lo tanto, devuelve -0,544021111, 0,850903525 y 0,893996664. Éste es un defecto de código que se descubre más tarde y con más esfuerzo de lo que sería deseable.

Prácticas de diseño de software y fragmentos para simulación

A no ser que los fragmentos para simulación se hayan construido porque el componente real todavía no estaba disponible, lo normal es retenerlos hasta después del despliegue. Es probable que las pruebas a las que dan soporte sean importantes durante el mantenimiento del producto. Por lo tanto, los fragmentos para simulación deben escribirse con estándares superiores al código desechable. No es necesario que los fragmentos para simulación cumplan los estándares de código del producto (por ejemplo, la mayoría no necesitan un conjunto de aplicaciones de prueba propio), pero después los desarrolladores tendrán que mantenerlos como componentes del cambio de producto. Si este mantenimiento es demasiado difícil, los fragmentos para simulación se rechazarán y se perderá la inversión realizada en ellos.

Los componentes, sobre todo cuando hay que retenerlos, alteran el diseño de componentes. Por ejemplo, suponga que el componente va a utilizar una base de datos para almacenar pares clave/valor de forma permanente. Considere dos casos de ejemplo de diseño:

Caso de ejemplo 1: La base de datos se utiliza para las pruebas y para su función normal. No es necesario ocultar al componente la existencia de la base de datos. Puede inicializarlo con el nombre de la base de datos:

 public Component(

String databaseURL) { try {     databaseConnection =         DriverManager.getConnection(databaseURL);     ... } catch (SQLException e) {...}     }

Aunque no desease que todas las ubicaciones que leyeron o escribieron un valor construyan una sentencia SQL, seguro que ha tenido varios métodos que contienen SQL. Por ejemplo, el código del componente que necesite un valor puede invocar este método del componente:
 public String get(String key) { try {     Statement stmt =       databaseConnection.createStatement();     ResultSet rs = stmt.executeQuery(       

"SELECT value FROM Table1 WHERE key=" + key);     ... } catch (SQLException e) {...}     }

Caso de ejemplo 2: En la prueba, la base de datos se sustituye por un fragmento para simulación. El código del componente debería tener el mismo aspecto independientemente de si se está ejecutando en la base de datos real o en el fragmento para simulación; por lo debe codificarse para que utilice métodos de una interfaz abstracta:
 

interface KeyValuePairs { String 

get(String key); void 

put(String key, String value);     }

Las pruebas implementan KeyValuePairs con algo simple, como una tabla hash:
 

class FakeDatabase implements KeyValuePairs  { Hashtable table = new Hashtable(); public String 

get(String key) {     return (String) table.get(key); } public void 

put(String key, String value) {     table.put(key, value); }     }
Cuando no se utiliza en una prueba, el componente utiliza un objeto adaptador que convierte llamadas a KeyValuePairs en sentencias SQL:
 

class DatabaseAdapter implements KeyValuePairs { private Connection databaseConnection; public DatabaseAdapter(String databaseURL) {     try {         databaseConnection =             DriverManager.getConnection(databaseURL);         ...     } catch (SQLException e) {...} } public String 

get(String key) {     try {         Statement stmt =            databaseConnection.createStatement();         ResultSet rs = stmt.executeQuery(           "SELECT value FROM Table1 WHERE key=" + key);         ...     } catch (SQLException e) {...} } public void 

put(String key, String value) {     ... }     }

Puede que el componente tenga un solo constructor para las pruebas y para otros clientes. Dicho constructor escogerá un objeto que implemente KeyValuePairs. O puede que sólo proporcione esa interfaz para las pruebas y requiera que los clientes ordinarios del componente pasen el nombre de una base de datos:
 class Component { 

public Component(String databaseURL) {     this.valueStash = new DatabaseAdapter(databaseURL); } // For testing. 

protected Component(KeyValuePairs valueStash) {     this.valueStash = valueStash; }     }

Desde el punto de vista de los programadores del cliente, los dos casos de ejemplo de diseño producen la misma API, aunque uno es más fácil de probar. (Tenga en cuenta que algunas pruebas pueden utilizar la base de datos real y otras la base de datos del fragmento para simulación).

Más información


Para obtener más información relacionada con los fragmentos para simulación, consulte lo siguiente: