pruebas funcionales y pruebas de carga sobre aplicaciones web

15
Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web Javier Jesús Gutiérrez 1 , Rafael Pineda 2 , Darío Villadiego 3 , Maria José Escalona 1 , Manuel Mejías 1 Departamento de Lenguajes y Sistemas Informáticos Universidad de Sevilla 1 {javierj, escalona, risoto}@lsi.us.es, 2 [email protected], 3 [email protected], RESUMEN El proceso de prueba en el desarrollo de sistemas software permite evaluar la calidad de una aplicación. Sin embargo las estrategias clásicas de pruebas del sistema software no son sencillas de aplicar a los sistemas web debido a sus características intrínsecas como arquitectura cliente-servidor, mezcla de elementos heterogéneos (páginas HTML, lenguajes de script, etc.), necesidad de soporte de accesos concurrentes y altas cargas de trabajo, clientes web muy heterogéneos, etc. En este trabajo se documenta un caso práctico en el que se toma como base una aplicación web muy sencilla desarrollada utilizando HTML, PHP y MySQL, y sobre la que se aplican técnicas y herramientas open-source para desarrollar un conjunto de pruebas funcionales tanto en la interfaz HTML del lado cliente como en el código PHP del lado del servidor. Por último se desarrolla una prueba de carga o stress sobre toda la aplicación. 1. INTRODUCCIÓN. Internet proporciona a los desarrolladores una forma innovadora para construir software y un parque potencias de usuarios que se contabilizan por millones [4]. Por esta misa razón, los problemas que se presentan en una aplicación web, pueden afectar a cientos de miles de usuarios y pueden causar cuantiosas pérdidas [2], además de afectar también a las relación entre los usuarios y la entidad dueña de la aplicación web. Por este motivo las pruebas de software cobran una importancia vital en el desarrollo de aplicaciones web. Las primeras aplicaciones web tenían un diseño muy simple, basado en páginas estáticas HTML. Actualmente, las aplicaciones web son más sofisticadas e interactivas, con interfaces de usuarios, mediante páginas dinámicas. Analizar, evaluar, mantener y probar las aplicaciones web actuales presentan muchos y novedosos desafíos para los desarrolladores y los investigadores del software. A continuación, en este apartado, se definirán algunos conceptos básicos utilizados en todo el trabajo, se presentarán las características básicas de una aplicación web según el modelo cliente/servidor y se dará una breve definición del proceso de prueba del software. En el apartado 2 describiremos una sencilla aplicación web que servirá de ejemplo para aplicar las técnicas de pruebas vistas en este trabajo. En el apartado 3 describiremos como realizar pruebas unitarias sobre dicha aplicación. En el apartado 4 veremos como realizar pruebas de integración. En el apartado 5, como ejemplo de prueba de sistema, veremos como realizar una prueba de carga y en el apartado 6 las conclusiones. 1.1. Definiciones. Una página web es todo tipo de información que puede ser vista en una ventana del navegador [2]. Generalmente está compuesta por código HTML, generado de manera estática o dinámica, o por componentes ejecutables en el cliente, como un módulo Flash. Se llama sitio Web a una agrupación de páginas web, donde los elementos de las páginas están relacionados semánticamente por el contenido y sintácticamente a través de enlaces. El acceso a la aplicación web de los usuarios se hace mediante peticiones HTTP, y la interfaz más utilizada es un navegador web ejecutado en un PC. Generalmente, una aplicación web se construye utilizando diversas tecnologías, incluyendo los lenguajes de scripting que funcionan dentro del HTML en el cliente, los lenguajes interpretados que funcionan en el servidor, los lenguajes compilados en el servidor, las páginas de módulos en el servidor, los lenguajes de programación de propósito general (servicios web), se suelen utilizar servidores de bases de datos como almacenes de información. Estas tecnologías cooperan entre sí para construir

Upload: others

Post on 23-Jul-2022

29 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Javier Jesús Gutiérrez1, Rafael Pineda2, Darío Villadiego3, Maria José Escalona1, Manuel Mejías1

Departamento de Lenguajes y Sistemas Informáticos Universidad de Sevilla

1{javierj, escalona, risoto}@lsi.us.es, [email protected], [email protected],

RESUMEN El proceso de prueba en el desarrollo de sistemas software permite evaluar la calidad de una aplicación. Sin embargo las estrategias clásicas de pruebas del sistema software no son sencillas de aplicar a los sistemas web debido a sus características intrínsecas como arquitectura cliente-servidor, mezcla de elementos heterogéneos (páginas HTML, lenguajes de script, etc.), necesidad de soporte de accesos concurrentes y altas cargas de trabajo, clientes web muy heterogéneos, etc.

