test de pruebas

26
Anexo Test de Pruebas ANEXO: TEST DE PRUEBAS La escritura de tests es tan importante que es algo que deberíamos hacer todo el tiempo a lo largo del ciclo de desarrollo del software. Los tests, si están bien escritos, nos permiten evaluar exhaustivamente la implementación de una aplicación en todos sus niveles. Test unitarios: un test unitario ejercita el funcionamiento de una unidad de código, normalmente una clase, aislada del resto de la aplicación. Tests de integración: un test de integración ejercita el funcionamiento de una o varias clases en el contexto de la aplicación. Típicamente, estos tests verifican la interacción con una base de datos, conexiones a sistemas externos, containers, etc. Lo importante es automatizar el testeo de la aplicación en todos los niveles. Los tests que escribamos deben tener dos propiedades: deben ser automáticos e independientes. Los tests son sumamente valiosos cuando el nivel de stress es alto, así, si podemos ejecutarlos automáticamente contamos con una valiosa herramienta para indicar que el sistema funciona correctamente. La autonomía e independencia entre los tests garantiza que la falla de un test no impacta al resto. Esto nos permite diagnosticar los problemas con más precisión. Una forma efectiva de probar clases Java es utilizar JUnit que es posiblemente el más antiguo y popular framework de test disponible para java. Por tal motivo es adoptado y bien conocido por la mayoría de los desarrolladores y muy familiarizados con el. Hay numerosas extensiones disponibles para JUnit que permiten las pruebas de cualquier componente de nuestro sistema. Un caso simple de pruebas extiende de junit.frameword.TestCase y este provee de algunos métodos básicos para construir pruebas incluyendo métodos “assert” que son los mecanismos para comprobar la corrección de nuestro código y realizar las validaciones adecuadas para garantizar el buen funcionamiento. Una forma efectiva de probar clases Java es por tanto utilizar JUnit. Esta es una excelente herramienta para probar nuestros JavaBeans normales, pero la necesidad de probar nuestro código llega mucho más Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 1

Upload: maelgo

Post on 26-Jul-2015

55 views

Category:

Documents


9 download

TRANSCRIPT

Page 1: Test de Pruebas

Anexo Test de Pruebas

ANEXO: TEST DE PRUEBAS

La escritura de tests es tan importante que es algo que deberíamos hacer todo el tiempo a lo largo del ciclo de desarrollo del software. Los tests, si están bien escritos, nos permiten evaluar exhaustivamente la implementación de una aplicación en todos sus niveles.

Test unitarios: un test unitario ejercita el funcionamiento de una unidad de código, normalmente una clase, aislada del resto de la aplicación.

Tests de integración: un test de integración ejercita el funcionamiento de una o varias clases en el contexto de la aplicación. Típicamente, estos tests verifican la interacción con una base de datos, conexiones a sistemas externos, containers, etc.

Lo importante es automatizar el testeo de la aplicación en todos los niveles. Los tests que escribamos deben tener dos propiedades: deben ser automáticos e independientes. Los tests son sumamente valiosos cuando el nivel de stress es alto, así, si podemos ejecutarlos automáticamente contamos con una valiosa herramienta para indicar que el sistema funciona correctamente. La autonomía e independencia entre los tests garantiza que la falla de un test no impacta al resto. Esto nos permite diagnosticar los problemas con más precisión.

Una forma efectiva de probar clases Java es utilizar JUnit que es posiblemente el más antiguo y popular framework de test disponible para java. Por tal motivo es adoptado y bien conocido por la mayoría de los desarrolladores y muy familiarizados con el. Hay numerosas extensiones disponibles para JUnit que permiten las pruebas de cualquier componente de nuestro sistema.

Un caso simple de pruebas extiende de junit.frameword.TestCase y este provee de algunos métodos básicos para construir pruebas incluyendo métodos “assert” que son los mecanismos para comprobar la corrección de nuestro código y realizar las validaciones adecuadas para garantizar el buen funcionamiento.

Una forma efectiva de probar clases Java es por tanto utilizar JUnit. Esta es una excelente herramienta para probar nuestros JavaBeans normales, pero la necesidad de probar nuestro código llega mucho más allá. Para la creación de casos de prueba se deberá utilizar StrutsTestCase.