En este trabajo se documenta un caso práctico en el que se toma como base una aplicación web muy sencilla desarrollada utilizando HTML, PHP y MySQL, y sobre la que se aplican técnicas y herramientas open-source para desarrollar un conjunto de pruebas funcionales tanto en la interfaz HTML del lado cliente como en el código PHP del lado del servidor. Por último se desarrolla una prueba de carga o stress sobre toda la aplicación.

1. INTRODUCCIÓN. Internet proporciona a los desarrolladores

una forma innovadora para construir software y un parque potencias de usuarios que se contabilizan por millones [4]. Por esta misa razón, los problemas que se presentan en una aplicación web, pueden afectar a cientos de miles de usuarios y pueden causar cuantiosas pérdidas [2], además de afectar también a las relación entre los usuarios y la entidad dueña de la aplicación web. Por este motivo las pruebas de software cobran una importancia vital en el desarrollo de aplicaciones web.

Las primeras aplicaciones web tenían un diseño muy simple, basado en páginas estáticas HTML. Actualmente, las aplicaciones web son más sofisticadas e interactivas, con interfaces de usuarios, mediante páginas dinámicas. Analizar, evaluar, mantener y probar las aplicaciones web actuales presentan muchos y novedosos desafíos para los desarrolladores y los investigadores del software. A continuación, en este apartado, se definirán algunos conceptos básicos utilizados en todo el trabajo, se presentarán las características básicas de una aplicación web según el modelo cliente/servidor y se dará una breve definición del proceso de prueba del software. En el apartado 2 describiremos una sencilla aplicación web que servirá de ejemplo para aplicar las técnicas de pruebas vistas en este trabajo. En el apartado 3 describiremos como realizar pruebas

unitarias sobre dicha aplicación. En el apartado 4 veremos como realizar pruebas de integración. En el apartado 5, como ejemplo de prueba de sistema, veremos como realizar una prueba de carga y en el apartado 6 las conclusiones.

1.1. Definiciones.

Una página web es todo tipo de información que puede ser vista en una ventana del navegador [2]. Generalmente está compuesta por código HTML, generado de manera estática o dinámica, o por componentes ejecutables en el cliente, como un módulo Flash.

Se llama sitio Web a una agrupación de páginas web, donde los elementos de las páginas están relacionados semánticamente por el contenido y sintácticamente a través de enlaces. El acceso a la aplicación web de los usuarios se hace mediante peticiones HTTP, y la interfaz más utilizada es un navegador web ejecutado en un PC.

Generalmente, una aplicación web se construye utilizando diversas tecnologías, incluyendo los lenguajes de scripting que funcionan dentro del HTML en el cliente, los lenguajes interpretados que funcionan en el servidor, los lenguajes compilados en el servidor, las páginas de módulos en el servidor, los lenguajes de programación de propósito general (servicios web), se suelen utilizar servidores de bases de datos como almacenes de información. Estas tecnologías cooperan entre sí para construir

Page 2: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

este tipo de aplicaciones, obteniendose una aplicación multiplataforma.

1.2. Arquitectura Cliente/Servidor en aplicaciones web.

El funcionamiento de una aplicación Internet es análogo al de una aplicación cliente/servidor tradicional, tal y como se muestra en la ilustración 1. Al introducir una dirección web en un navegador, este actua como cliente y solicita un fichero localizado en un ordenador accesible por Internet, el cual actuará de servidor. El servidor procesará la petición y enviará este fichero y el navegador, al recibirlo, lo interpretará y mostrará la página web.

Cliente Servidor

Petición

Respuesta

Ilustración 1. Funcionamiento básico de una aplicación Internet

Las primeras aplicaciones web se reducían a un simple petición de una página ya creada; sin importar la fecha o la hora de la petición, siempre recibía el mismo fichero. En los sistemas web actuales, como se muestra en la ilustración 2, se un paso más y la página a mostrar se genera dinámicamente con contenidos personalizados.

Cliente Servidor

Petición

Respuesta

Código ejecutable en elservidor

Servidor debases de datos

Ilustración 2. Funcionamiento básico de una aplicación Internet dinamica.

En la ilustración 2, se muestra como el esquema anterior es idéntico en cuanto al modelo cliente/servidor. Lo único que cambia es el servidor, ya que ahora consta de dos bloques: uno que envía la página web y otro bloque que la genera dinámicamente.

1.3 Una introducción al proceso de prueba.

Hoy en día, debido al aumento del tamaño y la complejidad del software, el proceso de prueba se ha convertido en una tarea vital dentro del proceso de desarrollo de cualquier sistema software [3]. Para analizar cómo se pueden aplicar métodos de pruebas en metodologías web, es necesario realizar antes una clasificación de los tipos pruebas existentes, en que momento se aplican y cuales son sus objetivos. En la tabla 1, se recoge la clasificación de esas pruebas [5] dependiendo de su cometido y de la fase de desarrollo en que se realizan.

Tipos de pruebas

Momento de realización Descripción

Pruebas Unitarias.

Durante la construcción del sistema

Prueban el diseño y el comportamiento de cada uno de los componentes de forma aislada.