Además se pueden utilizar otras herramientas para las pruebas de stress y carga, tales como Apache JMeter (http://jakarta.apache.org/jmeter) en la que podemos definir y simular escenarios concurrentes.

Para completar el conjunto de pruebas y garantizar la corrección del software construido deberíamos recurrir a realizar una evaluación del comportamiento funcional de la aplicación. Para ello utilizaremos herramientas que nos permiten introducir un patrón de navegación automatizado y ejecutar las pruebas de aceptación Un ejemplo de estos productos es Solex.

1.1 JUnit

En www.junit.org podemos encontrar la última versión de junit, actualmente la 3.7. Para poder usar JUnit lo único que debemos hacer es incluir el fichero junit.jar en nuestro classpath.

La forma de funcionar típica de un test con JUnit es: definir unos datos, darles algún tipo de tratamiento, obtener unos resultados y comprobarlos con los resultados que nosotros estábamos esperando. La idea final es que sea el propio JUnit el que no diga si el test ha idobien o por el contrario el resultado no coincide con el esperado.

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 1

Page 2: Test de Pruebas

Anexo Test de Pruebas

1.1.1 Assert

Empezaremos viendo como se pueden hacer las comprobaciones de los resultados. La clase junit.framework.Assert, nos proporciona una serie de métodos que son los encargados de hacer dichas comprobaciones. Esta clase contiene una serie de métodos que empiezan por assert. Tenemos métodos assert para comprobar si dos objetos son iguales (assertEquals...), para comprobar si un objeto es nulo (assertNull...), para comprobar si un objeto no es nulo (assertNotNull...) o para comprobar si dos variables apuntan a un mismo objeto (assertSame...).

Cada llamada a un método assert podemos considerarla como un test. La lógica de estos métodos es simple, si la condición del método assert se cumple el test es valido, en caso contrario el test no es valido y lanza un FailedAssertionError, o sea, un error en el testeo.

Debemos tener cuidado con los bloques try-catch, ya que estos bloques normalmente capturan excepciones que lanza nuestro código indicando alguna anomalía. Si en los test usamos algún bloque de este tipo no deberíamos dejar que el test acabe bien. Para este propósito disponemos del método fail() o fail(String mensaje), que lanza un FailedAssetionError, y nos informe de la anomalía.

1.1.2 TestCase

La clase abstracta junit.framework.TestCase es la base sobre la cual definiremos nuestros tests. Esta clase extiende de junit.framework.Assert.

Para crear un test con JUnit debemos seguir estos tres pasos:

Crear una clase que herede de la clase TestCase

public class SimpleTest extends TestCase

Crear un constructor con un parámetro de tipo String y llamar al constructor de la clase padre pasándole dicho String.

public SimpleTest( String nombre ) {super( nombre )

}

Crear uno o varios métodos que empiecen por "test", sin parámetros y que no devuelvan nada.

public void testSimple() {...

}

De esta forma tan simple hemos creado una clase de test. Ahora solo nos queda implementar el método testSimple().

import junit.framework.TestCase;public class SimpleTest extends TestCase {public SimpleTest( String nombre ) {super( nombre );}

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 2

Page 3: Test de Pruebas

Anexo Test de Pruebas

public static void main( String args[] ) {junit.textui.TestRunner.run( SimpleTest.class );}public void testSimple() {String s1 = "DySs";String s2 = "DySs";assertEquals( s1, s2 );}}

Como hemos visto un TestCase no es mas que una clase que contiene uno o varios métodos test...() donde aparecen una o varias llamadas a métodos assert...() o fail().

La ejecución de un test puede acabar de cuatro formas:

o Con la validación correcta de todos los asserts. Esto es lo que esperamos.

o Lanzando uno a varios FailedAssertionError con su información asociada. Esto ocurre si algún assert no ha sido valido, o sea, la ejecución de nuestro código no ha devuelto el resultado esperado.

o Lanzando cualquier Exception de Java. Esto no es provocado por la validación de los métodos assert, sino que nos indica algún error de implementación, ya puede ser del propio TestCase o de nuestro código.

o Puede que el resultado sea una mezcla de excepciones de Java y FailedAssertionErrors.

Ejemplo:

import junit.framework.TestCase;public class ErrorEnTryCatch extends TestCase {public static void main( String args[] ) {junit.textui.TestRunner.run( ErrorEnTryCatch.class );}public ErrorEnTryCatch( String nombre ) {super( nombre );}public void testTryCatch() {String error = null;try {System.out.println( error.toString() );} catch( NullPointerException npex ) {fail( "\nExcepcion capturada por el test\n" +npex );}}}

1.1.3 setUp() y tearDown()

La secuencia de ejecución de una clase que herede de TestCase es la siguiente:

setUp()

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 3

Page 4: Test de Pruebas

Anexo Test de Pruebas

testAlgo()tearDown()

Esta secuencia se repite para todos los métodos test que contenga nuestra clase.

Si tuviésemos varios métodos test que realizan algún tratamiento sobre unos mismos datos, deberíamos usar setUp() para la inicialización de dichos datos. En setUp() inicializaremos variables, estableceremos conexiones con bases de datos, etc. En tearDown() liberaremos recursos tales como las conexiones a bases de datos.

import junit.framework.TestCase;public class SimpleTest2 extends TestCase {private String s1;private String s2;private String s3;public SimpleTest2( String nombre ) {super( nombre );}

public static void main( String args[] ) {junit.textui.TestRunner.run( SimpleTest2.class );}public void setUp() {s1 = "DySs";s2 = "DySs";s3 = "Ashther";}public void testComparaStrings() {assertEquals( s1, s2 );}public void testConcatenaStrings() {String test1 = s1 + s3;String test2 = s2 + s3;assertEquals( test1, test2 );}}

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 4

Page 5: Test de Pruebas

Anexo Test de Pruebas

1.1.4 TestSuite

Es posible que tengamos nuestros tests estructurados en varias clases TestCase y nos interese ejecutarlos todos de una sola vez. Con este propósito JUnit nos proporciona la clase TestSuite que sirve para agrupar tanto TestCases como otras TestSuite.

Para crear una colección de tests debemos seguir los siguientes pasos:

Crear una clase que herede de TestCase

public class VariosTest extend TestCase

Crear un constructor con un parámetro de tipo String y llamar al constructor de laclase padre pasándole dicho String.

public VariosTest( String nombre ) {super( nombre )}

Crear un método estático de nombre suite, sin parámetros de entrada y que devuelvaun Test.

public static Test suite()

Crear un TestSuite dentro del método suite

TestSuite suite = new TestSuite();

Añadir tests al TestSuite

// Solo un método testsuite.addTest( new SimpleTest2( "testConcatenaString" );// Todos los metodos test de un TestCasesuite.addTestSuite( SimpleTest.class );// Otro TestSuitesuite.addTest( MiTestSuite.suite() );

devolver el TestSuite

return suite;

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 5

Page 6: Test de Pruebas

Anexo Test de Pruebas

Ejemplo:

import junit.framework.TestSuite;import junit.framework.Test;import junit.framework.TestCase;public class VariosTest extend TestCase{public VariosTest( String nombre ) {super( nombre );}public static void main( String args[] ) {junit.textui.TestRunner.run( suite() );}public static Test suite() {TestSuite suite = new TestSuite();suite.addTestSuite( SimpleTest.class );suite.addTest( new SimpleTest2( "testConcatenaStrings" ) );return suite;}}

1.1.5 TestRunner

Hasta ahora hemos visto como crear nuestros test, ahora veremos la forma de ejecutarlos. Todos los ejemplos tienen un método main donde se llama a junit.textui.TestRunner. TestRunner es la clase encargada de ejecutar nuestros tests. Disponemos de tres clases TestRunner, una en modo testo y dos mas en modo grafico, Swing y AWT.

public class VisualizaResultados {public static void main( String args[] ) {// Modo textojunit.textui.TestRunner.run( SimpleTest2.class );// Modo grafico con AWTjunit.awtui.TestRunner.run( SimpleTest2.class );// Modo grafico con Swingjunit.swingui.TestRunner.run( SimpleTest2.class );}}

1.1.6 Conclusión

La forma ideal de usar JUnit es desarrollando en paralelo el código de la clase y el test JUnit para ese trozo de código, en vez de escribir toda la clase y luego escribir el test. Si desarrollamos en paralelo siempre nos será mas fácil depurar el código y testearlo mucho mejor, pero como he dicho es una forma de trabajar, no una obligación. Como hemos podido comprobar el uso de JUnit es muy sencillo y a la vez potente. Y esto es solo la punta de iceberg, podéis encontrar mucha mas información en su pagina oficial, www.junit.org

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 6

Page 7: Test de Pruebas

Anexo Test de Pruebas

1.2 StrutsTestCase

Es una extensión de la clase estándar TestCase de JUnit de Apache, permite el desarrollo de casos de pruebas de software basado en el framework Struts. Fue creado para mejorar el paradigma de diseño Modelo-Vista-Controlador (MVC) dentro de la capa de presentación de una aplicación Web.

StrutsTestCase permite no solo probar la lógica de las clases Action como lo permite la clase TestCase si no que es capaz de invocar al controlador ActionServlet por lo que permite probar también los forward, ActionForms y mappings del software.

StrutsTestCase permite el desarrollo de estos casos de prueba en base a dos posibles implementaciones, una basada en Mock Object que no requiere la ejecución dentro de un contenedor de aplicaciones y otra basada en Cactus para la ejecución dentro de un contenedor.

JMock es una librería que permite realizar tests utilizando objetos simulados (mock objects) dinámicos. El objetivo es aislar los objetos que se testean sustituyendo los objetos con los que se relacionan por objetos simulados en los que podemos definir su estado y los resultados de los métodos. En esencia, un desarrollador es responsable de maquetar las clases que definen el interface para ser consumidas por las clases que se están probando.

Cactus es una extensión de JUnit, prueba código del lado del servido al nivel de unidad. Cactus soporta la aproximación in-container para pruebas del lado del servidor.

Ambas herramientas son imprescindibles y no deberían faltar en cualquier equipo de desarrollo de aplicaciones empresariales que busque la calidad.

La estrategia generalmente aceptada para pruebas en Struts será la de probar las clases de la capa de presentación a través de la capa de aplicación.

Seguidamente se muestra un ejemplo de uso de StrutsTestCase con Mock que valida una acción:

// Extendemos de MockStrutsTestCase:public class TestLoginAction extends MockStrutsTestCase {

public TestLoginAction(String testName) { super(testName); }

// Vamos a probar un caso de éxito public void testLogin() {

// Indicamos donde está nuestro fichero de configuración setConfigFile("/WEB-INF/config/struts-config.xml"); // Indicamos la acción que vamos a probar setRequestPathInfo("/login");

// Seteamos las form bean properties addRequestParameter("username","deryl"); addRequestParameter("password","radar"); // Realizamos la llamada actionPerform();

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 7

Page 8: Test de Pruebas

Anexo Test de Pruebas

//Verificamos el forward verifyForward("success"); // Comprobamos que no existan errores verifyNoActionErrors(); }}

Además StrutsTestCase provee métodos para desarrollar casos de pruebas sobre software basado en Struts y Tiles como muestra el siguiente ejemplo:

// Extendemos de MockStrutsTestCase:public class TestLoginAction extends MockStrutsTestCase {

public TestLoginAction(String testName) { super(testName); }

// Vamos a probar el caso anterior pero verificando Tiles public void testLogin() {

// Indicamos donde está nuestro fichero de configuración setConfigFile("/WEB-INF/config/struts-config.xml");

// Indicamos la acción que vamos a probar setRequestPathInfo("/login");

// Seteamos las form bean properties addRequestParameter("username","deryl"); addRequestParameter("password","radar");

// Realizamos la llamada actionPerform();

// Podemos verificar el forward verifyForward("success");

// La plantilla tiles que usará la salida verifyInputTilesForward("success.tiles.def");

// o ambos a la vez verifyTilesForward("success","success.tiles.def"); }}

StrutsTestCase puede descargarse desde la siguiente dirección:http://strutstestcase.sourceforge.net/

La versión actual es la 2.1.3 publicada en Noviembre de 2004 que da soporte a la versión de struts 1.2.X

Cabe destacar que el índice de actividad actual en el proyecto es muy alto. La falta de nuevas releases es debida principalmente a la escasa evolución que ha tenido el framework Struts Action o “clásico” en los últimos años. Por lo tanto hablamos de un producto muy maduro del

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 8

Page 9: Test de Pruebas

Anexo Test de Pruebas

que no se prevé nuevas versiones (aunque sí parches y correcciones), salvo que se produzcan grandes cambios en el framework de Struts.

Para poder utilizar StrutsTestCase es necesario disponer de las librerías:

La librería jakarta-commons-colections:http://jakarta.apache.org/commons/collections/

El conjunto de librerías que componen el sistema de casos de prueba Cactus:http://jakarta.apache.org/cactus/

Uso y configuración. Existe un FAQ:http://strutstestcase.sourceforge.net/faq.htm

Foro de discusión:http://sourceforge.net/forum/?group_id=39190

API:http://strutstestcase.sourceforge.net/api/index.html

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 9

Page 10: Test de Pruebas

Anexo Test de Pruebas

1.3 Pruebas de carga: JMeter

Por medio de la herramienta que presentamos a continuación, es posible medir el comportamiento de una aplicación ante diversos escenarios de concurrencia.

La información de esta herramienta se encuentra disponible en: http://jakarta.apache.org/jmeter/index.html

JMeter es una herramienta de carga para llevar acabo simulaciones sobre cualquier recurso de Software.

Inicialmente diseñada para pruebas de estrés en aplicaciones web, hoy en día, su arquitectura ha evolucionado no sólo para llevar acabo pruebas en componentes habilitados en Internet (HTTP), sino además en Bases de Datos , programas en Perl , requisiciones FTP y prácticamente cualquier otro medio.

Además, posee la capacidad de realizar desde una solicitud sencilla hasta secuencias de requisiciones que permiten diagnosticar el comportamiento de una aplicación en condiciones de producción.

En este sentido, simula todas las funcionalidades de un Navegador ("Browser"), o de cualquier otro cliente, siendo capaz de manipular resultados en determinada requisición y reutilizarlos para ser empleados en una nueva secuencia.

1.3.1 Prueba de carga básica

El componente principal de JMeter es denominado Plan de Prueba o Test Plan, en él se definen todos los aspectos relacionados con una prueba de carga, como : parámetros empleados por requisición, tipo de reportes a generarse con los resultados obtenidos, la posible reutilización de requisiciones compuestas por usuarios, entre otros aspectos.

A continuación se ilustra paso a paso un Plan de Prueba utilizado para simular una carga de 50 usuarios solicitando la página principal en determinado sitio.

Estando en la interfase principal de JMeter (ilustrada anteriormente), en la columna izquierda debe observar un icono llamado Test Plan -- selecciónelo -- al llevar acabo este paso, en la ventana derecha aparecerán varias opciones, aquella encontrada en la parte superior le permite asignar un nombre a su plan de prueba, defínalo a su criterio. El resto de las opciones representan funcionalidades avanzadas que no serán descritas para esta simulación.

Definido el nombre, colóquese nuevamente en el icono Test Plan y oprima el botón derecho de su "mouse", del menú generado seleccione la opción Add -- Thread Group; para efectos prácticos un "Thread Group" es considerado el grupo de usuarios que desea simular para su aplicación.

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 10

Page 11: Test de Pruebas

Anexo Test de Pruebas

Ahora seleccione el icono Thread Group recientemente creado. Al llevar acabo este paso la ventana derecha mostrará la siguiente serie de opciones :

o name : Utilizado para definir un nombre más descriptivo sobre el grupo de usuarios, como : "Usuarios Esperados"

o number of threads : Equivale al numero de usuarios que se desean simular, en este caso utilizaremos 50.

o Ramp-up period : Es el lapso de tiempo en segundos que se desea tener entre cada grupo de usuarios ("Thread Group") , utilizaremos 15 .

o Forever : Utilizado para indicar si la simulación para grupos de usuarios ("Thread Group") será llevada acabo infinitamente, esto es, si selecciona esta opción indica que desea simular 50 usuarios, esperar 15 segundos ("Ramp-up period"), simular otros 50 usuarios y así sucesivamente. Para esta prueba es recomendable defina 10 ciclos para simular un total de 500 usuarios en cuestión de 150 segundos.

o Scheduler : Finalmente, esta opción permite definir tiempos de arranque para determinados grupos de usuarios ("Thread Group") , para efectos prácticos de esta simulación no será seleccionada esta opción y se iniciará la prueba a nuestra discreción.

Una vez definidas las características del grupo de usuarios ("Thread Group"), colóquese nuevamente en este icono de la columna izquierda y ahora seleccione la opción Add -- Sampler -- HTTP Request . Lo anterior genera un icono denominado HTTP Request utilizado para definir las requisiciones de simulación. Si selecciona este último icono aparecerán las siguientes opciones en la ventana derecha :

o Server Name o IP : Empleado para definir la dirección I.P o nombre del servidor donde será llevada acabo la prueba de carga, se utilizará 127.0.0.1 para indicar un servidor local.

o port number: Define el puerto TCP de operación del servidor, será empleado 80, que es el "default" para Servidores de Páginas .

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 11

Page 12: Test de Pruebas

Anexo Test de Pruebas

o path : Utilizado para definir la ruta de acceso para llevar acabo la prueba, será definido /index.html, típicamente la página principal de todo sitio para Internet.

Ahora debe colocarse en el icono de HTTP Request y oprimir el botón derecho de su "mouse", del menú generado seleccione la opción Add -- Listener -- Graph Results, así como Add -- Listener -- View Results in Table. Lo anterior le indica a JMeter que debe generar una gráfica y tabla (respectivamente) con los resultados obtenidos en la simulación.

Finalmente guarde su plan de prueba ("Test Plan") y ejecútelo seleccionando la opción Run -- Start del menú superior. Si se coloca en el icono Graph Results mientras se esta llevando acabo la simulación, puede observar como es construida interactivamente la gráfica de resultados.

Como ultima nota, es recomendable que cuando ejecute la presente prueba de carga también realice un análisis sobre el comportamiento del Hardware, para tener una perspectiva global acerca del sistema.

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 12

Page 13: Test de Pruebas

Anexo Test de Pruebas

1.3.2 Prueba de carga avanzada

La prueba ilustrada en la sección anterior lleva acabo solicitudes idénticas en todos sus ciclos, sin embargo, aunque este tipo de requisiciones simulan el comportamiento que puede tener determinado cliente (Navegador/"Browser"), carece de elementos específicos que puedan simular con mayor exactitud una carga de producción real.

A través de JMeter también es posible realizar requisiciones para que cada solicitud contenga parámetros únicos por usuario, de esta manera permitiendo simular clientes específicos. Una caso típico como este se puede presentar al intentar simular el registro simultáneo de varios usuarios en una aplicación, ya que cada cliente (Navegador/"Browser") emplea un usuario y contraseña distinta.

A continuación se ilustra paso a paso como llevar a cabo una prueba de esta naturaleza en JMeter.

La definición de usuarios con sus respectivos parámetros de requisición es llevado acabo en un archivo XML llamado users.xml; en el directorio bin de JMeter puede encontrar una muestra de este archivo, así como su respectivo DTD .

Para nuestra prueba utilizaremos un archivo users.xml con los siguientes datos :

<?xml version="1.0"?><!DOCTYPE allthreads SYSTEM "users.dtd">

<allthreads>

<thread><parameter>

<paramname>usuario</paramname> <paramvalue>asanchez</paramvalue> </parameter>

<parameter> <paramname>contraseña</paramname> <paramvalue>java</paramvalue> </parameter>

</thread>

<thread><parameter>

<paramname>usuario</paramname> <paramvalue>jperez</paramvalue> </parameter>

<parameter> <paramname>contraseña</paramname> <paramvalue>xml</paramvalue> </parameter>

</thread>

<thread><parameter>

<paramname>usuario</paramname> <paramvalue>tpadilla</paramvalue> </parameter>

<parameter>

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 13

Page 14: Test de Pruebas

Anexo Test de Pruebas

<paramname>contraseña</paramname> <paramvalue>puntonet</paramvalue> </parameter>

</thread>

<!-- Más usuarios ("Threads") en base a prueba -->

</allthreads>

Como puede notar, el archivo inicia con el elemento <allthread> que anida estructuras <thread>, como fue mencionado anteriormente y para efectos prácticos, cada "Thread" representa una requisición de usuario. A su vez, dentro de cada elemento <thread> se definen los Tags <parameter> -- empleado para definir parámetros por solicitud -- y estos a su vez incluyen, <paramname> -- utilizado para definir el nombre del parámetro -- , así como <paramvalues> para especificar su respectivo valor.

En resumen, el archivo anterior representa tres solicitudes de usuarios con dos parámetros por requisición : nombre y contraseña; el tipo de solicitudes generadas por JMeter serían idénticas a las creadas por una forma HTML / XHTML .

Un vez generado users.xml colóquelo en el directorio bin de JMeter, sobre-escribiendo el archivo muestra.

Realice los mismos pasos indicados en la prueba básica de JMeter en la definición del "Thread Group", modificando el numero de usuarios para reflejar aquellos definidos en users.xml, en este caso tres :

Una vez definidas las características del grupo de usuarios ("Thread Group"), colóquese nuevamente en este icono de la columna izquierda y ahora seleccione la opción Add -- Sampler -- HTTP Request . Lo anterior genera un icono denominado HTTP Request utilizado para definir las requisiciones de simulación.

Ahora es necesario asociar el grupo de usuarios definidos en nuestro archivo con las requisiciones, esto se logra colocándose en el icono HTTP Request oprimiendo el botón derecho del "mouse" y seleccionando la opción : Add -- Pre Processors -- HTTP

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 14

Page 15: Test de Pruebas

Anexo Test de Pruebas

User Parameter Modifier; en esta ventana puede observar que las instrucciones "default" son leer el archivo users.xml del directorio bin de JMeter :

Posteriormente, seleccione nuevamente el icono HTTP Request para definir sus otros parámetros en la ventana derecha :

o Server Name or IP : Empleado para definir la dirección I.P o nombre del servidor donde será llevada acabo la prueba de carga, se utilizará 127.0.0.1 para indicar un servidor local.

o port number: Define el puerto TCP de operación del servidor, será empleado 80, que es el "default" para Servidores de Páginas .

o HTTP Request - Method : Modifique el método de requisición a tipo POST, ya que el proceso a simular es de registro.

o path : Utilizada para definir la aplicación de servidor empleada para procesar la requisición, en esta caso definiremos un JSP en el directorio principal del servidor : /logon.jsp .

o Send parameters with the request : A través del icono Add debe agregar los parámetros que serán enviados por solicitud como fueron definidos en users.xml , lo único que debe definir son sus nombres, los valores son tomados automáticamente del archivo XML .

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 15

Page 16: Test de Pruebas

Anexo Test de Pruebas

Colóquese nuevamente en el icono de HTTP Request y oprima el botón derecho de su "mouse", del menú generado seleccione la opción Add -- Listener -- Graph Results, así como Add -- Listener -- View Results in Table. Lo anterior le indica a JMeter que debe generar una gráfica y tabla (respectivamente) con los resultados obtenidos en la simulación.

Finalmente guarde su plan de prueba ("Test Plan") y ejecútelo seleccionando la opción Run -- Start del menú superior. Si se coloca en el icono Graph Results mientras se esta llevando acabo la simulación, puede observar como es construida interactivamente la gráfica de resultados.

Como ultima nota, es recomendable que cuando ejecute la presente prueba de carga también realice un análisis sobre el comportamiento del Hardware, para tener una perspectiva global acerca del sistema.

1.4 Pruebas de aceptación: Solex

Mediante esta herramienta es posible grabar la navegación realizada, introducir variables y puntos de comprobación y repetir la misma de forma automática para verificar que el sistema se comporta de la forma esperada.

La información de este plugin se encuentra disponible en: http://solex.sourceforge.net/

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 16

Page 17: Test de Pruebas

Anexo Test de Pruebas

1.5 Conclusiones y recomendaciones

Una buena razón para escribir tests es que ganamos en eficiencia a corto, mediano y largo plazo: un control exhaustivo y automático de la aplicación nos permite garantizar su buen funcionamiento en forma rápida. Con JUnit los tests pueden ser ejecutados desde varios ambientes diferentes: la IDE (Eclipse, JDev, etc), Ant, Maven, línea de comandos.

En segundo lugar, escribiendo tests ganamos en calidad: contar con una batería completa de tests nos permite refactorizar el código cómodamente para introducir mejoras. La correcta ejecución de los tests nos da ciertas garantías sobre la calidad de la aplicación.

En tercer lugar, la escritura de tests aumenta nuestro nivel de confianza con la implementación porque sabemos que el estado actual de la aplicación está bajo control. Esto es particularmente importante cuando hay diferentes personas en el grupo de desarrollo: la correcta ejecución de los tests nos garantiza que la integración de nuevos desarrollos no corrompe la base de código existente. La escritura de tests cases también aumenta el grado de confianza a nivel individual, lo que se traduce en mayor satisfacción por el trabajo realizado.

Finalmente, la escritura de tests también contribuye a una mejor documentación de la aplicación; de hecho los tests constituyen el tipo de documentación que evoluciona junto con la aplicación. Qué mejor forma de documentar una clase que con una batería de test cases que muestran explícitamente cómo debe ser utilizada, con sus datos de entrada y salida?

Una cuestión fundamental es que los tests sean escritos por la misma persona que escribe el código de la implementación. La escritura de tests no puede delegarse en alguien que desconoce los detalles finos de la aplicación ya que los tests deben evolucionar junto con la implementación.

Por otro lado, el testeo no es algo que corresponda a una fase específica del proceso de desarrollo. Es algo que debemos hacer todo el tiempo. Sobre todo, no es algo que debamos postergar para el final. Idealmente, los tests unitarios deben escribirse antes que el código de la clase que se testea.

En ese mismo sentido debemos mencionar una metodología de desarrollo llamada Test Driven Development (TDD) que justamente nos alienta a escribir los tests antes que el código de la implementación.

La aplicación de ese principio nos obliga a reflexionar sobre las responsabilidades y servicios expuestos por las clases de tal manera que puedan ser testeadas fácilmente. El resultado es un diseño mucho más limpio, comprensible e intuitivo. Aunque muchos consideran que TDD es demasiado extrema en sus ambiciones, debemos admitir que es realmente efectiva como forma de trabajo porque nos ayuda a concentrarnos en las necesidades y requerimientos concretos del sistema, dejando de lado la implementación de funcionalidad innecesaria.

Sin duda alguna StrutsTestCase + JUnit es la mejor elección a la hora de desarrollar casos de prueba del mercado para aplicaciones basadas en Struts Action, tanto por la simplicidad del código, como por las funcionalidades únicas que ofrece a la hora de probar Actions, ActionForms, forwards, mapping y Tiles.

Estas librerías usadas conjuntamente con la clase TestCase de JUnit nos proveen de un potente sistema de desarrollo de casos de prueba, las siguientes recomendaciones aseguran en gran medida la robustez y calidad de la aplicación desarrollada:

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 17

Page 18: Test de Pruebas

Anexo Test de Pruebas

Separación del desarrollo de los distintos componentes de la aplicación por capas:

1. Desarrollo de clases de la capa de modelo.

En esta fase se construyen normalmente las clases de negocio, persistencia a base de datos del componente que vamos a desarrollar, etc...

Paralelamente y mediante el uso de la clase TestCase de JUnit vamos desarrollando casos de prueba unitarios para cada funcionalidad que vamos completando. Antes de continuar con el desarrollo debemos ser capaces de lanzar toda la batería de pruebas desarrollada sin errores.

2. Desarrollo de clases de la capa de control.

Una vez disponemos de las clases de la capa de modelo y estamos seguros de su buen funcionamiento gracias a los casos de prueba, empezamos a generar las clases de control, las clases Action y ActionForm.

Paralelamente desarrollaremos casos de prueba con las clases de StrutsTestCase. Generaremos una clase de prueba para cada uno de los ActionForm y cada una de las clases de acción con un caso de prueba para cada posible comportamiento de la acción, esto asegurará un comportamiento correcto de las acciones.

3. Desarrollo de capa de vista.

Una vez que hemos probado satisfactoriamente todos los casos de prueba de ambas capas podemos desarrollar la capa de vista, una vez terminado el desarrollo lanzaremos todas las baterías de pruebas y comprobaremos que el conjunto de la aplicación responde como era de esperar.

Es muy posible tener que modificar o ampliar la funcionalidad de las clases de negocio o de control debido a cambios producidos durante el desarrollo de otras capas, nunca hemos de olvidar crear o modificar casos de prueba que cubran los cambios realizados y asegurarnos de que todos ellos responden como es de esperar.

Subdirección General de Desarrollo, Tecnología e Infraestructuras. Página: 18