Pruebas de Integración.

Durante la construcción del sistema

Comprueban la correcta unión de los componentes entre sí a través de sus interfaces, y si cumplen con la funcionalidad establecida.

Pruebas del Sistema.

Después de la construcción del sistema

Prueban a fondo el sistema, comprobando su funcionalidad e integridad globalmente, en un entorno lo más parecido posible al entorno final de producción.

Pruebas del Sistema.

Después de la construcción del sistema

Prueban a fondo el sistema, comprobando su funcionalidad e integridad globalmente, en un entorno lo más parecido posible al entorno final de producción.

Pruebas de Implantación.

Durante la implantación en el entrono de producción.

Comprueba el correcto funcionamiento del sistema dentro del entorno real de producción.

Pruebas de Aceptación.

Después de la implantación en el entorno de producción.

Verifican que el sistema cumple con todos los requisitos indicados y permite que los usuarios del sistema den el visto bueno definitivo.

Tabla 1. Tipos de prueba.

Page 3: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Las pruebas unitarias y de integración verifican componentes del sistema mientras que las pruebas del sistema y posteriores verifican todo el sistema, considerándolo una caja negra.

2. DESCRIPCIÓN DEL EJEMPLO.

Se va a tomar como base para aplicar las pruebas descritas en los siguientes apartados una aplicación web muy simple cuya misión es insertar entidades clientes en una base de datos. La aplicación consta de una interfaz, compuesta por un formulario para la introducción de entidades clientes escrita mediante una página HTML con código de validación escrito en JavaScript, la lógica de negocio encargada de validar dicho cliente e insertarlo en la base de datos, escrita mediante un script en PHP [9], y una tabla donde almacenar las entidades clientes, alojada en un servidor de bases de datos MySQL

[8]. En la ilustración 3 se muestran los elementos que componen esta aplicación.

Cliente Servidor

Formulario declientes MySQL

Inserción declientes

Error - Cliente noalmacenado

Cliente almacenadocorrectamente

Código devalidación

Ilustración 3. Componentes de la aplicación

para inserción de clientes.

En la ilustración 4 se muestran capturas de pantallas de las páginas HTML.

Ilustración 4. Formulario de inserción de clientes.

El código de validación JavaScript en la interfaz HTML verificará que no se deje vacío ningún campo obligatorio del formulario.

El código SQL para el servidor MySQL que define la tabla donde se almacena la información se muestra en la tabla 2.

Page 4: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

CREATE TABLE Clientes(Id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, Entidad VARCHAR(50) NOT NULL, Actividad VARCHAR(250) NOT NULL, Direccion VARCHAR(50) NOT NULL, Localidad VARCHAR(50) NOT NULL, Codigo_Postal VARCHAR(10) NOT NULL, Telefono VARCHAR(50) NOT NULL, Persona_Contacto VARCHAR(50), Cargo VARCHAR(50), Telefono_Contacto VARCHAR(10), Observaciones VARCHAR(250) );

Tabla 2. Código SQL de la tabla de clientes.

Para probar la aplicación se desarrollará, en primer lugar, un conjunto de pruebas unitarias que verifiquen todos los componentes del lado cliente y del lado servidor. En segundo lugar se desarrollará una prueba de integración que verifique el correcto funcionamiento del formulario y del código de inserción trabajando juntos, que englobaremos las pruebas de integración y del sistema. En último lugar, cuando el sistema esté completo y las pruebas no indiquen ningún error, se realizará una prueba de carga para comprobar como se comporta ante grandes cargas de trabajo.

3. PRUEBAS UNITARIAS. Como se ha visto en el apartado 1.3, las pruebas unitarias tienen como objetivo probar la funcionalidad de cada componente de manera independiente al resto de los componentes. Para esto vamos a dividir los componentes a probar en dos grupo, los componentes del lado cliente, páginas web, código JavaScript, etc. y los componentes del lado del servidor, como ficheros de script y bases de datos [1]. En la aplicación de ejemplo, los elementos que pertenecen a cada división se muestran en la ilustración 5.

Cliente Servidor

Error - Cliente noalmacenado

Cliente almacenadocorrectamente

Código devalidación

Formulario declientes MySQL

Inserción declientes

Ilustración 5. Componentes del sistema del

lado cliente y del lado servidor.

Los componentes del lado cliente son aquellos que se descargan y ejecutan en el navegador, mientras que los componentes del lado servidor se ejecutan en el servidor y sus resultados se envían al cliente. A continuación se describe las estrategias y herramientas empleadas para probar los componentes del lado del servidor, en el apartado 3.1, y del lado cliente, en el apartado 3.2, de la aplicación.

3.1. Pruebas del lado servidor.

Queda fuera del objetivo de este trabajo probar los elementos relativos al servidor de bases de datos utilizados, por lo que nos centraremos solo en ver las estrategias de prueba para código ejecutable en el servidor. La estrategia para probar el correcto funcionamiento del código del servidor es muy similar a la estrategia para realizar pruebas unitarias cualquier otro lenguajes de programación para aplicaciones no web. La idea principal es escribir un fragmento de código (un script PHP en el sistema de ejemplo) de prueba que invoque al código que queremos probar con un conjunto de valores de prueba y verifique si el resultado es el esperado. Para facilitar y automatizar este proceso, existen una serie de herramientas que siguen la filosofía de la herramienta open-source JUnit [11]. Una lista de herramientas xUnit para distintas plataformas se puede encontrar en [7]. De entre todas las herramientas disponibles para código PHP se ha elegido PEAR PHPUnit [13]. La descripción de la prueba a realizar sobre el sistema de ejemplo es la siguiente: el sistema ofrece una función para insertar clientes, la cual admite como parámetro una tabla con toda la información del cliente y devuelve un resultado indicativo de si el cliente se insertó correctamente o hubo un error. El prototipo de esta función se muestra en la tabla 3. // $result vale TRUE si el cliente se // insertó correctamente en la // base de datos o FALSE en otro caso. function insertarCliente($cliente) { //... return $result; }

Tabla 3. Estructura de la función de inserción de clientes.

La prueba va a consistir en dos partes, las cuales se detallan en la tabla 4.

Page 5: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Paso Acción Verificación. 1 Llamar a la función

“insertarCliente” con un cliente de prueba

Verificar que el resultado de la función.

2 Buscar en la base de datos el cliente de prueba insertado en el paso anterior

Verificar que el cliente existe en la base de datos y sus valores coinciden con los valores del cliente de prueba.

Tabla 4. Pasos de la prueba.

El código del script en PHP que implementa esta prueba se muestra a continuación, en la tabla 5. Al ejecutar esta prueba, si la función “insertarCliente” no presenta ningún fallo se obtiene una salida como la mostrada en la ilustración 6, la cual indica que la prueba ha sido superada satisfactoriamente.

<? include_once('./PHPUnit/PHPUnit.php'); include_once('./FuncionInsertarCliente.php'); class InsertarClienteTest extends PHPUnit_TestCase { var $cliente_prueba; function testInsertarCliente() { $this->PHPUnit_TestCase("testInsertarUnCliente"); } function setUp() { $this->cliente_prueba['entidad'] = "prueba_entidad"; $this->cliente_prueba['actividad'] = "prueba_actividad"; $this->cliente_prueba['direccion'] = "prueba_direccion"; $this->cliente_prueba['localidad'] = "prueba_localidad"; $this->cliente_prueba['codigo_postal'] = "00000"; $this->cliente_prueba['telefono'] = "000-00-00-00"; } function testInsertarUnCliente() { $resultado = insertarCliente($this->cliente_prueba); $this->assertTrue($resultado); } function testClienteInsertado(){ $conn = mysql_connect("localhost", "", "") mysql_select_db("Clientes") $sql = "SELECT * FROM Clientes WHERE entidad='". $this->cliente_prueba['entidad']."'"; $resultado = mysql_query($sql) $cliente = mysql_fetch_array($resultado) ; $this->assertEquals($this->cliente_prueba['entidad'], $cliente['Entidad'], "Entidades distintas."); // El resto de campos se comprueban de la misma manera. mysql_free_result($resultado); } } // Fin de la clase. echo "<HTML> <BODY>"; echo "<HR>"; echo "<BR> Prueba Insertar Cliente. <BR>"; $suite = new PHPUnit_TestSuite("InsertarClienteTest"); $result = PHPUnit::run($suite); echo $result -> toString(); echo "<HR>"; ?>

Tabla 5. Prueba de la función de inserción de clientes.

Page 6: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Ilustración 6. Prueba superada con éxito.

3.2. Pruebas unitarias del lado cliente.

Las pruebas de los componentes de lado cliente van a tener como objetivo asegurar que el código HTML es correcto y cumple los estándares [15] y comprobar el funcionamiento de las partes dinámicas de las páginas, en este caso verificar el código JavaScript de validación del formulario. Otras pruebas que pueden encuadrarse en esta categoría son: verificar que las páginas se visualizan adecuadamente en los navegadores que usan los clientes, comprobar la usabilidad del diseño, etc. 3.1.1. Pruebas de páginas HTML. A diferencia de los scripts del lado del servidor, una página HTML no suele realizar ninguna tarea, sino que contiene la información que se debe mostrar y como debe mostrarse. Por tanto se ha decidido elaborar pruebas para verificar que cada página de la aplicación de ejemplo cumple con los estándares HTML propuestos por el consorcio W3C. En la página web del consorcio se puede encontrar una herramienta de validación de archivos HTML [14]. En la tabla 6 se muestra un resumen del proceso de prueba de las páginas HTML de la aplicación. La herramienta de validación proporciona una opción para subir la página a validar. En la aplicación de ejemplo, al validar el formulario de clientes aparecieron los siguientes errores:

Line 107, column 38: document type does not allow element "BODY" here <body bgcolor="#FFFFFF" text="#000000"> Line 108, column 75: there is no attribute "BORDERCOLOR" ... cellpadding="0" align="left" bordercolor="#0066FF">

El primer error está provocado porque antes de la etiqueta <body> debería ir el fin de etiqueta </head> El atributo “bordercolor” está obsoleto y no cumple la versión 4.0 de la especificación HTML [15], ya que se debe utilizar hojas de estilo para definir los colores. Una vez arreglado los dos errores, el archivo pasa la especificación y el la herramienta de validación muestra el siguiente mensaje: “This Page Is Valid HTML 4.01 Transitional!”. Las otras dos páginas web del sistema (la página de cliente insertado correctamente y la página de error) pasaron la validación sin necesidad de realizar modificaciones.

Tabla 6. Prueba del formulario HTML de inserción de clientes.

Para evitar tener que verificar uno a uno cada archivo y tener que subirlos de nuevo cada vez que se realice una modificación, existe la opción de indicarle una URL y la herramienta de validación verificará todos los archivos HTML que sea capaz de alcanzar a partir de dicha URL. También existen aplicaciones que realizan automáticamente la conexión con la herramienta de validación. 3.1.2. Prueba de código JavaScript. Como vimos en el punto 2, el formulario de clientes incluye también un script en lenguaje JavaScript para evitar campos obligatorios en blanco. Este código también es necesario probarlo para verificar que su comportamiento es correcto, esto es, que detecta todas las posibles combinaciones inválidas. Originalmente el código JavaScript se encontraba incrustado en la página HTML que contiene el formulario de clientes, lo cual dificultaba su prueba. Por este motivo, el código fue movido a su propio archivo (“validar.js”). En la tabla 7 se muestra un fragmento del código de validación del formulario.

Page 7: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

function Validador(FormularioClientes) { if (FormularioClientes.entidad.value == "") { alert("El campo \"Entidad\" es obligatorio."); FormularioClientes.entidad.focus(); return (false); } if (FormularioClientes.actividad.value == "") { alert("El campo \"Actividad\" es obligatorio."); FormularioClientes.actividad.focus(); return (false); } // Igual para los demás campos obligatorios. // .... return (true); }

Tabla 7. Fragmento del contenido del archivo "validar.js"

Este código avisará si algún campo se deja en blanco, y colocará el foco en el campo en

blanco, como se muestra en la ilustración 7 e ilustración 8.

Ilustración 7. Validación del formulario mediante JavaScript.

Page 8: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Ilustración 8. Detalle de la ventana de alerta.

La primera estrategia posible es validar el código manualmente, introduciendo todas las posibles combinaciones en el formulario a mano y comprobando que los resultados del código JavaScript son adecuados. Esta solución es la más rápida y sencilla de realizar, pero requiere la dedicación exclusiva de una persona, es propensa a fallos debido a ser una tarea repetitiva y es necesario repetir el proceso manual de pruebas cada vez que se modifique el formulario o el código JavaScript. Otra estrategia es desarrollar una prueba de código, escribiendo otro script en JavaScript que verifique si el código de “validar.js” se comporta correctamente para un conjunto de valores, de manera similar a la prueba realizada en el apartado 3.1. Como se debe comprobar el código de “validar.js” aisladamente, es necesario crear un objeto que represente el formulario, un fragmento del código que representa al formulario se muestra en la tabla 8. function entidad(valor) { this.value=valor; return(this); } // Una función similar por cada campo. // ... function FormularioClientes(e, a, d, l, c, t) { this.entidad=new entidad(e); this.actividad=new actividad(a); this.direccion=new direccion(d); this.localidad=new localidad(l); this.codigo_postal=new codigo_postal(c); this.telefono=new telefono(t); return (this); }

Tabla 8. Objeto que representa el formulario de clientes.

Una prueba que verifique el código de validación con la ayuda de este representante se muestra en la tabla 9. <SCRIPT LANGUAGE="JavaScript" SRC="validar.js"></SCRIPT> <SCRIPT LANGUAGE="JavaScript" SRC="formularioClientes.js"></SCRIPT> <SCRIPT LANGUAGE="JavaScript"> var form= new

FormularioClientes("","a", ”d", "l", "c", "t"); if (Validador(form) == false) { alert("Prueba no superada."); } else { alert("Prueba superada."); } </SCRIPT>

Tabla 9. Prueba del código JavaScript del formulario de clientes.

A partir de esta prueba se podrían desarrollar más pruebas similares cambiando la posición del campo que se deja en blanco en la creación del objeto formulario.

Sin embargo esta estrategia tampoco es una buena solución ya que, aunque comprueba que la función devuelve el valor esperado, no comprueba que el mensaje de alerta contenga el texto adecuado o que el foco del formulario se coloque en el campo vacío. Además, una vez ejecutado la instrucción “alert” del código de validación (validar.js) la ejecución de la prueba no continua, por lo que también hay que comprobar manualmente que se muestra la ventana adecuada, no obteniendo ninguna ventaja respecto a la comprobación manual. Otras posibles soluciones para mejorar la eficiencia de las pruebas de código JavaScript, que se plantean como futuras líneas de investigación, son utilizar un intérprete de JavaScript independiente del navegador o una herramienta de captura de pulsaciones de ratón. Este mismo proceso puede realizarse para verificar otros tipos de lenguajes ejecutables en el cliente, como por ejemplo VBScript.

4. PRUEBAS DE INTEGRACIÓN. Una vez verificado cada uno de los componentes mediante pruebas unitarias, es necesario comprobar que dichos componentes son capaces de trabajar correctamente en conjunto. Para ello desarrollamos pruebas de integración. Dado que los elementos del lado cliente y servidor en aplicaciones Web se comunican mediante HTTP en vez de mediante llamadas a métodos o funciones, las herramientas tipo xUnit utilizadas en el apartado anterior no son adecuadas para probar la integración de los componentes del lado cliente y servidor. Los dos métodos principales para realizar pruebas automáticas de aplicaciones Web a través de su interfaz de usuario son mediante macros grabadas que puedan reproducirse y

Page 9: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

mediante un API programático que analice las respuestas HTTP. Las macros grabadas requieren revisiones frecuentes y tienden a ser frágiles, ya que es necesario volverlas a grabar cuando cambia la interfaz. Un API programático permite escribir un programa que realice las peticiones HTTP adecuadas y recibe y analice las respuestas del servidor. Esta aproximación es más flexible, minimiza el mantenimiento de las pruebas y permite probar sistemas web que devuelven como respuesta páginas HTML muy variables o complejas. El lado negativo de las pruebas basadas en API con respecto a las macros grabadas es que la aproximación dirigida al API tardan más en construirse. Esta es la aproximación a utilizar en este trabajo. Existen varias herramientas open-source que permiten realizar esta tarea. La herramienta elegida para este caso práctico es HttpUnit [6]. A pesar de estar escrita en Java, esta herramienta permite probar todo tipo de aplicaciones web. En este caso la vamos a aplicar a una aplicación en PHP con una interfaz en HTML.

4.1. Escribiendo una prueba de integración.

Básicamente HttpUnit funciona como un cliente web que recibe una página y al que se le puede preguntar por los elementos que incluye esa página e interactuar con ella. Esta herramienta proporciona muchas de las funciones de un navegador: control de cookies, análisis de contenido HTML, envío de formularios meditante los métodos GET y POST, autentificación, y más. Vamos a escribir una clase Java que conecte con el servidor y solicite el formulario y después realizaremos una serie de comprobaciones sobre el formulario para verificar que todo está en orden y una serie de acciones para verificar que el funcionamiento es el deseado. La prueba va a realizar las siguientes comprobaciones:

1. Verificar que es capaz de conectar con el servidor y solicitar el formulario de clientes.

2. Comprobar que se ha recibido la página adecuada verificando su título.

3. Comprobar que la página contiene el formulario adecuado verificando su título.

4. Comprobar que existen todos los campos del formulario y asignarles valores de prueba.

5. Comprobar que al pulsar el botón "Añadir" se obtiene la página que indica que se insertó correctamente el cliente. El código de la prueba se puede ver en la tabla 10.

import net.sourceforge.jwebunit.WebTestCase; import com.meterware.httpunit.*; import com.meterware.servletunit.*; import java.util.*; import junit.framework.*; public class TestFormularioClientes extends TestCase { public TestFormularioClientes() { super("TestFormularioClientes"); } public void testInsertarCliente() throws Exception { WebConversation wc = new WebConversation(); WebResponse resp = wc.getResponse( "http://localhost/ /FormularioClientes.htm"); Assert.assertEquals(resp.getTitle().compareTo("Formulario Clientes"), 0); WebForm form = resp.getFormWithName("FormularioClientes"); Assert.assertNotNull(form); form.setParameter("entidad", "entidad_prueba"); form.setParameter("actividad", "actividad_prueba"); form.setParameter("direccion", "direccion_prueba"); form.setParameter("localidad", "localidad_prueba"); form.setParameter("codigo_postal", "00000"); form.setParameter("telefono", "00000"); form.setParameter("persona_contacto", "persona_prueba"); form.setParameter("cargo", "cargo_prueba"); form.setParameter("telefono_contacto", "00-00-00");

Page 10: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

WebRequest req = form.getRequest("Submit"); resp = wc.getResponse(req); String output = resp.getText(); Assert.assertEquals( output.indexOf("Error"), -1 ); Assert.assertNotNull( resp.getLinkWith("<<< Volver")); } }

Tabla 10. Prueba de integración para el formulario de clientes.

Al igual que en el apartado 3.1, sería posible añadir a la prueba una comprobación adicional que verificara que el cliente de prueba existe en la base de datos. Con ello verificaríamos que el script de inserción funciona correctamente no solo cuando se invoca directamente, sino cuado se invoca a través del formulario HTML.

5. PRUEBA DE CARGA. Cómo ejemplo de prueba del sistema se ha optado por desarrollar una prueba de carga. Una prueba de carga es un tipo de prueba que permite comprobar el rendimiento de un servidor o aplicación cuando el número de clientes o hilos que acceden al él de manera concurrentemente es elevado. Por ejemplo, para un servidor web, una prueba de carga típica será crear un conjunto de hilos que accederán simultáneamente al servidor, simulando de este modo clientes que acceden concurrentemente. Las pruebas de carga permiten verificar aspectos como la escalabilidad, tiempo de respuesta, consumo de memoria y de recursos. Estas pruebas ayudan a garantizar que el sistema funcionará en las peores circunstancias sin ningún problema crítico. También ayudan a detectar problemas de concurrencia y sincronización no detectados durante el desarrollo del sistema. Una prueba de carga también sirve para medir la escalabilidad y potencia de los servidores donde se aloje el sistema web.

5.2. Un ejemplo práctico.

Para el desarrollo de una prueba de carga sobre nuestro sistema hemos seleccionado la herramienta Jmeter [10]. Esta es una herramienta open.source cuyo objetivo es realizar simulaciones sobre cualquier recurso software. Jmeter ha sido desarrollado dentro del proyecto Apache Jakarta y ha sido escrita en Java. En sistemas web, Jmeter simula todas las funcionalidades de un navegador, siendo capaz de manipular resultados en determinada requisición y reutilizarlos para ser empleados en una nueva secuencia El componente principal de una prueba en Jmeter es denominado plan de prueba (test plan), donde 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. La prueba de carga a desarrollar va a tener dos partes. En la primera se comprobará como responde el sistema ante una petición masiva de acceso al formulario de clientes. En la segunda se comprobará la respuesta del sistema ante inserciones masivas de clientes. Aunque es posible escribir y ejecutar pruebas en JMeter desde la línea de comandos, se utilizará las facilidades de su interfaz gráficas. Todas las capturas que se muestran en este trabajo pertenecen a la versión 1.8. Se ha utilizado esta versión por requerir una cantidad de recursos sensiblemente inferior que la versión 2.0. Al iniciar la aplicación, se muestra la pantalla principal, como se recoge en la ilustración 9.

Page 11: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Ilustración 9. Pantalla principal desde la cual creamos una nueva prueba.

El primer paso es añadir un grupo de hilos. Este elemento va a simular los usuarios que van a solicitar el formulario. Se configura la prueba

para crear 20 usuarios que soliciten la página, cada uno de ellos 2 veces, con 40 accesos en total, tal y como se muestra en la ilustración 11.

Ilustración 10. Definimos un grupo de veinte usuarios que realizarán dos peticiones al servidor.

Ahora se indica la acción a realizar de cada hilo. Para ello se añade una petición HTTP para

acceder a la página del formulario, como se muestra en la ilustración 11.

Page 12: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Ilustración 11. Petición http que ejecutará cada hilo.

Para completar la primera parte de la prueba, se añade un elemento que permita ver los resultados de la prueba de manera gráfica. Una

vez hecho esto, ya se puede ejecutar la primera parte de la prueba. En la ilustración 12 se muestra el resultado de varias ejecuciones.

Ilustración 12. Resultados de la primera parte de la prueba.

Ahora se realizará la segunda parte de la prueba, la cual va a consistir en la inserción de varios clientes. Para ello se repiten los mismos pasos que en la primera parte, solo que ahora en la petición HTTP incluimos que llame

directamente al script de inserción (InsertarCliente.php), definiendo las variables del formulario que espera, como se muestra en la ilustración 13.

Page 13: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Ilustración 13. Definición de la petición que rellenará y enviará el formulario de clientes.

Por último, la ilustración 14 muestra una captura de los resultados de la ejecución de la segunda parte de la prueba.

Ilustración 14. Resultados de la segunda parte de la prueba.

Analizando estos resultados y modificando el número de hilos y repeticiones es posible comprobar como se comporta nuestra la aplicación y los servidores frente a un gran número de peticiones.

6. CONCLUSIONES.

Se ha visto en este trabajo como es posible desarrollar una aplicación web y realizar varias etapas de pruebas de la misma únicamente con tecnologías open-source. Todas las técnicas aquí presentadas son perfectamente aplicables a otras plataformas (ASP.NET, JSP Servlets) y

Page 14: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

para proyectos de mayor complejidad. Parte de las pruebas se realizan utilizando herramientas desarrolladas en la plataforma Java, con lo que se demuestra también la interoperabilidad de estas técnicas y herramientas a pesar de aplicarse sobre plataformas tecnológicas diferentes, en este caso HTML y PHP. Uno de los principales problemas en el desarrollo de este ejemplo práctico es la necesidad de trabajar en varias plataformas de programación. Se ha utilizado HTML para la interfaz de usuario, PHP para la lógica de la aplicación y Java para realizar las pruebas. Esto supone la necesidad de disponer de un equipo interdisciplinar especializado en varios lenguajes. El trabajar con componentes tan heterogéneos también impone la necesidad de conocer estrategias distintas de prueba y de disponer de un conjunto amplio de herramientas de pruebas, adaptas a cada tecnología, y de la formación adecuada para su uso. Todas las herramientas utilizadas son de libre descarga y uso a través de Internet y disponen de su código fuente accesible, incluso herramientas comerciales como MySQL. Es muy importante separar adecuadamente cada uno de los elementos que conforman un sistema, esto es, los elementos de presentación, como código HTML y los elementos de programación, como los scripts. Una correcta separación facilita el desarrollo, la mantenibilidad y, como hemos visto aquí, el proceso de prueba. Futuras líneas de investigación planteadas a partir de este trabajo son: profundizar en estrategias y herramientas para la prueba de JavaScript e interfaces escritas en HTML, estudiar ejemplos prácticos con otras plataformas (.NET, Java) y otro tipo de componentes (interfaces en Flash) y estudiar estrategias y herramientas para verificar aplicaciones donde el código HTML es generado dinámicamente en el servidor.

REFERENCIAS. [1] Ash, L. 2003. The Web Testing Companion:

The Insider’s Guide to Efficient and Effective Tests. John Wiley & Sons, Hoboken, USA.

[2] Ye Wu, Jeff Offutt, Xiaochen Du. 2004. Modeling and Testing of Dynamic Aspects of Web Applicationsy. Submitted for journal publication

[3] M.J. Escalona, M. Mejías, J.J. Gutiérrez, J. Torres. 2004. Métodos de Testing Sobre La Ingeniería De Requisitos Web de NDT. IADIS WWW/Internet 2.004. 353-360.

[4] Jeff Offutt et-al. 2004. Web Application Bypass Testing. ISSRE '04

[5] Métrica v3. http://www.csi.map.es/csi/metrica3/

[6] HttpUnit. http://httpunit.sourceforge.net/ [7] Herramientas xUnit.

http://www.xprogramming.com/software.htm [8] MySQL. http://www.mysql.com [9] PHP. http://www.php.net/ [10] Apache Jmeter.

http://jakarta.apache.org/jmeter/ [11] Junit. http://junit.org/ [12] Alguna referencia a pruebas unitarias. [13] PEAR PHPUnit.

http://pear.php.net/package/PHPUnit/ [14]W3C HTML Validator.

http://validator.w3.org/ [15] HTML 4.01 Specification.

http://www.w3.org/TR/html4/

RESEÑA CURRICULAR.

Javier J. Gutiérrez es Ingeniero Informático por la Universidad de Sevilla. Actualmente se encuentra realizando los trabajos de investigación conducentes a la tesis doctoral en el Departamento de Lenguajes y Sistemas Informáticos la Universidad de Sevilla. Sus áreas de estudio se sitúan en el proceso de pruebas en ingeniería del software, las metodologías ágiles de desarrollo y la evolución del modelo de software libre.

Rafael Pineda cursa actualmente el último curso en Ingeniería Técnica de sistemas en la Universidad de Sevilla. Actualmente trabaja en su proyecto de fin de carrera basado en pruebas en sistemas web.

Darío Villadiego se tituló como Ingeniero Técnico en Informática de Sistemas en la Universidad de Sevilla y actualmente trabaja en el desarrollo de sistemas web, compaginándolo con sus estudios en Ingeniería Superior Informática.

María José Escalona se doctoró en Lenguajes y Sistemas Informáticos en 2004 con una tesis basada en el aspecto navegacional de los sistemas web. Hasta 2001 trabajó como analista de sistemas para varios organismos públicos y actualmente trabaja como profesora en el departamento de Lenguajes y Sistemas Informáticos de la Universidad de Sevilla. Su trabajo de investigación está orientado hacia las metodologías de desarrollo y la Ingeniería web.

Manuel Mejías se tituló como ingeniero industrial en 1985 y se doctoró como Ingeniero Industrial en 1997 en la Universidad de Sevilla.

Page 15: Pruebas Funcionales y Pruebas de Carga sobre Aplicaciones Web

Ha trabajado como profesor en ingeniería del software en la Universidad de Sevilla desde 1987. Dr. Mejías ha centrado su actividad investigadora en técnicas de descripción formal,

modelado de sistemas orientados a objeto, procesos de desarrollo software, métricas y gestión de proyectos software.