pruebas de sistemas software

Aprobando Ingeniería del Software II http://www.byteando.com/juanignacio Comparto todos mis apuntes de IS2 de la Univers

Views 115 Downloads 1 File size 4MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

Aprobando Ingeniería del Software II http://www.byteando.com/juanignacio Comparto todos mis apuntes de IS2 de la Universidad de Alicante a modo de libro electrónico y se lo dedico, primero, a Davinia por estar siempre ahí y apoyarme, y segundo a todos aquellos estudiantes de últimos cursos que están puteados con estas últimas asignaturas y que suman un problema más en sus vidas. Juan Ignacio Alberola Colomo 17/05/2010

Aprobando Ingeniería del Software II 2010 Tema 1: Modelos de Proceso

2

Aprobando Ingeniería del Software II 2010 El Proceso Software. El proceso de desarrollo software implica el paso de una idea a un programa, a un software. El proceso en si es lo que hay que hacer para conseguir convertir esa idea en el programa y sean lo más parecidos posible. Este proceso tiene una serie de tareas que se pueden organizar de diferente manera, estas ordenaciones se conocen como modelos de proceso, que son las mejores maneras de organizar el proceso para satisfacer al cliente. Se puede decir que el modelo de proceso es una representación abstracta de un proceso de desarrollo software. El ingeniero software es el responsable de elegir el modelo adecuado para desarrollar el proyecto y tomar las decisiones adecuadas para entregar el proyecto con éxito. Todo proceso de desarrollo software tiene una serie de tareas básicas e indispensables, estas tareas son las de especificación (¿qué hay que hacer?), diseño e implementación (¿Cómo hay que hacerlo?), validación (¿Qué hay que probar? ¿Cómo lo probamos?), y evolución (¿cómo realizo y mantengo los cambios?). Estas tareas básicas se organizan de manera diferente en los diferentes modelos de proceso.

Modelos Genéricos. Disponemos de una serie de modelos de proceso genéricos que han ido surgiendo uno después de otro intentando suplir las carencias unos de otros. Estos modelos genéricos son: -

Modelo en cascada. Modelo evolutivo. Modelo basado en componentes.

Modelo en cascada. Considera las actividades fundamentales del proceso de desarrollo (especificación, desarrollo, validación y evolución) y los representa como fases separadas del proceso. Desde cada tarea se puede volver hacia atrás si se encuentran errores o cambian los requerimientos.

3

Aprobando Ingeniería del Software II 2010 Actividades: -

Análisis y definición de requerimientos: Los servicios, restricciones, y las metas del sistema se definen a partir de las consultas con los usuarios. Entonces, se definen en detalle y sirven como una especificación del sistema. Diseño del sistema: El proceso de diseño divide los requerimientos en sistemas software o hardware. Establece una arquitectura completa del sistema. En el diseño se identifican y describen las abstracciones fundamentales del software y sus relaciones. Implementación y pruebas unitarias: En esta etapa el diseño se lleva a cabo como un conjunto o unidades de programas. Las pruebas unitarias verifican que cada unidad implementada cumple sus especificaciones. Integración y pruebas del sistema: Las unidades se integran se prueban como un sistema completo para asegurar que se cumplen los requerimientos. Puesta en marcha y mantenimiento: Es la fase más larga. El sistema se instala y se pone en producción. El mantenimiento implica corregir fallos no detectados y mejorar la implementación.

-

-

-

Este modelo se puede usar para sistemas en los que tenemos los requerimientos MUY claros, están bien entendidos y son muy estables. Lo importante de los modelos, a parte de su organización es conocer sus ventajas y sus inconvenientes. Ventajas: -

Hace visible el proceso, nos podemos situar a lo largo del proceso y tenemos control sobre él. Facilita pues la labor del gestor. Se produce documentación en cada fase por lo que como hemos dicho es un proceso que facilita mucho la visibilidad.

-

Desventajas: -

El coste de subsanar omisiones o cambios en los requerimientos así como arreglar errores implica un alto coste debido a que se debe volver atrás en el proceso. Si el cliente no tiene claro lo que quiere este proceso no será el adecuado.

Modelo evolutivo. El desarrollo evolutivo se basa en la idea de desarrollar una implementación inicial, exponiéndola a los comentarios del usuario y refinándola a través de las diferentes versiones hasta que se desarrolla un sistema adecuado. Las actividades de especificación, desarrollo y validación se entrelazan en vez de separarse, con una rápida retroalimentación entre estas.

4

Aprobando Ingeniería del Software II 2010

Disponemos de dos tipos de modelos evolutivos: -

Desarrollo explorativo: se trabaja con el cliente para explorar sus requerimientos y entregar un sistema final. El desarrollo comienza con las partes del sistema que se comprenden mejor y se van integrando nuevos atributos propuestos por el cliente. Desarrollo prototipado: Más orientado a programas pequeños. Se empiezan con prototipos para las partes no claras y este siempre se ha de desechar. El prototipo solamente sirve para aclarar los requerimientos con los clientes y una vez claros se desarrolla una definición mejorada de los requerimientos para el sistema. Se puede usar junto a otros modelos.

-

Este modelo al igual que los otros, posee unas ventajas y unos inconvenientes: Ventajas: -

Suele ser más efectivo que el enfoque en cascada pues satisface las necesidades inmediatas del cliente. El desarrollo y la especificación se puede hacer de forma creciente. Tan pronto como los clientes entiendan mejor el problema se puede reflejar en el sistema software.

-

Desventajas: -

El proceso no es visible. Los administradores tienen que hacer entregas regularas para medir su progreso y si el sistema se realiza rápidamente puede no ser rentable generar documentación. Puede surgir una estructura deficiente. Los cambios continuos tienden a corromper la estructura del software haciendo que incorporar cambios sea cada vez una tarea más difícil y costosa.

-

Estos modelos se suelen usar en sistemas pequeños o medianos haciéndose los problemas típicos de estos modelos más graves en sistemas grandes y con un tiempo de vida largos. Para este tipo de sistemas grandes se recomienda un proceso mixto que incorpore las mejores prácticas de un modelo en cascada y del desarrollo evolutivo. Las partes del sistema bien comprendidas se pueden especificar y desarrollar usando cascada, las otras no tan claras como la interfaz de usuario se deben desarrollar usando un enfoque explorativo.

5

Aprobando Ingeniería del Software II 2010 Modelo basado en componentes. Se aprovecha de la reutilización de código de los proyectos SW. Se basa en la reutilización de componentes ya desarrollados o COTS (Commercial Of The Shelf).

Las etapas de especificación de requerimientos y validación son comparables a las de otros procesos pero intermediamente hay una variación en las tareas a realizar, estas son: -

Análisis de componentes: Una vez obtenida la especificación se buscan los componentes para implementar tal especificación. Normalmente no existe una concordancia al 100% y los componentes solo proporcionan parte de la funcionalidad deseada. Modificación de requerimientos: Durante esta etapa se ve si se pueden modificar los requerimientos para que se amolden a los componentes encontrados. Si no podemos modificar los requerimientos se puede volver a realizar el análisis de componentes para buscar soluciones alternativas. Diseño del sistema con reutilización: Se diseña o se reutiliza un marco de trabajo para el sistema. Los diseñadores tienen en cuenta los componentes y organizan el marco de trabajo de acuerdo a satisfacerlos. Si no hemos encontrado componentes posiblemente tendremos que implementar desde cero algunos módulos o cambiar componentes si tenemos acceso a su código. Diseño e integración: El software que no se puede conseguir se desarrolla y los componentes se integran en un único sistema.

-

-

-

De nuevo, ventajas e inconvenientes. Ventajas: -

Reduce la cantidad de software a desarrollar, reduciendo costes y riesgos. Permite entregar antes el software.

Desventajas: -

Los compromisos con los requerimientos son inevitables y esto puede dar lugar a que el sistema no cumpla las necesidades reales de los usuarios. Si las nuevas versiones de los componentes no están bajo el control de la organización se pierde el control sobre la evolución del sistema.

-

6

Aprobando Ingeniería del Software II 2010 Modelos Iterativos. Surgen para afrontar los cambios continuos que sufren los requerimientos de un software a lo largo de su desarrollo. Permitiendo las iteraciones del proceso modificar el trabajo de iteraciones anteriores. La esencia es que el desarrollo se produce en conjunción con la especificación, viene a ser lo mismo que se ha dicho en el párrafo anterior. Las iteraciones suelen ser de duración fija (entre 2 y 6 semanas) y para ellas se eligen un conjunto reducido de casos de uso o requerimientos a implementar. Durante ese tiempo solamente se afronta la implementación de esos casos de uso. Se dice entonces que son timeboxed. Si elegimos x casos de uso y vemos que no da tiempo a implementarlos en el tiempo estipulado no se retrasa o alarga la iteración sino que se elimina trabajo y se deja para la siguiente. Después de ese desarrollo se obtiene un sistema ejecutable, pero aún incompleto, es importante destacar que este sistema no es desechable, sino que ya es una parte del sistema final. Dentro de los modelos iterativos nosotros vamos a estudiar un par: -

Modelo incremental. Modelo en espiral.

Modelo incremental. Los clientes identifican, a grandes rasgos, los servicios que proporcionara el sistema y se identifican los más importantes y los menos. Después de esto se definen varios incrementos en donde cada uno proporciona un conjunto de la funcionalidad del sistema. La asignación de las funcionalidades a los incrementos depende de la prioridad, así normalmente los primeros incrementos tienen las funcionalidades más críticas. En los incrementos, cuando se decide lo que se va a implementar se congelan los requerimientos y no se pueden modificar. Además, cuando se acaba un incremento se le puede proporcionar al cliente para que lo pruebe.

7

Aprobando Ingeniería del Software II 2010 Ventajas: -

Los clientes no tienen que esperar hasta que el sistema esté completo para sacarle provecho. El primero incremento satisface los requerimientos más críticos de tal forma que se puede usar el software inmediatamente. Los clientes pueden usar los incrementos iniciales como prototipos y obtener experiencia sobre los requerimientos posteriores del sistema. Normalmente no suele fracasar el proyecto, pero se pueden encontrar problemas en algunos incrementos. Dado que lo más crítico se entrega antes y los incrementos posteriores se integran en ellos, hace que lo más crítico se pruebe más. Así se hace menos probable encontrar errores en parte críticas del sistema.

-

Desventajas: -

Los incrementos deben ser pequeños y se debe entregar alguna funcionalidad del sistema. Puede ser difícil adaptar el tamaño a la funcionalidad. Puede necesitarse algún recurso en todos los incrementos, pero como se implementa de manera incremental no nos daremos cuenta hasta que sea necesario.

-

Modelo en espiral. Este modelo también es iterativo. Cada ciclo de la espiral representa una fase del proceso software, de esta forma el ciclo más interno podría referirse a la viabilidad del proyecto, el siguiente a la definición de requerimientos, etc, aunque no hay fases fijas dando las vueltas necesarias dependiendo de lo que sea necesario. La principal característica de este modelo es que los riesgos se resuelven de forma explícita en cada vuelta de la espiral. Lo podemos usar como el modelo en cascada, pero con la diferencia de que se explicitan los riesgos, por lo que las vueltas hacia atrás no van a suceder tanto como en cascada.

8

Aprobando Ingeniería del Software II 2010 Cada ciclo, como se puede ver, se divide en cuatro secciones, en orden: -

Determinar objetivos, alternativas y restricciones: Se definen los objetivos específicos y se identifican las restricciones del proceso y del producto trazando un plan detallado de gestión. Además se identifican los riesgos y a partir de estos se planean estrategias alternativas. Evaluación y reducción de riesgos: Se analizan los riesgos identificados y se defienen los pasos para reducir tales riesgos. Desarrollo y Validación: Se desarrolla el sistema después de reducir los riesgos. Planificar siguiente fase: Si hemos acabado una fase, en esta sección se determina pasar a una nueva fase o bien seguir en la misma con otro ciclo de la espiral.

-

Modelos Ágiles. Este tipo de modelos surgen para subsanar los problemas de todos los anteriores, normalmente altos costes. Estos modelos: -

Se centran en el código en vez de en el diseño. Se basan en aproximaciones iterativas del desarrollo del software. Pretenden entregar software funcional rápidamente y evolucionar este también de forma rápida para satisfacer los requerimientos cambiantes.

Usados normalmente para sistemas de empresas pequeñas o medianas. Los principios básicos de todos los modelos ágiles son los siguientes:

9

Aprobando Ingeniería del Software II 2010 Programación Extrema XP. Posiblemente el método ágil más ampliamente utilizado. Se basa en el desarrollo iterativo de pequeños incrementos de funcionalidades. Sus aspectos básicos son: -

-

Desarrollo incremental: Llevado a cabo mediante entregas pequeñas del sistema además de frecuentes con unas pocas funcionalidades. Implicación del cliente: El cliente forma parte del equipo de desarrollo trabajando codo a codo con este. Son los responsables de establecer las pruebas de aceptación del sistema. Centrado en la gente, no en el proceso: Se programa por parejas, el código es de propiedad colectiva y se desarrolla en jornadas de trabajo no excesivas. Centrado en los cambios: Se hacen entregas regulares del sistema, con un desarrollo probado y una integración continua. Programación por parejas: Se trabaja en parejas, verificando cada uno el trabajo del otro para que no se escapen errores. Sentido colectivo: Las parejas trabajan en todas las áreas del sistema, así todos los desarrolladores conocen todo el sistema sin crearse lagunas de conocimiento. Pruebas e integraciones continúas: Cuando se acaba una tarea se integra en el sistema. Diseño simple: Diseño necesario solo para cumplir los requerimientos de unidad. Ritmo sostenible: Nada de horas extra, ya que se suele reducir la calidad del código y baja la productividad a medio plazo. Refactorización y mejora del código: Cuando se encuentran mejoras en el código, se introducen inmediatamente.

Los ciclos XP suelen ser cortos (1-3 semanas por iteración). Y cada 2 o 3 semanas se hace un plan para la iteración siguiente sin mucho detalle inicialmente para posteriormente ir desglosándolo. Normalmente se parte de escenarios (stories) que se dividen en tareas que se planifican. Después se desarrolla, integra y se prueba para hacer una release y evaluar el software. Luego, se vuelve a empezar con otros escenarios.

10

Aprobando Ingeniería del Software II 2010 Modelo RUP. Es un modelo relativamente moderno derivado del trabajo con UML. Es un modelo hibrido que integra características de cascada, iteraciones y ágil. Normalmente se definen tres perspectivas: -

Dinámica: Muestra las fases a lo largo del tiempo. Estática: Actividades que se llevan a cabo durante todas las fases. Práctica: Sugiere buenas prácticas.

Perspectiva dinámica. Fases. -

-

-

11

Inicio: Se establece un caso de negocio del sistema. Se identifican todas las actividades externas, tanto personas como sistemas que interactuaran con el sistema y se definen estas interacciones. Esa información se usa para evaluar la aportación que hace el sistema al negocio y si es de poca importancia se puede cancelar el proceso en esta fase. Elaboración: Se desarrolla una compresión del dominio del problema, se establece un marco de trabajo arquitectónico y un plan del proyecto que identifica los riesgos clave. Al finalizar se tiene un modelo de los requerimientos, una descripción arquitectónica y un plan de desarrollo. Construcción: Se diseña el sistema, se programa y se hacen pruebas. Se tiene el SW operativo y la documentación. Transición: Se pone el sistema en producción, generando instalaciones, distribuyendo el sistema, etc.

Aprobando Ingeniería del Software II 2010 Perspectiva estática. Actividades o flujos de trabajo: -

Modelado del sistema: Se modelan los procesos de negocio usando los casos de uso del negocio. Requerimientos: Se definen los requerimientos funcionales y no funcionales haciendo casos de uso para los primeros. Análisis y Diseño: Se crea y documenta un modelo de diseño usando modelos arquitectónicos, modelos de componentes, de objetos y de secuencia. Implementación: Se implementan los subsistemas como componentes. Pruebas: Se llevan a cabo junto con la implementación. Despliegue: Release del producto y puesta en producción. Gestión de configuraciones: Gestión de los cambios en el sistema. Gestión del proyecto: Gestión del desarrollo del sistema. Entorno: Identificar las herramientas que se van a usar.

Perspectiva práctica: -

Desarrollo iterativo: Planificar incrementos con la prioridad de los mismos para el cliente Gestión de requerimientos: Documentación explícita de los mismos al mismo tiempo que estar al tanto de los posibles cambios. Modelado visual del software: UML para presentar vistas estáticas del sistema. Verificación de calidad: Asegurarse que cumple estándares de calidad. Control de cambios: Usar un sistema de gestión de cambios y procedimientos para gestionarlos.

Se verás mas de RUP en el material adicional y en las prácticas del tema.

12

Aprobando Ingeniería del Software II 2010 Tema 2: Gestión de Proyectos

13

Aprobando Ingeniería del Software II 2010 En este tema se estudia el tema de la gestión de proyectos, es una actividad que se lleva a cabo durante todo el proceso de desarrollo y se puede considerar una actividad paraguas ya que lo envuelve desde principio a fin. Un ejemplo de esto lo tenemos en RUP como disciplina de soporte llevada a cabo en cada una de las fases e iteraciones. Es importante conocer a qué se dedica el gestor de proyectos, por eso se empieza estudiando las actividades de gestión entre las que está la creación de una agenda para el proyecto y su control y monitorización. Estos tres puntos son los esenciales en el tema.

Actividades de de gestión. El gestor de proyectos se encarga de varios asuntos, entre ellos elabora un plan de proyecto que contempla la creación de una agenda, además hace estimaciones de coste y tiempo, se evalúan los riesgos y se organiza al personal. También monitoriza y controla el plan del proyecto, identificando los hitos y entregas del proyecto además el gestor debe tener conocimiento del progreso del proyecto y comparar el progreso con lo que se había planificado. Selecciona al personal basándose en sus conocimientos y su disponibilidad. En un entorno ideal todos sabrían de todo y estarían disponibles al 100% con la experiencia necesaria, pero normalmente se elige un equipo profesional mínimo capaz de desarrollar el trabajo basándose en sus conocimientos y en su personalidad. Por último, el gestor debe rendir cuentas, creando y presentando informes. Debe informar a los clientes y contratistas sobre el proyecto, en consecuencia, la habilidad de comunicarse tanto por escrito como oralmente es esencial para el gestor. De hecho, es un asunto que Galipienso busca en los objetivos de la asignatura, la capacidad de comunicarnos y escribir bien. El OBJETIVO FINAL es entregar el proyecto a tiempo, sin exceder el coste estimado y satisfaciendo las necesidades del cliente. Volviendo al plan del proyecto, en la planificación se decide de antemano QUE hay que hacer, COMO hay que hacerlo, CUANDO hay que hacerlo y QUIEN lo va a hacer. Esto es importante pues en el examen no hay porque enrollarse, simplemente si se pide un plan de proyecto debemos contestar a estas cuestiones de forma resumida. La buena gestión del proyecto depende de planificar completamente el progreso del proyecto. El gestor se anticipa a los problemas que pueden surgir y prepara soluciones a estos problemas. Un plan preparado al inicio de un proyecto debe usarse como conductor para el proyecto y debe ser el mejor posible de acuerdo con la información disponible. El plan evolucionará conforme el proyecto avance y se disponga de más información. Para planificar un proyecto existen diversos algoritmos, pero en la asignatura nos ponen uno que es el siguiente, se adjunta la imagen de las transparencias y a continuación se explica cada apartado.

14

Aprobando Ingeniería del Software II 2010

Las actividades en azul son actividades de creación del plan y las que están en rojo son actividades de monitorización. Los dos siguientes apartados se van a centrar exclusivamente en confeccionar la agenda y en monitorizar el progreso del proyecto. Pero ahora veamos cada actividad de la planificación. Establecer objetivos, ámbito y restricciones del proyecto: Se decide que es lo que se quiere hacer, los límites del proyecto y su dominio así como los requisitos funcionales y no funcionales, de tiempo, coste, personal y maquinaria disponible. Definir hitos y entregas: Servirá para monitorizar el proyecto y darle visibilidad. Estimar recursos: Vemos cuanta gente vamos a necesitar en función del tamaño y complejidad del proyecto. Organizar al grupo de trabajo: Asignar trabajo al personal y decidir cuándo lo va a hacer. Determinar estándares de calidad: Poner en común prácticas entre el equipo para que el proyecto sea lo más uniforme posible. Determinar riesgos: Pensar en los problemas que pueden surgir y anticipar soluciones. Organizar comunicación del grupo: Dependiendo de cómo se comunique el equipo el proyecto avanzará más rápidamente o no. Confeccionar una agenda: Identificar las tareas y sus dependencias. Definir presupuesto: Escribir plan: Contestar a QUE, COMO, QUIEN y CUANDO. Este último plan puede tener diferentes formatos, pero el que nos dan en las transparencias es el siguiente. I O A R D A M.

15

Aprobando Ingeniería del Software II 2010 Introducción: Describe brevemente los objetivos del proyecto y expone las restricciones que afectan a la gestión del mismo. Organización del proyecto: Describe la forma en la que el equipo de desarrollo está organizado, la gente involucrada y sus roles en el equipo. Modelo de proceso con sus actividades y orden. Análisis de riesgos: Describe los posibles riesgos del proyecto, la probabilidad de que surjan estos riesgos y las estrategias de reducción de riesgos propuestos. Requerimientos hardware y software: Describe el hardware y el software de ayuda necesario para llevar a cabo el desarrollo además si es necesario comprar hardware o software se incluye su coste. Descomposición del trabajo (WBS): Describe la división del proyecto en actividades e identifica los hitos y las entregas. Agenda del proyecto: Describe las dependencias entre actividades, el tiempo estimado requerido para alcanzar cada hito y la asignación de gente a esas actividades. Mecanismos de monitorización e informes: Cuándo se deben generar informes asi como los mecanismos de supervisión a usar.

Confección de agendas. El siguiente proceso de confección de agendas sirve como hilo conductor para lo que resta de tema.

Los gestores estiman el tiempo y los recursos requeridos para completar las actividades y organizarlas en una sucesión coherente. A menos que el proyecto a calendarizar sea similar a otro anterior las estimaciones previas son una base no cierta para este proceso. Los calendarios se deben actualizar conforme se vaya obteniendo nueva información. Las primeras actividades del proceso de creación de agendas (identificar actividades y dependencias entre actividades) no nos resultan nuevas pues es lo que se estudió en el primer

16

Aprobando Ingeniería del Software II 2010 tema y viene influenciado por el modelo de proceso a seguir. Las salidas o representaciones de la agenda pueden ser varias, los diagramas de actividades muestran las dependencias entre ellas y los diagramas de barras el tiempo que llevan dichas actividades. Si nos centramos en la identificación de actividades vemos que la entrada son los requisitos software y la salida es un WBS o Work Breakdown Structure. Un WBS identifica las actividades del proyecto y las estructura por niveles de abstracción de forma jerárquica. Los WBS nos ofrecen una vista de todo el trabajo significativo, una descomposición clara en tareas para la asignación de responsabilidades y un marco para la confección de la agenda y la estimación y monitorización de costes. Hay que tener en cuenta que NO es un WBS, no es un plan del proyecto ni una agenda, ni una cronología de realización de actividades. Al identificar las actividades también se deben identificar los hitos y las entregas. Las actividades deben organizarse para producir salidas tangibles para dar visibilidad al proyecto y ver el progreso del mismo para favorecer la gestión. Como el software es intangible la información solo se puede proveer como documentos que describen el estado del software. Los hitos o milestones son instantes de tiempo que marcan el final de alguna actividad del proceso de desarrollo SW. En cada uno debe existir una salida formal, como un informe que se deba presentar al gestor y no demasiado amplios. Los hitos implican una monitorización y control del trabajo realizado. Las entregas son resultados del proyecto que se entregan a los clientes. La parte importante está en saber cuánta visibilidad dar al proyecto y definir la cantidad de hitos para que el proyecto sea exitoso. Después de identificar las actividades hay que ver si existen dependencias entre ellas e identificarlas. Necesitamos saber por ejemplo si una actividad debe haber finalizado por completo antes de que otra pueda empezar, o puede que una actividad no pueda empezar después de un cierto tiempo después de que acabe otra (lag) o también puede que estemos condicionados por otro tipo de restricciones como que una actividad deba acabar o empezar lo antes posible. En MS Project tenemos varias dependencias entre tareas. FC o Finalizar para Comenzar: Una tarea no empieza hasta que otra acabe. CC o Comenzar para Comenzar: Empiezan a la vez. FF o Finalizar para Finalizar: Finalizan a la vez. CF o Comenzar para Finalizar: Una tarea no acaba hasta que empieza otra. Además de las dependencias tenemos otras restricciones sobre las fechas o delimitaciones.

17

Aprobando Ingeniería del Software II 2010 Sin fecha: Empezar lo más pronto posible o lo más tarde posible. Semiflexibles: No empezar antes de X. Inflexibles: Empezar en X. Volviendo al proceso de creación de agendas, lo que sigue es la estimación de recursos y la asignación de estos a las tareas. Los recursos pueden ser de varios tipos, por ejemplo, de trabajo refiriéndose a gente y equipamiento, de materiales o de coste. Una tarea además puede requerir más de un recurso. Estos recursos no pueden estar disponibles el 100% de su tiempo, sobre todo los de trabajo (gente) así que la asignación de recursos a las tareas se hará en base a la disponibilidad de estos Para asignar los recursos primero se estiman los recursos necesarios para cada tarea en base al ESFUERZO requerido para finalizar dicha tarea y luego se asignan los recursos a cada actividad. El esfuerzo de una tarea es el tiempo necesario para acabarla, no hay que confundirlo con la duración pues esta dependerá de los recursos asignados. La duración normalmente se mide en días y el esfuerzo en horas. Además cada recurso asignado a tareas tiene una disponibilidad D al día, por ejemplo, 8 horas. Esfuerzo, duración y recursos no se pueden contemplar de manera independiente, están interrelacionados entre ellos de la manera siguiente, según las herramientas automáticas de gestión de proyectos. Esfuerzo = duración * disponibilidad al día. Realmente esta relación es exponencial, como ya se verá, pero los programas automáticos solamente hacen cálculos y usan esta fórmula. Estas herramientas no hacen estimaciones, solo cálculos. En MS Project, basándonos en la anterior ecuación, si dejamos alguno de los campos fijos se recalculan los demás en base a la siguiente tabla.

Si estamos con la duración fija y la actividad es condicionada por el esfuerzo, la asignación de más recursos reduce los valores de la unidad individual de cada recurso. O sea, que si metemos más recursos, estará cada uno menos disponible.

18

Aprobando Ingeniería del Software II 2010 Si la tarea únicamente está condicionada por el esfuerzo modifica la duración si se añaden o quitan recursos. El trabajo o esfuerzo permanece constante Una vez que tenemos todas las entradas en el programa (actividades, relaciones, duraciones y recursos) se hacen unos CALCULOS. Fechas de inicio y fin más tempranas y tardías de las actividades. Holguras totales y libres de las actividades. Una holgura total es el tiempo que una actividad puede retrasarse sin retrasar el proyecto entero. Una holgura libre es el tiempo que una actividad puede retrasarse sin retrasar las actividades dependientes de ella. El camino crítico es aquel formado por actividades con holgura total igual a cero. Y es importante saber que puede haber más de un camino crítico. Con esto podemos ir monitorizando la agenda adelantando o retrasando tareas según sea necesario respondiendo ante problemas que se vayan presentando a lo largo del desarrollo.

Monitorización y control. Una vez realizada la agenda, hay que ir controlándola y tomando decisiones con el objetivo principal de entregar el proyecto a tiempo con los costes apropiados. El 70% de los proyectos cuestan más de lo presupuestado o se entregan más tarde de lo planificado y el 52% de ellos se entregan con un 189% de lo presupuestado. Otros muchos ni se entregan. Monitorizar o hacer un seguimiento a una agenda consiste en comprobar si la agenda planificada se ajusta con la agenda real. A la agenda inicial la llamaremos agenda planificada, es la que hemos creado siguiendo los pasos del apartado anterior basada en nuestra intención inicial y estimaciones. La agenda real es lo que realmente está sucediendo con el proyecto a partir de información real. Para hacer la monitorización se necesitan datos que ofrezcan una visión cuantitativa de la agenda, estos datos son métricas del proyecto. Se pueden usar varias de ellas, por ejemplo, la holgura libre dice lo que se puede retrasar una tarea sin afectar a las demás. En MS Project para hacer el seguimiento de una agenda hay que seguir el siguiente procedimiento. -

-

19

Guardar línea base del proyecto: Esto se hace a través de la opción Proyectos  Herramientas  Establecer línea base. Los campos duración, trabajo, comienzo, fin y costo se guardan como valores PREVISTOS. Establecer fecha de estado: Definimos en qué fecha nos encontramos a través de las opciones Proyecto Información del proyecto  Fecha de estado.

Aprobando Ingeniería del Software II 2010 -

Introducir datos reales: HerramientasSeguimientoActualizar tareas. Con esto los valores que estaban previstos pasan a ser REALES. Comparar el progreso: A través de una vista Gantt de seguimiento.

Entre las métricas anteriormente nombradas existen varias más como por ejemplo: -

Fechas de inicio y fin. Duraciones. Holguras. Análisis del Valor Acumulado (EVA)

Pero la cuestión importante es el USO de estas métricas para controlar y monitorizar una agenda. Controlar una agenda consiste en tomar las decisiones adecuadas para que las diferencias entre las agendas planificada y real sean mínimas partiendo de que las actividades críticas (con holgura total igual a cero) no se pueden retrasar y que las actividades no críticas se pueden retrasar siempre y cuando el retraso no supere su holgura total. Earned Value Analysis (EVA). El Valor Acumulado es una métrica, tal y como se vio en el apartado de métricas. Esta métrica en concreto proporciona una información cuantitativa del progreso de un proyecto asignando a cada tarea un valor devengado basado en su porcentaje estimado del valor total. EVA permite vislumbrar dificultades antes de que estas sucedan lo que permite tomar decisiones antes que el proyecto entre en crisis y la liemos parda. Un EVA siempre se realiza en un momento determinado del tiempo y básicamente usa y compara tres tipos de información: -

¿Cuánto trabajo (del planificado) debería haberse realizado hasta el momento? BCWS. ¿Cuánto se ha gastado hasta el momento? ACWP. ¿Cuál es el valor (en términos de línea base) del trabajo realizado hasta el momento? BCWP.

Un ejemplo de estos tres parámetros se puede encontrar en las transparencias 42, 43 y 44 seguidas en clase. Otro parámetro es el BAC o trabajo planificado al final del proyecto. -

Si BAC = BCWS: La tarea debería haber acabado ya. Si BAC > BCWS: La tarea aun no ha acabado. Para ver el porcentaje hecho de la tarea se divide BCWS/BAC.

Veamos ahora el funcionamiento de EVA. Indicadores de PROGRESO. -

20

Schedule Variance (SV) = BCWP – BCWS.

Aprobando Ingeniería del Software II 2010 -

Schedule Performance Index (SPI) = BCWP / BCWS. Si BCWP > BCWS la tarea o proyecto va adelantada según la agenda planificada. Un SPI de 1.5 significa que sólo se ha usado un 67% del tiempo planeado para completar una parte de la tarea en un determinado periodo de tiempo. Para saber el porcentaje se hace el SPI al revés, o sea, BCWS / BCWP.

Indicadores de PRODUCTIVIDAD. -

21

Cost Variance (CV) = BCWP – ACWP. Cost Performance Index (CPI) = BCWP/ACWP. Si BCWP > ACWP la tarea o proyecto está gastando menos de lo planificado. Un CPI de 0.8 significa que se está gastando un 25% más de lo que estaba planificado (por cada € planificado se está gastado 1.25€) para saber esto hay que hacer el CPI pero al revés ACWP / BCWP.

Aprobando Ingeniería del Software II 2010 Tema 2: Gestión de proyectos - Ejercicios

22

Aprobando Ingeniería del Software II 2010 ¿Qué modelo de proceso representa la siguiente agenda?

Representa un modelo en cascada, se pueden ver fácilmente las distintas actividades del proceso de desarrollo (Requerimientos, Análisis y Diseño, Implementación, Pruebas y Despliegue). Por otro lado se puede considerar que tiene tintes de un desarrollo evolutivo ya que se presenta un prototipo intercalándolo con los requerimientos. ¿Qué estilo de plan elegirías como gestor de proyecto?

El segundo, ya que indica claramente la salida de cada tarea, el primero serviría en todo caso para alguna plantilla genérica. Recalcular los valores para la siguiente tarea con las unidades (recursos) fijos.

Vamos a seguir la ecuación para recalcular que usa MSProject que es Trabajo = Duración x Unidades. De esta manera. Si duración se cambia a 2 días el trabajo se recalcula y 2*8 = 16. El trabajo cambia a 16.

23

Aprobando Ingeniería del Software II 2010 Si el trabajo se cambia a 32 horas entonces la duración se recalcula 4*8 = 32. La duración es de 4 días. Si las unidades se reducen a la mitad la duración aumenta proporcionalmente, si eran 3 días ahora es el doble al reducir las unidades a la mitad. La duración es de 6 días. Recalcular los valores para la siguiente tarea con la duración fija.

Igual que en el ejercicio anterior pero dejando la duración fija. Si se cambia la duración a 2 dias se recalcula el trabajo a 16 horas. Si se cambia el trabajo a 32 horas Lucas estará sobreasignado ya que al ser la duración fija necesitaría trabajar 10.6 horas al día para completar la tarea en 3 días. Si las unidades se reducen a la mitad el trabajo se recalcula a la mitad. Ahora es de 12 horas. Ejercicios sobre holguras.

¿Qué pasa si A se retrasa 3 días? No pasa nada, el proyecto no se retrasa y B puede comenzar lo antes posible. ¿Qué pasa si A se retrasa 4 días? El proyecto no se retrasa pero la holgura total de A se reduce en 4 y pasaría a ser 2, por otro lado la holgura total de B pasaría a ser 2. ¿Qué pasa se A se retrasa 6 días? El proyecto no se retrasa pero las dos actividades se convierten en críticas al consumirse en ambas toda su holgura total.

24

Aprobando Ingeniería del Software II 2010 Realizar un análisis cuantitativo del progreso de las siguientes tareas.

Con MSExcel he resuelto la tabla que hay que analizar siguiendo las fórmulas adecuadas. SV = BCWP – BCWS. SPI = BCWP / BCWS. CV = BCWP – ACWP. CPI = BCWP / ACWP. BAC 1000 1500 6000 1000 1000 2000

BCWS 1000 1500 5000 500 500 1000

BCWP 1000 1000 4000 0 500 1500

ACWP 1200 1500 4500 0 750 1500

SV 0 -500 -1000 -500 0 500

CV -200 -500 -500 0 -250 0

SPI 1 0,66666667 0,8 0 1 1,5

CPI 0,83333333 0,66666667 0,88888889 0,66666667 1

Tarea 1. La tarea debería haber acabado según lo planificado pues BAC = BCWS. Por otro lado la tarea se está ejecutando según la agenda ya que SV=0. Vemos también que la tarea ha acabado porque BAC = BCWS = BCWP. Por otro lado hemos gastado más de lo presupuestado, concretamente 20% más, esto quiere decir que por cada € presupuestado estamos gastando 1.20€. Tarea 2. La tarea debería haber terminado según lo planificado pues BAC = BCWS. Por otro lado la tarea va con retraso porque SV = -500, se ha completado un 66% de la tarea. Estamos gastando más de lo presupuestado, concretamente 1.5€ por cada € presupuestado. Tarea 3.

25

Aprobando Ingeniería del Software II 2010 La tarea aun no ha acabado según lo planificado, de hecho llevaría el 83% según lo planificado. Va retrasada porque SV < 0, concretamente lleva un 80%. Por otro lado por cada € presupuestado hemos gastado 1.125€. Así que en un 80% completado hemos gastado 500€ más. Tarea 4. Debería llevar el 50% según lo planificado, pero no ha empezado. Tarea 5. La tarea aun no ha acabado, según lo planificado lleva el 50%. SV = 0 nos indica que la tarea se está llevando a cabo según la agenda pero hemos gastado 250€ más de lo que había presupuestado, esto quiere decir que por cada € presupuestado hemos gastado 1.5€. Tarea 6. Según lo planificado no ha acabado y debería llevar el 50%. La tarea va adelantada en un 50%. Para completar lo que se lleva de tarea se ha usado un 67% del tiempo estipulado y de momento se ajusta al presupuesto sin gastos de más.

26

Aprobando Ingeniería del Software II 2010 Tema 3: Estimación de Proyectos

27

Aprobando Ingeniería del Software II 2010 INTRODUCCIÓN. DEFINICIONES. Una estimación es un proceso analítico para predecir el coste y la duración de un proyecto que ofrece unas ciertas funcionalidades. Se puede entender el proceso analítico como un análisis de unos datos de entrada que producen una salida que en este caso es la predicción. Esta predicción puesto que nadie es adivino es difícil acertar de pleno. Las estimaciones siempre llevan una probabilidad asociada ya sea explícita o implícita, por ejemplo si decimos que un proyecto estará acabado en 10 días asumimos con el 100% de certeza que en 10 días estará acabado, esto no es realista, no se hacen predicciones con un solo valor. Las predicciones deben entrar en un intervalo razonable, se debe dar un rango de valores lo suficientemente amplio como para que la probabilidad de que el valor correcto pertenezca al rango sea lo más alta posible, si es posible cercana al 100%. Las estimaciones deben ser lo más exactas posible aunque normalmente nos quedaremos por arriba o por abajo lo que tendrá sus consecuencias. Por ejemplo las estimaciones optimistas, es decir, en las que suponemos que acabaremos antes de lo que en realidad sucederá conducen a un fracaso del proyecto y a generar más errores debido al estrés de los programadores que a su vez verán su salud minada. Por otro lado se empleará más tiempo en reuniones para la reconducción del proyecto. Por otro lado las estimaciones pesimistas, es decir, las que asumen que acabaremos más tarde de lo que se podría acabar activan la ley de Parkinson que viene a decir que trabajaremos durante todo el periodo de tiempo, si tenemos 2 meses nos apañaremos para trabajar esos dos meses, igual que si tuviésemos 40. Además se sufre el síndrome del estudiante, es decir, dejar todo para última hora porque “aun queda tiempo”. Como es muy difícil ser exacto al menos es conveniente saber que puede suceder al sobreestimar o al subestimar.

Estimación y planificación. Importancia de las estimaciones. Errores al estimar. La estimación y la planificación son conceptos relacionados, de hecho veíamos como para hacer una agenda es necesario estimar tiempo y coste. La planificación hace referencia a QUE hay que hacer para conseguir un objetivo, la meta es conseguir un resultado en particular. Por otro lado la estimación hace referencia a CUANTO hay que hacer de cada cosa, y la meta es conseguir la mayor exactitud posible. Además las estimaciones tienen mucho que ver con el control del proyecto, es decir, con su monitorización. Así pretenden determinar si los objetivos del proyecto son realistas para permitir un control de forma que se cumplan los objetivos. Las estimaciones exactas tienen mucha importancia ya que estas:

28

Aprobando Ingeniería del Software II 2010 -

-

Mejoran la visibilidad del estado del proyecto: Si la agenda planificada es realista (basada en estimaciones exactas) se puede hacer un seguimiento según los planes. Favorecen la alta calidad: Al estar lo real ajustado a lo planificado la presión sobre la agenda es menor por lo que se cometen menos errores. Mejoran la coordinación con actividades de “no programación”: La agenda debe incluir actividades que no sean de programación. Incrementa la credibilidad del equipo de desarrollo: Al ajustarse lo real a lo planificado se tendrá que variar poco y no tendremos que hacer modificaciones lo que incrementa la credibilidad. Estos tíos son unas máquinas, han acertado a la primera. Proporcionan información de riesgo en etapas tempranas: Al detectar discrepancias entre los objetivos y las estimaciones indican un riesgo de que el proyecto fracase.

Las estimaciones pueden ser poco exactas debido a que podemos cometer errores al estimar, estos errores pueden provenir de diferentes lugares. -

Información inexacta: No disponemos de suficiente información sobre lo que tenemos que construir. Información inexacta sobre las capacidades de la organización: No sabemos las habilidades del equipo que se encargará de desarrollar el producto. Proceso de desarrollo caótico: Todo es un caos, desorganizado, poca comunicación, etc. Inexactitud en el proceso de estimación: Podemos omitir actividades y requerimientos así como una subjetividad, por ejemplo, al apreciar el tamaño del proyecto.

Cono de la incertidumbre y los valores de las estimaciones.

El cono representa la exactitud en el mejor caso que es posible conseguir en las estimaciones del software en diferentes momentos del proyecto. El cono no se estrecha por sí mismo. Se estrecha tomando decisiones que reducen las fuentes de variabilidad sobre el proyecto.

29

Aprobando Ingeniería del Software II 2010 Para entender esto mejor… la x es lo que queremos estimar, por ejemplo esfuerzo, tiempo y funcionalidades. En el momento de viabilidad del proyecto la mejor estimación posible será de 4x o 0.25x, no podremos obtener una mejor estimación, por eso puede no ser conveniente usar métodos sofisticados de estimación en estas etapas tempranas. Cuando vamos teniendo partes del proyecto claras es más fácil estrechar el cono, por ejemplo, después de tener la viabilidad, los requerimientos y el diseño se estrecha bastante. En última instancia, al final del cono, con todo desarrollado la estimación será la realidad.

En el eje x se tiene el nivel de detalle considerado a la hora de presupuestar, o mejor expresado, la cantidad de información para la estimación. Se pueden ver varias gráficas superpuestas. -

30

Budgeting effort: Cuanta más información se disponga más esfuerzo costará hacer una estimación. Budget maintainability: Cuanta más información se tenga la mantenibilidad de las estimaciones se verá reducida ya que tendremos más variables y más claras. Budget accuracy: A más información más exactos seremos. Budget value: Hay que conseguir un equilibro entre el esfuerzo y la mantenibilidad para conseguir más valor.

Aprobando Ingeniería del Software II 2010 ¿Qué hay que estimar? Esfuerzo, tiempo y coste total. Cuando estimamos tenemos que responder a las siguientes preguntas. -

¿Cuánto esfuerzo es necesario para completar una actividad? ¿Cuánto tiempo se necesita para completar una actividad? ¿Cuál es el coste total de una actividad?

Además cuando respondemos a estas preguntas podemos estimar la cantidad de funcionalidades que se pueden entregar. Como ya se ha dicho antes, las actividades de estimación y confección de agendas son actividades de gestión que se intercalan. El esfuerzo requerido para realizar una tarea X es la cantidad de trabajo que se necesita para completar dicha tarea X. No confundir con la duración que dependerá del número de recursos asignados a dicha tarea, de la cantidad de comunicación requerida y de la capacidad de la tarea para ser divida en partes. El esfuerzo es medido en personas/tiempo, normalmente en personas/mes que equivale a 152 horas de trabajo. Volviendo a la duración nos podríamos encontrar con varios casos, unos más realistas que otros. En las gráficas hay una relación de cantidad de personas con los meses necesarios para completar una tarea. Gráfica

Descripción

Sería una tarea completamente particionable y asignable a personas sin necesidad de una comunicación entre ellas.

Una tarea no particionable, tiene que ser desarrollada como un todo o disponer de restricciones secuenciales.

31

Aprobando Ingeniería del Software II 2010

Es una tarea particionable pero se requiere comunicación entre las subtareas.

Es el caso más realista. La tarea puede particionarse pero se requiere comunicación entre las personas. Se puede ver que al añadir personas a partir de un punto la cantidad de tiempo necesario crece exponencialmente.

Hablando de coste y precio. Desarrollar un software tiene un coste asociado normalmente dado por las siguientes variables. -

Costes de esfuerzo (horas trabajadas): Engloban los sueldos de los ingenieros y gastos de seguros o seguridad social. Costes hardware y software: ¿Se necesitan máquinas? ¿Comprar entorno de desarrollo? Costes de viajes y aprendizaje: Congresos, cursos. Otros: Alquileres, redes, recursos compartidos.

En cuanto al precio, aunque no es objetivo de la asignatura, hay múltiples factores que influyen en él. Tener en cuenta que el precio es los costes más los beneficios. -

-

32

Oportunidad de mercado: Podría ofrecer un bajo precio debido a que quiere conseguir cuota de mercado. Obtener pocos beneficios al principio puede traducirse en más posteriormente. Incertidumbre en las estimaciones: Si se está inseguro de las estimaciones, se puede incrementar el precio por encima del beneficio normal para cubrir contingencias. Términos contractuales: Por ejemplo el permitir que se disponga del source code o no. Volatilidad de los requerimientos: Se puede reducir precio para ganar un contrato y luego subirlos cuando los requerimientos vayan cambiando. Salud financiera: Posibilidad de bajar precios por necesidad de obtener un contrato por dificultades económicas.

Aprobando Ingeniería del Software II 2010 FACTORES QUE INFLUENCIAN LAS ESTIMACIONES. Las estimaciones se ven fuertemente condicionadas por varios parámetros, están expuestos de más influencia a menos. -

Tamaño del proyecto. Tipo del proyecto: No es lo mismo un programa para el Mercadona que uno para la NASA. Factores personales. Lenguaje de programación. Otros: Cocomo II.

Tamaño del proyecto. Es el factor más significativo que contribuye a las estimaciones de esfuerzo y tiempo. Normalmente el proceso de estimación que vamos a seguir es el siguiente.

El tamaño del código lo podemos cuantificar con unas métricas, ejemplos de estas métricas son las Líneas de Código (LOC), los Puntos de Función (FP) y los Puntos de Objeto (OP). Hay que destacar también que el esfuerzo requerido para completar un proyecto crece exponencialmente con el tamaño del proyecto debido a lo siguiente.

Diseconomías de escala. Normalmente se asume que un sistema 10 veces más grande que otro requerirá 10 veces más de tiempo, pero esto es totalmente falso. Cuanto mayor sea el proyecto se requiere más comunicación entre la gente implicada así que el rendimiento de un equipo es inversamente proporcional a la cantidad de comunicación que se deba entablar. Al crecer la comunicación crece el esfuerzo de forma exponencial. Esto es la diseconomía de escala, lo contrario de la economía de escala que es asumir que a más gente, menos tiempo. Para reducir la diseconomía de escala hay que reducir la escala partiendo el problema en problemas más pequeños que requieran menos comunicación.

Métricas de tamaño. Lineas de Código LOC. Es una medida propuesta inicialmente cuando los programas se escribían en tarjetas, con una línea por tarjeta. Actualmente los lenguajes de programación permiten escribir varias sentencias en una línea o una misma sentencia en varias líneas. No es importante la definición de línea de código sino que siempre se use la misma de forma sistemática. Además se asume que cuantas más líneas de código habrá más documentación.

33

Aprobando Ingeniería del Software II 2010 Una ventaja de las LOC es que se puede calcular de forma fácil y objetiva pero son totalmente dependientes del lenguaje de programación. Ofrecen una estimación bastante buena pero no se puede saber lo que vale hasta que ha finalizado la implementación.

Métricas de tamaño. Puntos de función FP. Estos se basan en una combinación de elementos de la aplicación. -

Entradas externas (EI: External Inputs): Pantallas, formularios, señales de control, a partir de las cuales los usuarios u otros programas cambian los datos. Salidas externas (EO: External Outputs): Pantallas, informes, gráficos. Consultas externas (EQ: External Inquiry): Datos no elaborados, por ejemplo datagrids. Ficheros internos usados por el sistema (ILF: Internal Logical Files): Tablas de la BD. Ficheros externos al sistema (EIF: External Interface Files): Ficheros externos.

A cada uno de ellos se le asocia un peso en función de: -

Para los EI, EO y EQ se cuentan el número de ficheros actualizados o referenciados (FTR) y el número de Data Element Types (DET) o campos. Para los ILF y EIF se cuentan el número de Record Element Types (RET) o agrupaciones de campos y los DET.

La suma ponderada de los elementos anteriores dan como resultado los puntos de función no ajustados. Para ajustarlos hay que determinar el VAF o Value Adjustement Factor, para esto se valor del 0 al 5 un total de 14 características de la aplicación y se suman los valores resultantes (TDI). Al final el VAF se calcula como: VAF = (TDI * 0.01) + 0.65 Para hacer el ajuste FPA = FPNA * VAF. Para el cálculo de los puntos de función no ajustados se usan una serie de tablas, como las de este ejemplo.

34

Aprobando Ingeniería del Software II 2010 Si una entrada externa EI tiene 6 DETs y 5 FTRs según la tabla de EI le corresponde un valor de 6.

Métricas de tamaño. Puntos de objeto o de aplicación OP. Los puntos de objeto o puntos de aplicación son una medida alternativa relacionada con la funcionalidad cuando se usan lenguajes 4GLs o similares para el desarrollo. Recalcar que los OP no son clases de objetos de la programación orientada a objetos así que no contamos ni objetos creados ni clases. Se calculan haciendo una estimación ponderada de: -

El número de pantallas distintas que son visualizadas. El número de informes que se producen por el sistema. El número de módulos en lenguajes imperativos que deben desarrollarse para complementar el código de la base de datos.

Esta manera de calcularlos es una de tantas recetas para poder calcularlos. Los OP tienen las mismas ventajas e inconvenientes que los FP, además tiene una cierta subjetividad a la hora de calcularlos dependiendo del estimador y se emplea una granularidad más gruesa que en los FPs. En la asignatura se centran en el cálculo de los FP que al fin y al cabo es lo que puede ser más largo de hacer en el examen. Los FP y OP se pueden traducir a LOC mediante el análisis de datos históricos de la siguiente manera: LOC = AVC * FP.

Tipo del proyecto. Este factor es el segundo más importante a la hora de hacer estimaciones. Los proyectos más complejos requieren mayor esfuerzo y suelen tener menos productividad. Podemos tener proyectos del mismo tamaño pero de diferente dificultad, cuán más difíciles sean la productividad tiende a ser menor, lo que es lo mismo, hay que pasar más tiempo pensando las líneas de código, estas requerirán más esfuerzo. La productividad es una medida de la “velocidad” a la que los ingenieros implicados en el desarrollo del software producen dicho software y su documentación asociada. Una cosa que NO es la productividad es un indicador de calidad. Básicamente medimos la funcionalidad útil por unidad de tiempo: Productividad = tamaño/esfuerzo(pm).

35

Aprobando Ingeniería del Software II 2010

Factores personales. Es el tercer factor más significativo que contribuye a las estimaciones. En la siguiente imagen se observan diferentes factores sobre el personal y como estos pueden afectar positivamente disminuyendo el esfuerzo (zona azul) y negativamente aumentándolo (zona gris). La zona nominal sería la línea negra, es decir, por ejemplo, si la continuidad del personal es muy baja el esfuerzo se ve aumentado en un 29% sobre el valor normal (línea negra).

Lenguaje de programación. La experiencia en el lenguaje de programación y herramientas específicas usadas en el proyecto tiene un efecto alrededor de un 40% sobre el ratio de productividad del proyecto. Algunos lenguajes producen más funcionalidad por línea que otros. Dependiendo del nivel de soporte de las herramientas automáticas usadas con el lenguaje se puede incrementar hasta en un 50% el esfuerzo requerido. Los programadores que usan lenguajes de programación interpretados suelen ser más productivos que los que usan lenguajes compilados.

36

Aprobando Ingeniería del Software II 2010 Otras influencias. Factores de ajuste COCOMO II. Esta parte será vista con detalle posteriormente.

CONSIDERACIONES ESPECÍFICAS. Tenemos que tener claro qué es lo que queremos estimar, debemos conocer las incógnitas a despejar y pueden venir por dos lados diferentes. Por un lado dadas unas funcionalidades a implementar tenemos que estimar el tamaño del proyecto, el esfuerzo y el tiempo que tardará en entregarse, y partiendo de estas estimaciones el coste del mismo pensando en los sueldos del personal y otros gastos. Por otro lado se nos pueden dar una serie de restricciones de presupuesto y tiempo y debemos de ser capaces de saber la cantidad de funcionalidades que podemos implementar. A la hora de estimar podemos seguir dos estrategias diferentes, la “top-down” y la “bottomup”, en ambas el WBS es importante para ver la jerarquía de tareas.

Estimaciones “top-down”. Comienza a nivel de sistema y evalúa la totalidad de funcionalidades y cómo estas interactúan entre ellas. Además se puede usar sin conocer la arquitectura ni los componentes que formarán parte del sistema, es decir, no es necesario conocer los niveles más bajos del WBS. Este método tiene en cuenta costes de integración, gestión de configuraciones y documentación, que suelen estar en la parte más alta del WBS, pero por otro lado puede infraestimar costes relacionados con la resolución de problemas técnicos de bajo nivel difíciles de resolver. Puede que abajo del WBS haya algo muy problemático y que requiera más esfuerzo/tiempo/coste del que hemos estimado.

Estimaciones “bottom-up”. Pues simplemente lo contrario que el anterior. Comienza a nivel de componentes y estima el esfuerzo requerido para cada componente. Dichos esfuerzos se añaden a la estimación final. Se puede usar cuando la arquitectura del sistema es conocida y los componentes han sido identificados. Proporciona estimaciones bastante exactas se el sistema se ha definido con detalle y puede infra-estimar costes a nivel de sistema (nivel más alto) como la integración y la documentación. Con estas definiciones es lógico pensar que las estimaciones top-down se usarán más cuando estemos comenzando el desarrollo y la bottom-up cuando vayamos teniendo claros la arquitectura y los componentes conforme avanzamos el proyecto.

37

Aprobando Ingeniería del Software II 2010 Consiguiendo estimaciones exactas. Debemos seguir unos pasos lógicos a la hora de intentar conseguir las estimaciones más exactas posibles. Todo empieza contando, es lo primero que tenemos que hacer siempre que podamos para cuantificar el tamaño del proyecto. Cuando no se pueda contar calcularemos y en última instancia emitiremos juicios (nada recomendable) pero esto hará que lo paguemos caro porque las agendas planificada y real no se parecerán en nada. Podemos contar muchas cosas, todo esto serian métricas, números que nos dicen cuantitativamente el tamaño del proyecto, pueden ser desde FPs, casos de uso o talas de la base de datos. Por ejemplo, si conocemos las funcionalidades y queremos estimar tamaño, tiempo y coste, al comienzo del desarrollo lo más sensato es contar los puntos de función. Luego, después de contar, hemos de convertir estas cuentas en estimaciones. Una vez contados los FP debemos convertirlo en una estimación de esfuerzo, para ello necesitamos calibrar (convertir a estimación) lo que hemos contado con algún tipo de dato. Los datos que se suelen usar para calibrar suelen ser: -

-

Datos procedentes de la industria. Datos históricos de nuestra empresa. Vamos a ser más exactos ya que es nuestra empresa. Importante trabajar siempre igual para que los datos históricos sean aceptables. Datos del proyecto. Podemos fijarnos en los modelos iterativos en estimaciones pasadas de anteriores iteraciones.

MÉTODOS DE ESTIMACIÓN. Juicio experto. Con este método se consulta a expertos en técnicas de desarrollo de software y/o del dominio de la aplicación. El experto o expertos emiten un juicio sobre tareas individuales según una estimación bottom-up y para ello puede ser útil usar un WBS. Dentro del juicio experto podemos usar dos variantes, el individual y en grupos, concretamente en éste último tenemos la técnica Delphi. Para asegurar los juicios efectivos hay que usar expertos que realmente han trabajado en lo que van a estimar, no vale con cuatro personas que hayan leído sobre el tema, se han tenido que poner varias veces manos a la obra. Otra manera de asegurar juicios efectivos puede ser usar la granularidad adecuada y usar rangos, además se pueden usar fórmulas y comparar las estimaciones con los resultados reales.

38

Aprobando Ingeniería del Software II 2010 Técnica Delphi. La técnica Delphi es el método experto en grupos y se procede de la siguiente manera. 1. El coordinador presenta a cada estimador su formulario de estimación. 2. Los estimadores preparan individualmente su estimación. 3. El coordinador modera una discusión sobre cuestiones de estimación relacionadas con el proyecto. 4. El coordinador recoge las estimaciones anónimamente. 5. El coordinador presenta un resumen de las estimaciones. 6. El coordinador modera una discusión sobre las variaciones. 7. Los estimadores votan anónimamente la media de las estimaciones. Si alguno vota NO, se vuelve al paso 2. 8. El resultado es una única estimación, o bien un rango de estimaciones. Cuando se ve que la estimación no se ajusta más, entonces se paran las iteraciones. Aquí abajo hay un pequeño ejemplo.

Ésta técnica se usa para estimaciones iniciales del proyecto ya que se tiene una granularidad alta al comienzo del mismo y consume mucho tiempo. Es útil también para estimaciones en nuevas áreas de negocio o nuevas tecnologías. Se usa además para proyectos que engloban diversas disciplinas y se consigue una exactitud posible media.

39

Aprobando Ingeniería del Software II 2010 Ley de Parkinson. La ley de Parkinson se basa en que cuanto más tiempo me den, me las voy a apañar para ocuparlo todo. El coste se determina en función de los recursos/tiempo disponibles en vez de evaluaciones objetivas. Si un SW tiene que entregarse en 6 meses y se tiene a 5 personas el esfuerzo estimado será de 30pm. Es adecuado cuando las restricciones prevalecen sobre las características deseadas del producto y se puede aplicar a cualquier proyecto consiguiendo una baja exactitud en las estimaciones.

Modelado algorítmico de costes. Las estimaciones se hacen como una función matemática basada en diversos atributos del producto, proceso y proyecto. La fórmula básica que siguen estos modelos es: Esfuerzo = A x SizeB x M. Donde A es una constante dependiente de la organización. La B refleja la diseconomia de escala y cuanto más grande sea la curva exponencial de la que ya se habló será más pronunciada. Size es el tamaño del proyecto, y es esencial, ya hemos visto que es el elemento más importante a la hora de estimar. M es información adicional para que la estimación sea más exacta. Vamos a estudiar uno de estos modelos, en concreto el de COCOMO (Constructive Cost Model). COCOMO. Con el tiempo se han ido modificando las fórmulas de COCOMO pasando de la versión 81 a la versión II. Básicamente se han ido haciendo estimaciones de muchos proyectos y sacar fórmulas matemáticas que den como resultados esos esfuerzos estimados. El modelo COCOMO II tiene varios submodelos que generan estimaciones del software más detalladas. Estos submodelos son: -

40

Application composition model. Indicado para proyectos construidos con herramientas modernas de construcción de interfaces gráficos para usuario. Early design model. Usado cuando los requerimientos están disponibles pero no es necesario disponer de la arquitectura completa. Reuse model. Usado para calcular el esfuerzo de integración de componentes reusables. Post-architecture model. Usado una vez que se diseña la arquitectura del sistema y se dispone de más información del mismo.

Aprobando Ingeniería del Software II 2010 Esta última es la única que se va a estudiar en la asignatura, así que en el examen solo tendremos que justificar este.

Resumen de usos de los diferentes submodelos.

Uso de los diferentes submodelos a lo largo del cono de incertidumbre.

Veamos ahora las fórmulas y que es cada parte de ellas. Es importante saber que para el examen no es necesario saber las formulas de memoria pero si saber justificar qué es cada parte de las mismas.

41

Aprobando Ingeniería del Software II 2010

Vamos a ello. Empezamos por las ecuaciones de tamaño para saber el Size de la ecuación. Las líneas de código se miden en miles así que es importante que lo que calculemos lo pasemos a miles, COCOMO se usan para proyectos grandes. -

KNSLOC: Son las nuevas líneas de código que hay que implementar. Son líneas que no existen y hay que crearlas. KESLOC: Son las líneas de código que no están hechas desde cero sino adaptadas de versiones existentes. REVL: Es el porcentaje de código que se ha implementado pero se ha desechado por la volatilidad de los requerimientos. KASLOC: Son las líneas de código modificadas. AT: El porcentaje de líneas de código que se traducen automáticamente.

Para las ecuaciones de esfuerzo tenemos lo siguiente. -

PMAuto: Esfuerzo correspondiente al código automáticamente generado. Mult(SF): Son los factores de escala que se ven a continuación. Sum(EM): La suma de los multiplicadores de esfuerzo.

La B se ajusta a 0.91 y ATPROD a 2400.

42

Aprobando Ingeniería del Software II 2010

Además tenemos las ecuaciones de tiempo.

Los multiplicadores de esfuerzo y factores de escala tampoco hay que sabérselos de memoria, sino que hay que saber identificarlos en un enunciado.

Multiplicadores de esfuerzo y factores de escala.

43

Aprobando Ingeniería del Software II 2010 Otra manera de verlos:

EJEMPLOS DE CÁLCULOS. Para hacer estimaciones hemos visto que tenemos que seguir una serie de pasos, vamos a ver ejemplos de estos pasos y diferentes maneras de llevarlos a cabo. Hemos visto que lo primero que hay que hacer es estimar el tamaño del proyecto, nosotros en la asignatura vamos a hacerlo calculando los puntos de función (FP). En prácticas se explica cómo calcularlos y en el documento de la práctica correspondiente también. El segundo paso es calcular el esfuerzo a partir del tamaño que hemos estimado usando datos históricos de productividad. Si los datos históricos tienen un rango estrecho (la diferencia es un factor de 3 desde el mayor al menor) se puede usar un modelo lineal. Por ejemplo, si hemos estimado el tamaño y hemos visto que el tamaño está entre 65000 y 100000 LOC vamos a estimar el esfuerzo partiendo de datos históricos de otros proyectos.

44

Aprobando Ingeniería del Software II 2010

Podemos descartar proyectos, en este caso descartamos el Proyecto C porque 65000/3 = 21666,6 y el Proyecto C tiene 7444 LOC, es demasiado pequeño para compararlo con el nuestro. Por otro lado el Proyecto E tampoco nos sirve, es demasiado grande, 100000*2 = 300000 así que lo descartamos también. Luego podemos calcular la productividad de cada proyecto, como vimos es el tamaño/esfuerzo y con esto tendremos proyectos con una mayor productividad y proyectos con una menor productividad. La calibración se hace dividiendo el tamaño menor entre la mayor productividad y el mayor tamaño entre la menor productividad. En este caso [65000/1612, 100000/986] lo que nos da [40, 101] pm. El resultado es pm porque lo que estamos dividiendo es LOC entre LOC/PM. Otra forma de de cálculo del esfuerzo de manera más concreta, es usar Construx, que se usará en prácticas. Construx utiliza una mezcla entre el modelo Putnam y el COCOMO. Este método nos permite estimar el esfuerzo a partir de FP, LOC o GUI. Las estimaciones con Construx se calibran de dos maneras posibles, mediante datos históricos o mediante datos provenientes de la industria. Es decir, en Construx podemos calibrar introduciendo los datos del método anterior. En nuestro ejemplo, con Construx hemos obtenido [65, 94] pm. El tercer método sería hacer una comparación con datos de la industria. Existen datos de proyectos del mismo tipo con dificultad semejante. Podemos ver en este gráfico la media y la media más una desviación típica. Es labor del estimador elegir entre las dos. En la gráfica el eje X representa las líneas de código y el eje Y el esfuerzo necesario. Para nuestro caso, cogemos la media y si nos movemos hasta 65000 LOC obtenemos 85pm, si nos movemos hasta las 100000 obtenemos 170pm. De esta manera usando este método

45

Aprobando Ingeniería del Software II 2010 obtenemos una estimación de [85, 170] pm. Decir que éste último método es el menos fiable ya que los datos no tienen en cuenta posibles incidencias dentro de nuestra empresa y factores personales. Bien, hemos visto tres métodos de estimar el esfuerzo, pero es importante saber, de cara al examen también que no todos los métodos de estimación son iguales. Debemos ponderar y dar más peso a las que tienden a producir mejores resultados. NUNCA hay que coger la media y la ponderación depende de nosotros, así que eso, lo importante es no dar a todas el mismo peso. Normalmente Construx es mejor que los datos de proyectos anteriores y éste mejor que los datos de la industria. El tercer paso, después de haber estimado el tamaño y el esfuerzo, es estimar el tiempo. El tiempo se calcula a partir del tamaño y del esfuerzo y la ecuación básica para la estimación del tiempo es: Tiempo_meses = 3 * Esfuerzo_PM^1/3. Esta fórmula se usa para estimaciones tempranas en proyectos medianos o grandes. El tiempo también se puede calcular mediante la comparación con datos históricos y partiendo de la fórmula anterior podemos obtener otra: Tiempo = Tiempo_proyectos_pasados * (Esfuerzo_estimado/Esfuerzo_proyecto_pasado)^1/3. Vamos a ver un ejemplo.

Hemos calculado las estimaciones de tiempo usando la fórmula para los proyectos de la tabla anterior pero sin contar los que habíamos descartado. Como vemos calculamos el tiempo usando el esfuerzo que nosotros habíamos estimado y un valor medio que no es necesario calcularlo. Luego podemos hacer dos cosas, podemos coger valores medios de las estimaciones baja y alta y obtener [12, 13.8] meses o coger el peor del bajo y el mejor del alto, esto lo que hace es ampliar el rango para ser más exactos y así contemplamos posibles problemas. Se suele usar este segundo método cuando no tenemos demasiada confianza en los datos. En este caso sería la estimación [10.8, 15.3] meses.

46

Aprobando Ingeniería del Software II 2010 Bueno, pues ya hemos hecho una estimación de esfuerzo, y otra de tiempo. Entre estos dos aspectos debe haber un equilibro siempre. Acortar el tiempo incrementa el esfuerzo ya que se requiere más comunicación y más coordinación y se requieren más tareas en paralelo. Cuando estimamos tiempo podemos obtener una agenda nominal que no se debe acortar en más de un 25% porque sería inviable. Además se pueden reducir costes alargando la agenda y reduciendo el personal.

Si bien hemos estimado el esfuerzo y el tiempo del proyecto en general, normalmente luego debemos asignar estas estimaciones a las diferentes actividades del proceso software. Normalmente esto se hace partiendo de una tabla de distribución del esfuerzo para proyectos de diferentes tamaños y de unos ajustes que depende del tiempo del proyecto. De esta manera al asignar esfuerzos a diferentes actividades debemos considerar el tamaño del proyecto, el tipo de proyecto y los tipos de esfuerzo contenidos en los datos de calibración usados. A continuación se expone la tabla de esfuerzos por actividades en proyectos de diferente tamaño y los ajustes por tipo de proyecto.

47

Aprobando Ingeniería del Software II 2010 Vamos a usar estas tablas para asignar el esfuerzo a las diferentes actividades de un proyecto con 80 000 LOC (1450 FP) y con un esfuerzo estimado de 80pm. 80 000 LOC son 80 KLOC asi que en la primera tablas vemos que estamos entre 25 y 125 KLOC. Para cada actividad el porcentaje será la media entre estos dos valores. De esta manera -

Requerimientos: (4+7) / 2 = 4.4%. Arquitectura: (14+15)/2 = 14.5%. Construcción: (49+44)/2 = 46.5%. Pruebas: (23+23)/2 = 23%. Gestión: (10+11)/2 = 10.5%.

Ahora, con los ajustes, vamos a rellenar la siguiente tabla:

Para facilitar la tarea lo he hecho con MS Excel.

48

Aprobando Ingeniería del Software II 2010 Tema 3: Estimaciones. Ejemplo de COCOMO

49

Aprobando Ingeniería del Software II 2010 Este ejercicio es el que está en las transparencias de la asignatura, concretamente en el Tema 3, pero en las transparencias hay algún error que otro (lo que no quiere decir que esto esté libre de errores por lo que agradecería que si hay alguno, me lo indicaseis). Básicamente se trata de hacer estimaciones usando el modelo COCOMO haciendo uso de sus fórmulas y toda la tropa. Antes de nada vamos a recordar las fórmulas que, importante, no hace falta sabérselas de memoria para el examen, pero sí saber identificar cada parte de ellas. Recordemos que la ecuación básica de esfuerzo en los modelos algorítmicos es Esfuerzo = A x Size^B X M. Donde A es una constante establecida por la organización, Size el tamaño del proyecto, B el factor de escala y un multiplicador de esfuerzo. Aquí las formulas del modelo COCOMO. Ecuaciones de Esfuerzo.

Lo importante, saber qué es cada cosa. En la ecuación de PMns se refiere a que es la agenda nominal, es decir, sin contemplar el multiplicador SCHED. La E es el factor de escala que se calcula como se indica en la fórmula de E, donde B siempre estará calibrada a 0.91 en nuestro caso, y el sumatorio de los 5 factores de escala que veremos a continuación y que sí hay que aprendérselos y sobre todo saber identificarlos en un texto. Por otro lado, al esfuerzo nominal habría que sumarle el esfuerzo de las líneas generadas automáticamente calculándose como se indica y siendo ASLOC el número de líneas de código adaptadas, siento AT el porcentaje automáticamente traducido y ATPROD un valor por defecto referente a la productividad de la traducción automática, ajustada a 2400 en nuestro caso. Una vez calculado esto, si lo tenemos, debemos calcular el tamaño haciendo uso de las siguientes fórmulas.

50

Aprobando Ingeniería del Software II 2010

Donde REVL es el porcentaje de código desechado por la volatilidad de los requerimientos. KNSLOC los miles de nuevas líneas de código. KESLOC los miles de líneas de código equivalentes, por ejemplo de un módulo a parte, esta parte se usará para el análisis de la reusabilidad. Para calcular KESLOC tenemos que multiplicar KASLOC que son las miles de líneas adaptadas por lo que indica la fórmula siendo AT el porcentaje traducido automáticamente y AAM un factor de ajustamiento de adaptación. Este último se calcula como se indica siendo AA el grado de asimilación, SU el porcentaje de entendimiento del software, DM el porcentaje del diseño modificado, CM el porcentaje de código modificado y IM el porcentaje de integración y pruebas modificadas. Ya, por último, podemos calcular también el tiempo de desarrollo siendo:

Siendo SCED el multiplicador de esfuerzo de compresión o dilatación de la agenda. Lo veremos más tarde en el ejemplo. Por otro lado tenemos los multiplicadores de esfuerzo y los factores de escala, estos si hay que sabérselos como dije, y además saber identificarlos en un texto de algún ejercicio, yo para aprendérmelos uso la siguiente manera. Tal y como están en las transparencias los divido en cuatro grupos. -

51

Producto. CRDDR o CPLX. Complejidad del Producto. o RELY. Fiabilidad requerida por el software. o DOCU. Extensión de la documentación necesaria. o DATA. Tamaño de la base de datos usada.

Aprobando Ingeniería del Software II 2010 -

-

-

-

52

o RUSE. Porcentaje requerido de componentes para reutilización. Computador. TPS o TIME. Restricciones de tiempo. o PVOL. Volatilidad de la plataforma de desarrollo. o STOR. Restricciones de memoria. Personal. APPPAL o ACAP. Capacidad de análisis. o PCON. Continuidad del personal. o PCAP. Capacidad de programación. o PLEX. Experiencia en la plataforma. o APEX. Experiencia en el dominio de la aplicación. o LTEX. Experiencia en el lenguaje de programación y herramientas. Proyecto. TSS o TOOL. Uso de herramientas software. o SCED. Compresión de la agenda. o SITE. Extensión de la aplicación (local, metropolitana) y comunicación requerida. Factores de escala. PRPTF o PMAT. Madurez del proceso de desarrollo. o RESL. Resolución de riesgos y arquitectura. o PREC. Precedentes, experiencia de la organización en el tipo de aplicación. o TEAM. Cohesión del equipo. o FLEX. Flexibilidad en el desarrollo.

Aprobando Ingeniería del Software II 2010 Ejercicio. LA aplicación que vamos a desarrollar es una para automatizar el pago de impuestos, a partir de ahora lo conoceremos como API. Se ha realizado un análisis previo de factibilidad, los requerimientos han sido validados con prototipos y se ha realizado un diseño preliminar. Se nos ha proporcionado una estimación de tamaño de 281FP siendo la equivalencia en lenguaje Java de 53LOCs por cada FP. Además hay un compromiso de entregar el proyecto en 6 meses o menos lo que tendremos que ver si se puede o no. Por último sabemos que se trata de una aplicación standalone que se distribuirá en CD y vía Internet. Con esto sabemos que como se ha hecho un diseño preliminar tenemos que usar el modelo Post-arquitectónico, aunque de hecho, en la asignatura solamente usaremos este modelo. Por otro lado sabemos que el tamaño de la aplicación en líneas de código será 281 x 53 = 14893 LOCs o lo que viene siendo lo mismo 14.9 KLOCs (en Cocomo trabajamos en miles de líneas). Y se trata de una aplicación standalone por lo que no requerirá más comunicación ni extensión que la de un edificio de oficinas. Cálculo del factor de escala. NOTA: Luego siempre nos tendrán que dar una especificación de la aplicación de donde tendremos que interpretar y sacar los multiplicadores de esfuerzo y los factores de escala. Vamos a empezar por los factores de escala, recordamos que son 5 (PRPTF: pmat, resl, prec, team, flex). Las especificaciones las podremos dividir en los 4 grupos anteriormente nombrados (Producto, Computador, Personal, Proyecto). El personal actual de la organización es un personal contratado de una compañía local con nivel 2 CMM. Dicho personal tiene experiencia en el dominio de la empresa (por lo menos tres años) y tienen experiencia previa como desarrolladores en Java (también 3 años como mínimo). Nuestra empresa además sufre una alta movilidad de los trabajadores, concretamente superior al 30% por año y tienen pocas habilidades como analistas. Además hay tres jefes programadores que entran en conflicto con los líderes de grupos y programadores más jóvenes, estos conflictos son a menudo. Por otro lado aunque consideramos el proceso de desarrollo importante, no interferimos regularmente en este aspecto y la empresa está muy familiarizada con este tipo de aplicaciones.

53

Aprobando Ingeniería del Software II 2010 De arriba a bajo tenemos los factores: PMAT, TEAM, FLEX y PREC. Para RESL como no está tomaremos un valor intermedio posteriormente.

54

Aprobando Ingeniería del Software II 2010

Cálculo de los multiplicadores de esfuerzo. Debemos ahora identificar los multiplicadores de esfuerzo. El personal actual de la organización es un personal contratado de una compañía local con nivel 2 CMM. Dicho personal tiene experiencia en el dominio de la empresa (por lo menos tres años) y tienen experiencia previa como desarrolladores en Java (también 3 años como mínimo). Nuestra empresa además sufre una alta movilidad de los trabajadores, concretamente superior al 30% por año y tienen pocas habilidades como analistas. Además hay tres jefes programadores que entran en conflicto con los líderes de grupos y programadores más jóvenes, estos conflictos son a menudo. Por otro lado aunque consideramos el proceso de desarrollo importante, no interferimos regularmente en este aspecto y la empresa está muy familiarizada con este tipo de aplicaciones. De arriba a bajo en naranja, tenemos APEX, LTEX, PCON y ACAP, además teníamos SITE al ser standalone. Calculamos ahora el valor del multiplicador de esfuerzo.

55

Aprobando Ingeniería del Software II 2010

Nos quedaría calcular SIZE, pero como no tenemos código desechado ni líneas equivalentes, el tamaño es el que hemos calculado con anterioridad. Cálculo de la estimación de esfuerzo. Nos queda el siguiente cálculo.

56

Aprobando Ingeniería del Software II 2010

Análisis de sensibilidad. Se nos pide ahora ver qué pasa cuando los requerimientos de documentación son mínimos y cuando son máximos y ver lo que pasa con el esfuerzo.

Además también se nos pide el ahorro de esfuerzo que podríamos tener si la madurez del proceso es de CMM 4 lo que su valor seria 1.56. Debemos calcular de nuevo el factor de escala.

Análisis de reusabilidad. Nota: vamos a ver qué pasa ahora, si merece la pena hacer uso de un componente existente que sustituya una parte de nuestro código o no. Un aspecto de la aplicación puede satisfacerse adaptando un software existente recientemente desarrollado denominado Calculadora de Tasas Declarables (CTD). Si la usamos, un applet de Java de 4000LOC podría satisfacer aproximadamente un 20% de la funcionalidad requerida (un 20% de los UFP necesarios). Se estima que el rediseño del applet sería aproximadamente menos del 20%, y que la cantidad de código a reescribir sería no más de un 30%. Además la integración y pruebas para comprobar el rendimiento con los cambios introducidos no requerirán más de un 25% de esfuerzo adicional. Debido a la elevada rotación del personal, la gente que desarrolló CTD ya no están contratadas por nuestra organización, y el personal actual tiene una familiaridad limitada con CTD, sin embargo hay una buena correlación entre API y CTD ya que siguen los mismos estándares de documentación.

57

Aprobando Ingeniería del Software II 2010

Desarrollando desde 0, tendríamos que implementar el 20% de 14.9 = 2.98KLOC o aproximadamente 3KLOC o 3 000 líneas de código desde 0 para satisfacer esas necesidades. Quedándonos la fórmula del tamaño como indico a continuación.

En cambio si adaptamos el CTD nos quedaría como sigue.

Tenemos que calcular entonces KESLOC, que recordamos, las líneas equivalentes de la funcionalidad a sustituir y que resolvemos en el siguiente cálculo.

Para calcular AAM tenemos que seguir las siguientes fórmulas.

Para calcular AAF hemos resaltado en el texto del análisis de reusabilidad en azul, y en orden, DM (modificación del diseño), CM (código modificado), IM (pruebas modificadas).

Los valores de AA, UNMF y SU los tenemos que elegir en una tabla a partir de lo que diga el texto, de esta manera elegimos un AA intermedio, un UNFM mayormente no familiar debido a

58

Aprobando Ingeniería del Software II 2010 que no están contratados los desarrolladores del CTD y un SU alto por la buena correlación entre la documentación.

Ya solo nos queda calcular.

59

Aprobando Ingeniería del Software II 2010

Esto quiere decir que en las funcionalidades que se pueden adaptar podemos ahorrarnos un 50% de código. Para ver el ahorro de esfuerzo debemos calcular el esfuerzo con el tamaño usando la adaptación del componente CTD.

Cálculo del tiempo. Ahora, por último, debemos estimar el tiempo de desarrollo usando la fórmula que está al inicio del documento.

Nos habían dicho que teníamos que entregar en 6 meses o menos, pero esto es imposible ya que la agenda nominal no se puede acortar más de un 25% y la estaríamos acortando más de un 50% si entregamos en 6 meses. Como mucho podríamos entregar, a costa de incrementar el esfuerzo, en 9.4 meses.

60

Aprobando Ingeniería del Software II 2010 Tema 4: Gestión de Configuraciones

61

Aprobando Ingeniería del Software II 2010 Definiciones. Si recordamos el modelo UP, la gestión de configuraciones era una de las disciplinas de soporte que existían y se hacían a lo largo de todas las fases. Esta disciplina, la gestión de configuraciones, consiste en el desarrollo y uso de estándares y procedimientos para gestionar la evolución de un sistema software durante y después de la entrega del mismo al cliente. Los estándares son prácticas comúnmente aceptadas porque han sido probadas y se ha comprobado que efectivamente cumplen sus objetivos de una manera adecuada, decir además que los estándares van evolucionando con el tiempo conforme la gente los va usando y subsanando los posibles problemas. Estos estándares nos ofrecen algunas ventajas. a) Encapsulan las mejores prácticas. Todo el mundo lo usa porque confía en ellos, han sido probados y se conoce bien. b) Permiten continuidad en el trabajo. Al establecer una norma, todos los trabajadores trabajan de la misma manera. Por ejemplo, al llegar un nuevo desarrollador éste trabajará con los mismos criterios. c) Constituyen un marco para garantizar la calidad. Al usar las mejores prácticas la gente que sabe que se usa el estándar tienen cierta confianza en nosotros. Los procedimientos definen cómo hacer algo, son actividades que juntas tienen un propósito u objetivo común. Existen una serie de procedimientos estándares de diferente ámbito, como local, nacional, internacional. El objetivo de la gestión de configuraciones es controlar los costes y esfuerzo implicado en la realización de cambios en el sistema. Esta gestión de configuraciones comienza con el inicio del proyecto y acaba cuando el software ya no está en circulación. Es decir, cuando ya no se usa never more. Por otro lado, no hay que confundir la gestión de configuraciones con el mantenimiento ya que este segundo es hacer los cambios al sistema cuando este se ha entregado al cliente mientras que la gestión de configuraciones implica el cómo manejar la gestión de esos cambios. Por otro lado el mantenimiento solamente empieza cuando se ha entregado el software al cliente. Si mezclamos el tema de los modelos de proceso y el de gestión de configuraciones ésta última está fuertemente influenciada por los modelos. -

62

Cascada: En un modelo en cascada el SW se construye una sola vez durante todo el proceso. Iterativo o Incremental: Se construye una vez en cada iteración. Ágil: Los procedimientos deben ser menos rígidos para que consuman menos tiempo.

Aprobando Ingeniería del Software II 2010 Elementos de configuración. Son aquellos documentos que se van a requerir para un futuro mantenimiento. Será cualquier documento que se haya desarrollado a lo largo del proceso de desarrollo y es susceptible de tener cambios, puede ser cualquier fichero como el código, diagramas de clases, entidades relación. Cualquier artefacto. Cualquier elemento de configuración que ha sido aceptado para formar parte de la base de datos de configuración del sistema se convierte en línea base (cualquier cambio que se quiera hacer tiene que pasar por una serie de pasos antes). Esto último es así porque cuando un artefacto pasa a ser línea base es visible por todos los miembros del grupo y por eso cuando hay que hacer algún cambio debe seguir algún procedimiento.

Tareas del gestor de configuraciones. Dependiendo del tamaño del proyecto puede haber una persona que hace las tareas específicas del gestor de configuraciones pero si no existe este rol es el gestor del proyecto el que se encarga de ellas. Estas tareas que serán explicadas a continuación con más detalle son las siguientes. -

Planificación de la gestión de configuraciones. Gestión de los cambios del sistema. Construcción del sistema. Gestión de nuevas versiones.

Planificación de la gestión de configuraciones. Es la primera tarea del gestor de configuraciones y como cualquier planificación tenemos que responder a las preguntas: QUE, COMO, CUANDO y QUIEN. Un plan de GC describe los estándares y procedimientos usados para la GC. El punto de partida para la planificación debe ser la elección de los estándares. -

-

Definir QUE se va a gestionar y cómo se identifican los elementos de configuración. La identificación de los EC implica darles un nombre para que cuando los veamos nos de la máxima información de lo que contiene sin tener que abrir el fichero o documento. Todos los documentos que van a ser útiles para una futura evolución del sistema deberían ser controlados por el sistema GC. Definir QUIEN será el responsable de los procedimientos de GC. Definir las políticas de control de cambios y versiones (CÓMO y CUANDO). Es decir, definir los algoritmos a seguir a la hora de hacer un cambio.

Además se identifican las herramientas que se van a usar y se establece cómo usarlas así como describe la estructura de la BD de configuraciones.

63

Aprobando Ingeniería del Software II 2010 La identificación de los elementos de configuración se pueden hacer de varias maneras pero cada una tendrá sus ventajas e inconvenientes. Quizá una aproximación jerárquica sea la más flexible aunque tiene los inconvenientes de que es particular para cada proyecto y puede ser difícil identificar componentes relacionados.

Además hablando de estándares y de procedimientos aquí se muestra un ejemplo de lo que podría ser un formulario de petición de cambios y una manera de registrar los cambios en el código fuente de los archivos.

64

Aprobando Ingeniería del Software II 2010 Dentro de la planificación de la GC hemos visto que hay que elegir las herramientas a usar para la gestión de configuraciones. Algunos ejemplos de estas herramientas pueden ser CVS que implementa un control de versiones de los EC manteniendo el registro de todo el trabajo y los cambios el nos ficheros que forman el proyecto. Permite además que distintos desarrolladores colaboren. Otra herramienta es ANT que se usa para la construcción del sistema y facilita el trabajo a la hora de realizar tareas mecánicas y repetitivas. Es similar a MAKE pero para Java. La base de datos de configuraciones registra cualquier información relevante relacionada con las configuraciones y sus elementos. Permite evaluar el impacto de los cambios en el sistema y generar informes sobre el proceso de GC. No incluye información sobre los elementos de configuración, sino que registra información sobre los usuarios de los componentes, los clientes, la plataforma de ejecución, los cambios propuestos. Se debe posibilitar el contestar a consultas relacionadas con este tipo de información.

Gestión de los cambios del sistema. El objetivo es seguir la pista a los cambios realizados y asegurar que se implementen de la forma más efectiva. Se establecen procedimientos para analizar los costes y beneficios de los cambios propuestos aprobando los que son relevantes y registrando qué componentes del sistema sufren cambios. El procedimiento se inicia cuando el EC se entrega al grupo de GC, es decir, cuando se convierte en línea base pasando a formar parte de la BD de configuraciones. Un posible procedimiento, pero que no el único, puede ser el siguiente:

El control de cambios también puede ser soportado por herramientas CASE, estas herramientas deben facilitar que los documentos correctos deben pasarse a las personas correctos en el tiempo correcto.

65

Aprobando Ingeniería del Software II 2010 Deben cumplir una serie de características, como poseer un editor, un sistema workflow, una base de datos de cambios y un generador de informes. Ejemplos pueden ser Bugzilla y Rational ClearRequest.

Construcción del sistema. Es el proceso de compilar y linkar los componentes software en un sistema ejecutable, de esta manera podemos concluir que diferentes sistemas se pueden obtener de diferentes combinaciones de componentes. Es un proceso soportado por herramientas automáticas conducidas por scripts de compilación. Además hay que distribuir los ejecutables en las máquinas correspondientes y en los directorios correspondientes. Al construir un sistema tenemos que tener claras las respuestas a las siguientes preguntas: -

¿Se han incluido todos los componentes? ¿Estamos usando la versión adecuada de los componentes? ¿Están disponibles todos los ficheros de datos (bases de datos)?

El flujo que sigue la construcción del sistema puede ser este:

Vemos que es el sistema de gestión de versiones el que usa los componentes adecuados para compilar posteriormente y linkar los objetos. Todo parte de un script de construcción que indica las órdenes que hay que ir ejecutando. Y hablando de estos scripts existe soporte CASE para la construcción del sistema con el objetivo de automatizar el proceso de construcción para reducir los errores humanos y el tiempo requerido. Estas herramientas deben tener en común: -

Lenguaje de especificación de dependencias y su intérprete. Soporte para la selección e instanciación de herramientas. Compilación distribuida. Gestión de objetos derivados. Refiérese a que si no se ha modificado un archivo no se compila.

Un ejemplo de estas herramientas es ANT. Es una herramienta para la construcción de programas basada en Java independientemente de la plataforma.

66

Aprobando Ingeniería del Software II 2010 Podemos hacer una comparación con make, para que nos quede más claro. Make usa un fichero llamado makefile que contiene el script de ejecución, en cambio ANT usa xml dentro de un fichero llamado build.xml. Los elementos principales de un fichero build.xml son: -

Project: Obligatorio, elemento central. Cada Project tiene uno o más targets, que se pueden ejecutar. Property: es un par nombre-valor que pueden ser definidas por el usuario. Target: es un conjunto de tasks que se ejecutan y pueden depender de otros targets. Task: es un código que se puede ejecutar, pueden tener varios atributos haciendo referencias a las properties.

Para que quede más claro he hecho una imagen poniendo en ella explicaciones:

67

Aprobando Ingeniería del Software II 2010 Gestión de versiones y releases. Al poder existir diferentes configuraciones para un mismo sistema el gestor de configuraciones son los responsables de seguir la pista a las diferencias entre las diferentes versiones para asegurar su correcto mantenimiento y que sean entregadas a los correspondientes clientes en el momento adecuado. Una versión es una instancia del sistema que difiere funcionalmente de otra. Esto es que pueden tener diferentes funcionalidades, rendimiento mejorado o errores reparados o pueden ser funcionalmente equivalentes pero diseñadas para diferentes plataformas. Normalmente las versiones son visibles en el interior del grupo de desarrollo. El gestor debe decidir cuantas versiones hay que hacer y cuando hacerlas así como los cambios introducidos en cada una de ellas. Una entrega o release es una instancia del sistema distribuida a los clientes, normalmente es más costosa pues implica la distribución del programa a los clientes. Al fin y al cabo es una versión entregada al cliente. Para gestionar las versiones y las entregas se deben realizar una serie de actividades. -

Hay que idear un esquema de identificación de versiones. No existe uno universal, hay que elegir alguno teniendo en cuenta ventajas e inconvenientes. Planificar cuando se debe producir una entrega. Equilibrio entre número de cambios y tiempo transcurrido entre entregas. Asegurar que los procedimientos y herramientas se aplican adecuadamente. Ver que se está haciendo bien.

Identificación de versiones. Se deben definir procedimientos para identificar las versiones de los componentes de forma no ambigua. Hay tres técnicas básicas. -

-

-

68

Numeración de versiones: Al componente se le asigna un número de versión explicito y único. Es el más usado. Para ver lo que contiene cada versión y los cambios hay que acudir a una tabla de features donde dice lo que se ha incorporado, quitado, o subsanado. Identificación basada en atributos: Cada componente tiene un nombre y un conjunto asociado de atributos para cada versión del componente. Los componentes se identifican por tanto por su nombre y los atributos. Es menos inmediata pero ofrece más información. Identificación orientada al cambio: casa sistema se nombra a partir de los atributos, pero también se asocia con una o más solicitudes de cambios. Esta opción es mucho más costosa. Está pensada solo para sistemas, no para componentes. Se deben introducir reglas de consistencia para limitar las combinaciones de cambios.

Aprobando Ingeniería del Software II 2010 Planificación de releases. El gestor de configuraciones es el responsable de decidir cuándo se entrega el sistema a los clientes, gestionando el proceso de crear dicha entrega y la documentación asociada. Una entrega puede incluir: -

Ficheros de configuración y de datos. Programa de instalación. Documentación electrónica y de papel. Empacado y publicidad.

El coste de una release es superior al de las versiones y nunca debemos asumir que el cliente dispone de releases anteriores. Es decir, que no hay que asumir que para que vaya la release 2, el cliente tiene que tener anteriormente la 1. Como en todo eso de la GC, la gestión de versiones puede ser automatizada con herramientas CASE. La gestión de versiones implica la gestión de grandes volúmenes de información para asegurar que los cambios en el sistema son almacenados y controlados. Las herramientas de gestión de versiones controlan un repositorio de EC. Para trabajar con un EC debemos extraerlo en un directorio de trabajo y posteriormente volverlo a introducir. Las características de estas herramientas deben ser: -

Identificación de versiones y entregas. Gestión de la información almacenada. Registro del historial de cambios. Desarrollo independiente. Soporte para uno o varios proyectos.

CVS es una aplicación que usa una arquitectura cliente-servidor donde el servidor guarda las versiones actuales del proyecto y su historial. Los clientes se conectan al servidor para sacar una copia completa del proyecto, realizar modificaciones, y posteriormente volver la copia al servidor o repositorio CVS. Varios clientes pueden sacar copias al mismo tiempo, luego el servidor trata de acoplar ambas versiones si es posible haciendo un merge. Si se ha modificado la misma línea el servidor avisa de ello al segundo en modificarla y este elige en cambiarla o dejar la que está. Cuando se completa la actualización la versión se incrementa en todos los componentes implicados y se almacena información del autor, descripción y fecha. Todo este tema del USO de CVS se especificará mejor en el material de prácticas.

69

Aprobando Ingeniería del Software II 2010 Tema 6: Automatización de las Pruebas

70

Aprobando Ingeniería del Software II 2010 Introducción. A partir de este tema entramos en un mundillo nuevo dentro de lo que es la asignatura. Nos hemos saltado el Tema 5 que será el que veamos el último. Los temas 5, 6 y 7 pertenecen a las PRUEBAS de un sistema. Y vamos a empezar a ver como se automatizan estas. Dentro del tema vamos a ver por qué es importante automatiza las pruebas y estudiar una herramienta para ello, JUnit. Nos tiene que quedar muy claro qué es JUnit y cómo utilizarlo.

Automatización de las pruebas. En la siguiente imagen podemos ver una panorámica general de lo que son las pruebas en sistemas software. Nosotros nos vamos a centrar en este tema en las pruebas unitarias donde pretendemos aislar elementos individuales del software del resto del código y determinar si funcionan exactamente como se esperaba probando cada unidad por separado. En general, las pruebas consistirán en un proceso para comprobar si la unidad hace lo que tiene que hacer. Dando unas entradas se tienen que producir determinadas salidas. Si se producen, todo guay, si no, pues mal.

Como he dicho, nos vamos a centrar en lo del recuadrito donde ejecutaremos las pruebas de unidad. Como se puede ver en distintas fases del proyecto hay distintos tipos de prueba. De esta manera una vez de integran las unidades probadas en un modulo, se prueba este para ver si cumple con el diseño, cuando se integran estos se hace una prueba funcional del sistema para ver si cumple con los requerimientos funcionales. Posteriormente se comprueba el rendimiento y requerimientos no funcionales para luego ver si se cumple con los requerimientos del cliente y por último una prueba de instalación en el entorno de producción.

71

Aprobando Ingeniería del Software II 2010 Las pruebas de unidad, las de integración, funcional y de rendimiento las englobaremos en los otros temas en pruebas de Verificación del software y las otras dos en Validación del mismo y las llamaremos indistintamente pruebas de aceptación. Como decía, las unidades será lo primero que se pruebe siendo ejemplo de unidades los elementos más pequeños como funciones, clases, etc. Es la ejecución de las pruebas unitarias lo que vamos a automatizar en este tema. Interesa automatizar las pruebas porque el hacer las pruebas y repetirlas con los mismos parámetros de entrada cada vez que modifiquemos el código costaría mucho tiempo hecho manualmente cosa que no interesa al gestor interesándole más consumir poco tiempo en ello. Los tests automáticos se pueden repetir cada vez que el código se modifica haciendo pruebas de regresión, siendo esto la repetición de una unidad tantas veces como se modifique el código estando entonces dicha unidad bien probada. Por otro lado, al automatizar las pruebas, se puede ampliar la extensión de las mismas pudiendo probar con mayor número de datos de prueba sin tener que hacerlo manualmente. Habíamos dicho también que había que aislar lo mejor posible las unidades, aunque esto no siempre es fácil, de hecho, a veces incluso es difícil. Para conseguir aislar las unidades y automatizar las pruebas necesitaremos usar dos conceptos. Driver: Es el código que automatiza la ejecución del conjunto de pruebas preparando los datos de prueba, realizando las llamadas a las unidades a probar, almacenando los resultados comprobando que son correctos y generar un informe de las pruebas. Para que se entienda, sería como un main principal y temporal donde llamamos a las funciones a probar y vemos si da lo que tiene que dar o no. Stub: Es el código que simula parte del programa llamado por la unidad a probar. Simula el código al que llama y devuelve un resultado. Por ejemplo seria una función de llamada a base de datos, pero que, por ejemplo, nosotros le ponemos lo que tiene que devolver directamente en lugar de conectar a la BD. NOTAS: Nuestro objetivo es hacer las pruebas, ver si está bien o mal, no es nuestro trabajo la depuración. No hay que cambiar el código que quiero probar entre pruebas.

72

Aprobando Ingeniería del Software II 2010

JUnit 4. Vamos a lo que vamos. Buscábamos que con unas entradas en concreto nos diese un resultado esperado. JUnit es un API de Java que permite crear los drivers (de hecho solo crea los drivers) para ejecutar los casos de prueba sobre los componentes UP de forma automática. Esta herramienta permite implementar las pruebas o tests enviando las entradas a las UP (parámetros de entrada), nos da respuestas de la ejecución de la UP (salidas esperadas) y determina si un test falla o no (informe). Los tests, se ejecutan a través de test runners que no son más que un mecanismo para leer las pruebas y ejecutarlas registrando y siguiendo la pista de los resultados de los tests. Resultados. Los resultados de las pruebas pueden ser varios, en concreto tres: Pass: El caso de prueba consigue su propósito y que el software a probar funciona tal y como se esperaba. Fail: Indica que el caso de prueba consigue su propósito pero el software a probar no funciona tal como se esperaba. Error: Indica que el caso de prueba no consigue su objetivo, normalmente por la ocurrencia de algún evento inesperado o que no se ha escrito correctamente.

73

Aprobando Ingeniería del Software II 2010

Usos de JUnit. JUnit normalmente se usa para aplicar una metodología TDD (Test Driver Development) escribiendo siempre un test JUnit y ejecutarlo antes de escribir la UP a probar por lo que es imperativo automatizar las pruebas. Cuando ejecutamos las pruebas implementamos el código de forma que sea el mínimo código requerido para “pasar” las pruebas. Si modificamos el código las pruebas las debe pasar igualmente, haciéndolo de forma incremental y haciendo por tanto tests de regresión. Esta metodología nos permite hacer una especificación completa del programa desde el principio (por ejemplo, al diseñar las pruebas podemos pensar que pasaría cuando a una función le pasamos números negativos). Tests y ejemplos. Un test es un conjunto de métodos Java que implementan el driver para probar las unidades del sistema. JUnit usa aserciones (asserts) para informar del resultado de un test, estas aserciones se implementan en un paquete y por ejemplo ofrece la comprobación. -

Igualdad entre objetos. Referencia a objetos idénticos. Referencias a objetos null o not null.

Nosotros, de forma obligada por Galipienso, debemos definir un caso de prueba en cada método de prueba proporcionando unos datos de entrada y un resultado esperado. El resultado esperado es obligatorio meterlo de forma explícita. Por ejemplo:

74

Aprobando Ingeniería del Software II 2010 Vemos que ponemos nosotros los datos de entrada y el resultado esperado. Comprobamos con un assert que el resultado de la UP y el resultado esperado sean iguales. Pasos para realizar las pruebas de unidad. Para hacer las pruebas de unidad tenemos que seguir una metodología paso a paso. 1. Preparar el entorno de pruebas para satisfacer determinadas condiciones. Por ejemplo inicializar valores de variables, establecer una conexión de red, etc.

2. Ejecutar el caso de prueba: ejecutar el código a probar usando datos de entrada si se requieren. 3. Evaluar los resultados obtenidos: comprobar si el resultado esperado es el mismo que el realmente obtenido. 4. Volver a restablecer el estado del entorno de pruebas a su situación origina. Por ejemplo puede ser necesario volver a inicializar ciertas variables para que se puedan ejecutar los tests.

NOTA: Los métodos implementados en 1 y 4 se llaman FIXTURES y se ejecutan siempre antes (before) y después del método de prueba (after). Las anotaciones @Before y @After se usan para indicar acciones que se ejecutan antes y después de cada método de prueba anotado con @Test. Incluso @After se ejecuta si han ocurrido excepciones. Además se permiten muchos @Before y muchos @After igual que no pueden ser necesarios. Si tenemos dos métodos de prueba la secuencia de ejecución sería: -

Befores. Prueba 1. Afters. Befores. Prueba 2. Afters.

Así llegamos a mi BPA! … jurjurmuhaha!

75

Aprobando Ingeniería del Software II 2010 Ademas de estos fixtures podemos ejecutar una vez antes de todos los métodos de prueba o una vez después de ellos y antes o después de todos los befores y afters. Esto puede ser útil para inicializar o detener servidores, establecer o cerrar comunicaciones, etc. Siendo casi siempre actividades que consumen mucho tiempo. Para ello se usan las anotaciones @BeforeClass y @AfterClass.

Aserciones. Están definidas en la clase JUnit Assert: -

Si una aserción es cierto, el método continúa ejecutándose. Si cualquier aserción es falsa, el método detiene su ejecución en dicho punto y el resultado del método de prueba será fail. Si se lanza cualquier otra excepción durante la ejecución del método el resultado de dicho método de prueba será error. Si no se viola ninguna aserción durante la ejecución del método el resultado será pass.

Todos los métodos de aserciones son métodos estáticos. Aquí un listado de las posibles aserciones de las que disponemos.

76

Aprobando Ingeniería del Software II 2010 Pruebas de excepciones. Se hace igual que en los otros métodos, pero después de @Test debemos indicar entre paréntesis la excepciones perada al ejecutar el método de prueba. Si no se lanza ninguna excepción, o bien si tiene lugar una no esperada, el test fallará, si alcanzamos el final del método sin lanzar excepción se provoca un fallo en el test.

Por otro lado, si queremos probar el mensaje de la excepción, o limitar el ámbito en el que se espera la excepción, capturaremos la excepción y usaremos la aserción fail si no se lanza la excepción. Es decir, podemos poner fail dentro de un try cuando se debería haber lanzado una excepción.

Un par de ejemplos más: Hacer notar que siempre que estamos hablando de probar excepciones las probamos en el método de test por lo que será el método de la UP a probar el que tenga que lanzar el error.

77

Aprobando Ingeniería del Software II 2010 Organización de los tests en JUnit. Cada método de prueba representa un único caso de prueba que puede tener un resultado de forma independiente. Normalmente todos los tests de una clase Java se agrupan en una clase separada siguiendo una serie de convenciones siendo la clase a probar Value y la clase que contiene los tests ValueTest (Calculadora y CalculadoraTest). Las agrupaciones de tests se llaman SUITES, en estas suites todos los tests de una clase Java se agrupan en una clase separada.

Y se pueden ejecutar desde el código, desde la línea de comandos o desde eclipse de las siguientes maneras.

La integración de JUnit con Eclipse la veremos en prácticas así como más ejemplos. Esto es todo por ahora.

78

Aprobando Ingeniería del Software II 2010 Tema 7: Pruebas Dinámicas

79

Aprobando Ingeniería del Software II 2010 Introducción. En este tema continuamos con las pruebas. Concretamente vamos a hablar de las pruebas dinámicas de las cuales solamente vamos a practicar dos métodos. Por otro lado vamos a introducir brevemente las pruebas estáticas viendo un tipo de estas. En este tema tenemos que terminar conociendo las diferencias entre pruebas estáticas y dinámicas así como saber diseñar las segundas. Por otro lado dado un proyecto tenemos que saber diseñar pruebas de caja blanca y pruebas de caja negra.

Pruebas dinámicas vs pruebas estáticas. Primero de todo vamos a ver la diferencia entre estos tipos de pruebas. Por un lado tenemos las pruebas dinámicas que solamente se pueden hacer durante la implementación ya que necesitamos ejecutar sí o sí el código fuente a probar para detectar los fallos, por ello tenemos que disponer del código. No se puede concluir que hay algún error en el código si no lo ejecutamos con unos datos de entrada y comprobamos que el resultado real es igual al esperado, por lo tanto solo podemos usarlas cuando disponemos de un prototipo o un ejecutable del programa. Por el contrario, las pruebas estáticas son aquellas que no necesitan ejecutar el código para detectar defectos en el código. Normalmente son más efectivas, detectando más errores en menos tiempo. Como no es necesario ejecutar el código se pueden aplicar en cualquier momento del desarrollo y pueden resultar más efectivas en cuanto a coste que las pruebas dinámicas. El disponer de dos tipos nos pueden llevar a pensar que unas son mejores que otras, pero no es así, son pruebas complementarias, cada tipo de pruebas detectan un tipo de errores que las otras no. Si nos dejamos un error usando unas pruebas podemos detectarlo con las otras y viceversa. Pruebas estáticas: Inspecciones de código. Estas inspecciones las podemos realizar en cualquier momento del desarrollo y no es necesaria la ejecución del código para detectar errores. Se trata de un estudio a fondo del código que tiene que estar correcto y compilable. Durante las inspecciones de código hay una serie de roles que desarrollan en proceso de inspección. Roles: -

80

Desarrollador: Los autores del código tienen que estar presentes ya que ellos serán los que mejor comprenden el código. Moderador: Conduce y organiza la reunión y registra los resultados decidiendo si no hay errores, si los hay pero no son importantes o los hay graves. Inspector: Miran el código, lo analizan y dicen lo que han encontrado en él.

Aprobando Ingeniería del Software II 2010 Proceso: -

-

-

Preparación individual: Es trabajo del moderador repartir el código a priori para que cada rol se lo estudie a fondo para cuando llegue la reunión saber de que se va a hablar y solamente comentar lo que se ha encontrado y no malgastar tiempo. Recopilación de resultados: se trata de poner en común lo que se ha encontrado teniendo como objetivo tratar el mayor número de errores en el menor tiempo posible. Proceso corto: No debe ser un proceso de más de dos horas.

Los artefactos a inspeccionar se examinaran usando unas técnicas de lectura, siendo una de ellas las listas de comprobación de errores que sin simples listas de preguntas a las que tenemos que responder sí o no, por ejemplo, ¿están todas las variables inicializadas? Estas listas de comprobación son una estandarización de las comprobaciones y dicha estandarización facilita posteriormente la automatización de la inspección. Las listas de comprobación se pueden ir modificando con el tiempo a medida que van saliendo nuevos tipos de errores, pero un ejemplo estándar de lista de comprobación puede ser el siguiente: -

-

-

-

-

81

Errores de datos. o ¿Están todas las variables inicializadas antes de que se usen? o ¿Todas las constantes tienen nombre? o ¿El primer elemento de los arrays empieza por 0,1 o algo más? o ¿La cota superior de los arrays es longitud-1 o longitud? o Si se usan cadenas de caracteres, ¿hay un delimitador asignado explícitamente? Errores de control. o Para cada condición, ¿la condición es correcta? o ¿Terminarán todos los bucles? o Las sentencias compuestas, ¿tienen los paréntesis bien puestos? o En los switch case ¿se contemplan todos los caso? Errores de entrada/salida. o ¿Las variables de entrada tienen todas valor antes de usarlas? o ¿Las variables de salida tienen un valor asignado antes de ser enviadas a la salida? Errores de interfaz. o Las llamadas a las funciones, ¿tienen el número correcto de parámetros? o ¿Coinciden los tipos de parámetros? o ¿Los parámetros están en el orden correcto? o Si los componentes acceden a memoria, ¿tienen todos los mismos modelos de memoria compartida? Errores de memoria. o Si una estructura enlazada se modifica, todos los enlaces a esta estructura ¿se reasigan todos? o Si se usa memoria dinámica, ¿se ha reservado memoria correctamente?

Aprobando Ingeniería del Software II 2010 -

o ¿Se libera el espacio después de usarlo cuando no se usa más? Errores de manejo de excepciones. o ¿Se han tenido todos las opciones que pueden provocar error en cuenta?

Pruebas estáticas automáticas. Como había dicho antes, si se estandarizan las pruebas son susceptibles de ser automatizadas pues estandarizar consiste en sistematizar las cosas y a partir de ahí siempre lo haremos igual de forma mecánica. Para automatizar las inspecciones usaremos analizadores estáticos, herramientas basadas en el procesamiento de ficheros fuente en formato de texto. No solo detectaremos errores sino que también podemos detectar código basura. Las etapas a realizar durante un análisis estático son las siguientes. -

Análisis del flujo de control: Comprobaciones de bucles con varias entradas y salidas, código no alcanzable, etc. Análisis de uso de los datos: detección de variables no usadas, escritas dos veces sin asignaciones intermedias, variables declaradas pero no usadas, etc. Análisis de la interfaz: Comprobación de inconsistencias de los prototipos de las funciones y procedimientos y su uso. Análisis de flujo de información: Identifica las dependencias entre las variables de entrada y salida. Análisis de caminos: Identificación de caminos y sentencias ejecutadas en dichos caminos.

Ejemplos de herramientas estáticas automáticas. Disponemos de varias herramientas para realizar inspecciones de código. Tenemos a Lint para código C, PMD para Java detectando código duplicado, código inaccesible, expresiones complejas y posibles errores. CPD para Java también detecta duplicidades, Crap4J descubre qué parte del código es difícil de mantener y Sonar para Java, Flex, PL, C++) es la más potente de todas, ya que contempla todo lo anterior en una sola herramienta. Pruebas dinámicas. Este tipo de pruebas si las vamos a practicar en prácticas. Como habíamos dicho se necesita la ejecución del código para detectar la presencia de errores. El proceso de pruebas requiere previamente un diseño de casos de pruebas. Siendo este diseño la elección de las entradas que creemos serán convenientes y saber el resultado esperado obteniendo los casos de prueba.

82

Aprobando Ingeniería del Software II 2010

Casos de prueba = entradas + salidas esperada. Podemos resumir el proceso con la anterior imagen. Siendo el diseñar los casos de prueba donde nos vamos a centrar en este tema y siendo los otros tres pasos lo que automatiza JUnit. Para diseñar los casos de prueba no basta con elegir datos de entrada aleatorios ya que gastaremos mucho tiempo para nada, si elegimos valores aleatorios estructuralmente podemos no probar alguna parte de código donde pueda haber un error, por ejemplo, nunca entraríamos en un bucle o en una rama de un if, por otro lado, si elegimos los datos aleatoriamente podemos estar probando siempre una cosa que va bien y quizá con una prueba que pruebe esa parte sabemos que está bien así que no sería necesario probar con más datos de entrada.

Por ello debemos de ser sistemáticos a la hora de elegir los datos de entrada y hacer uso de los particionamientos de estos datos agrupando los datos de entrada que llevan a la misma conclusión. Las pruebas sistemáticas dependen de estos particionamientos representando conjuntos de posibles comportamientos del sistema. Debemos elegir muestras significativas de cada partición asegurándonos de cubrir todas las particiones. En este tema descubriremos como identificar las particiones. Destacar que hay muchos métodos de pruebas dinámicas garantizando algo cada método y unos métodos garantizas cosas que otros no.

83

Aprobando Ingeniería del Software II 2010 Métodos de prueba de CAJA BLANCA. Las pruebas de caja blanca se llaman también pruebas estructurales obteniendo los casos de prueba a partir del CODIGO de la unidad a probar. Se analiza la estructura del código a probar para obtener los datos de entrada necesitados. Se necesita tener la UP implementada, es decir, necesitamos su código.

En la siguiente imagen se puede ver a lo que nos referimos, a partir del código obtenemos los datos de entrada, pasándoselos al código para ejecución y viendo las salidas de los tests. Pruebas de caminos. Nuestro objetivo serán, principalmente, con el menor número de pruebas obtener el mayor numero de errores. La prueba de caminos es un método de caja blanca cuyo OBJETIVO es ejecutar cada camino independiente en el código a probar garantizando que se ejecutan todos ellos. Si sabemos que se ejecutan todos estos caminos estaremos ejecutando todas las sentencias del código al menos una vez y que todas las condiciones se evalúan a cierto y falso. Un camino independiente es un camino en un grafo de flujo que representa un “camino” del programa que difiere de otros caminos en al menos un nuevo conjunto de sentencias y/o una nueva condición. Los pasos a seguir para diseñar las pruebas son mecánicos y secuenciales, son los siguientes: a) b) c) d)

Construir el grafo de flujo del programa. Calcular la complejidad ciclomática CC. Obtener los caminos independientes. Determinar los datos de entrada de forma que se ejerciten todos los caminos independientes. e) Determinar el resultado esperado. El resultado del diseño de las pruebas de camino se presentarán en tablas como la siguiente siendo los datos de entrada y resultados esperados DATOS REALES Y CONCRETOS, MUY IMPORTANTE, si no es así en el ejercicio del examen se tendrá un CERO.

84

Aprobando Ingeniería del Software II 2010

Con estos datos se los pasaremos a JUnit. Grafo de flujo. Los grafos de flujo representan el flujo de ejecución de la unidad a probar, los nodos de estos grafos representan decisiones (condiciones) y sentencias consecutivas y los arcos representan el flujo de control.

Es importante para el examen tener CLARO que cada nodo SOLAMENTE puede representar UNA SOLA DECISIÓN. Complejidad Ciclomática CC. Es una métrica que proporciona una medida de la complejidad lógica de un componente software y se calcula a partir del grafo de flujo de la siguiente manera: CC = número de arcos – número de nodos + 2. El valor CC indica el máximo número de caminos independientes en el grafo. Por ejemplo, para una sentencia if:

Obtención de caminos independientes. Hay que buscar tantos caminos independientes como valor obtenido por la CC, aunque pueden salir menos caminos siendo la CC la cota superior de caminos independientes. Con esos caminos recorreremos todos los nodos y todas las aristas del grafo, por ejemplo:

85

Aprobando Ingeniería del Software II 2010

Obtener datos de entrada que ejerciten los caminos independientes. Simplemente, una vez obtenidos los caminos tenemos que decidir los datos de entrada que obliguen a recorrer cada camino y poner el resultado esperado.

Ejemplo:

86

Aprobando Ingeniería del Software II 2010

87

Aprobando Ingeniería del Software II 2010 Métodos de pruebo de CAJA NEGRA. Recordamos que seguimos dentro de las pruebas dinámicas que son las que necesitan ejecutar el código para obtener los casos de prueba, además, en las de caja blanca necesitábamos tener el código fuente visible para hacer los casos de prueba, cosa que no es necesaria en las pruebas de caja negra. En estas pruebas se obtienen a partir de las especificaciones de la unidad a probar tratando a esta como una caja negra de la que solo conocemos sus entradas y sus salidas.

Con este tipo de pruebas tenemos la ventaja de que podemos crear los casos de prueba antes de implementar el código cosa bastante útil si queremos seguir una metodología de desarrollo guiada por las pruebas. Dentro de este tipo de método vamos a ver uno en concreto, la prueba de particiones equivalentes. Prueba de particiones equivalentes. Este método garantiza que probamos con todas las particiones necesarias en los datos de entrada. Este es su objetivo, probar todas y cada una de las particiones de entrada y salida tanto válidas como inválidas. Todos los datos que pertenecen a una partición de entrada tienen el mismo comportamiento dentro de la caja negra a probar, es decir, si una partición válida son los números positivos cualquier valor dentro de ese grupo hará que el programa se comporte igual y provoque la misma salida (suponiendo que solo se tenga una entrada). Pasos para diseñar las pruebas. Para crear los casos de prueba primero tenemos que crear las particiones de entrada y de salida válida y no válida para cada uno de los parámetros de entrada y de salida. Luego hay que combinar esas particiones de entrada y de salida cumpliendo una serie de restricciones: -

-

88

Como máximo solo se puede probar una clase inválida en cada uno de los casos de prueba (cada fila de la tabla de casos de prueba puede contener como mucho una entrada no válida). Cada uno de los casos de prueba puede ejercitar cualquier número de entradas válidas (cada fila puede contener más de una entrada válida).

Aprobando Ingeniería del Software II 2010 -

La tabla resultante tendrá las filas necesarias para que todas las clases válidas y no válidas sean probadas al menos una vez.

Si nos presentan una tabla de este tipo pero sin la columna de clases ni la de caminos nos será imposible distinguir el método por el cual se han diseñado los casos de prueba. JUnit automatiza esta tabla y no tienen en cuenta el método usado para diseñar los casos de prueba. Reglas para obtener las particiones. Se presentan algunas maneras de generar particiones que luego se tendrán que combinar para casos más complejos.

Además podemos crear particiones con valores límite para probar valores que estén cerca de los límites de las particiones. Veremos más casos y ejemplos en las prácticas.

89

Aprobando Ingeniería del Software II 2010 Tema 5: Verificación y Validación

90

Aprobando Ingeniería del Software II 2010 Este es el último tema del curso, el tema 5, aunque lo vemos después del 6 y el 7 porque en prácticas convenía seguir este orden. En este tema se va a remarcar la importancia de las pruebas así como clasificarlas y hacer el uso de stubs. Además si nos dan un proyecto software tenemos que saber planificar las pruebas e implementar stubs.

Pruebas. Principales Conceptos. Las pruebas nos ayudan a conseguir el principal objetivo del gestor, el entregar el proyecto a tiempo sin sobreexceder un coste y que entregue unas funcionalidades concretas. Las pruebas nos ayudan a ver que las funcionalidades son las adecuadas. Repetimos que lo primero que se deja de hacer cuando falta tiempo son las pruebas por lo que buscamos ser eficientes y encontrar el máximo número de errores en el menor tiempo posible con el menor número de casos de prueba. Destacar también que durante el desarrollo, un 30-40% de las actividades están relacionadas con las pruebas. Los objetivos de las pruebas, de la verificación y validación son descubrir defectos en el sistema (descubrir cosas que no van bien) y evaluar si el sistema funciona según las expectativas del cliente (¿el cliente está contento con el programa?). Estos dos términos forman parte del proceso de prueba software (Verificación y Validación). Recordamos de los otros temas que el proceso de prueba puede demostrar la presencia de errores y nunca la ausencia de estos. Para ver que hay ausencia de errores tendríamos que hacer uso de pruebas exhaustivas que recorriesen todos los caminos del programa, pero son impracticables. En el ejemplo hay 10^14 caminos. El coste temporal haría estas pruebas impracticables con la tecnología actual. En cuanto a la verificación: -

Implica probar el programa implementado para ver si funciona conforme a las especificaciones. Tenemos que responder ¿Estamos construyendo el programa CORRECTAMENTE? Perseguimos detectar situaciones en las que el comportamiento del software es incorrecto o no conforme a la especificación. Una prueba exitosa es aquella que demuestra que el programa funciona mal.

En cuanto a la validación: -

91

Implica probar el programa implementado para ver si satisface las necesidades del cliente. Se trata de responder: ¿Estamos construyendo el programa correcto? Buscamos que el programa funcione correctamente usando los casos de prueba que reflejen el uso esperado del sistema.

Aprobando Ingeniería del Software II 2010 -

Una prueba exitosa es aquella que muestra que el programa es el correcto.

El proceso de las pruebas ya lo vimos en el tema 7, pero aquí se vuelve a ver. A partir de los métodos que hemos aprendido debemos diseñar unos casos de prueba. Posteriormente se preparan los datos y se ejecutan, podemos automatizar esta ejecución con herramientas como JUnit. Posteriormente se comparan los resultados obtenidos con los esperados y se hace un informe de las pruebas.

El objetivo, de nuevo, es encontrar defectos en el software de la forma más eficiente posible, es decir, con el menor número de pruebas posible. Esta es la manera de proceder al hacer las pruebas. Pero este proceso hay que repetirlo en tres etapas generales durante el desarrollo de un software. -

Pruebas de unidad o de componentes. Prueba del sistema o verificación. Pruebas de aceptación o validación.

Además de saber que es cada cosa y el proceso de las pruebas no hay que dejar pasar el término depuración y destacar que son procesos distintos, las pruebas y la depuración. El primero de ellos pone en evidencia la presencia de errores y el otro localiza y repara los errores. Normalmente, en proyectos grandes, estas actividades las realizan dos persos distintas pero en proyectos relativamente pequeños lo puede hacer la misma persona cambiando de rol.

Planificación de las pruebas. Como todos los planes que hemos ido viendo a lo largo de la asignatura en este también tenemos que responder QUE pruebas hacer, COMO hacerlas, QUIEN las tiene que hacer y CUANDO deben hacerse. Decir además que todo esto puede verse influenciado por el modelo de proceso seguido como veremos posteriormente.

92

Aprobando Ingeniería del Software II 2010 Antes de nada vamos a responder el QUE, ¿qué tipo de pruebas tenemos que hacer? Para ello hay que conocer la clasificación de las pruebas, vamos a ver varias de estas clasificaciones. Según la necesidad de ejecutar el código para detectar defectos: -

Dinámicas. Estáticas.

Según los objetivos de las pruebas: -

-

Pruebas de validación (necesito al cliente). o Alfa: Son aquellas en las que nos podemos reunir con el cliente. Una vez reunidos hacemos que el cliente use el software y vamos tomando nota de sus movimientos y los fallos detectados. o Beta: Se lanza un número limitado de unidades al mercado o en Internet y mediante un feedback por parte de los usuarios se detectan errores. Pruebas de verificación (defectos). o Pruebas de particiones (Caja blanca). o Pruebas de estructurales (Caja negra).

Según el elemento al que se aplica: -

-

Pruebas del sistema. o Pruebas de integración (regresión). o Pruebas de aceptación o de entregas. o Pruebas de propiedades emergentes. Pruebas de componentes. o Pruebas de funciones o métodos dentro de un objeto. o Prueba de clases. o Pruebas de componentes formados a partir de la composición de varios objetos (de Interfaces).

Especial mención requieren las pruebas de integración, implicando este proceso construir el sistema a partir de sus componentes individuales y probar el (sub)sistema resultante para detectar defectos en las interacciones entre dichos componentes. Este tipo de pruebas suelen realizarse de forma incremental. Lo fundamental es el orden a seguir a la hora de hacer la integración disponiendo de dos modelos según el orden de las llamadas entre componentes.

93

Aprobando Ingeniería del Software II 2010 Bottom-Up. Los errores se localizan más fácilmente que con big-bang (todo de golpe) y no se necesitan stubs puesto que se primero se integran los componentes que no hacen llamadas a otros componentes. Otra ventaja es que las pruebas pueden hacerse en conjunción con la implementación. Como inconveniente tiene que los módulos de más alto nivel se prueban los últimos y por lo tanto se prueban menos y no disponemos de un esqueleto del sistema hasta el final por lo que tendremos que usar algún driver. Top-Down. No hacen falta muchos drivers puesto que se hace de arriba abajo integrando primero los componentes de más alto nivel por lo que harán falta bastantes stubs. Por otro lado estos módulos son los más probados siendo los menos los más pequeños y potencialmente reutilizables. Este método no es aconsejable cuando no queremos que sea muy costoso puesto que la creación de stubs consume bastante tiempo. Hay otros modelos de integración, por ejemplo el modelo sándwich mezcla los dos y va integrando por arriba y por abajo. El modelo dirigido por los riesgos es usado por UP y da igual el orden de llamada, se integra primero lo más crítico. Durante la integración se hacen pruebas de regresión que consiste en una vez integrado un componente se prueba todo lo que ya estaba integrado. Proceso de planificación. Se trata de enlazar las actividades de pruebas y las de desarrollo buscando un equilibrio entre las pruebas estáticas y las dinámicas.

94

Aprobando Ingeniería del Software II 2010 La imagen anterior muestra un enlace general entre el desarrollo y las pruebas. Básicamente viene a demostrar que las primeras pruebas diseñadas son las que se prueban las últimas. Más que nada por los requerimientos de las pruebas para ser diseñadas. Primero, a partir de la especificación de los requerimientos y del sistema se puede hacer un plan de aceptación. A partir de la especificación del sistema y del diseño de los componentes se puede planificar las pruebas de integración, por ejemplo elegir el orden de integración cuando dispongamos de los componentes. A partir del diseño y de un diseño más detallado se puede hacer un plan de integración de los subsistemas. Una vez codificado el programa realizamos las pruebas en orden inverso, como ya tenemos los componentes podemos hacer la integración de los subsistemas, luego la del sistema y por último la de aceptación. A partir de este modelo general surgen otros dos llamados modelo en V y modelo en W, la diferencia entre ellos es el momento en el que se planifican las pruebas. Modelo en V. En este modelo se empiezan a diseñar las pruebas después de codificar el programa. De esta manera tenemos como ventaja que si han cambiado los requerimientos durante la codificación cuando planifiquemos las pruebas del sistema ya tendremos esos cambios en cuenta. Como desventaja tenemos que puede pasar mucho tiempo desde las diferentes fases hasta que se diseñan y realizan las pruebas. Modelo en W. Este modelo se parece más al general, planificando las pruebas justo después de llevar a cabo las fases del proyecto. Hay una gran cercanía en el tiempo entre la fase y el diseño de las pruebas por lo que suelen estar más claras. Una vez se codifica se pasan las pruebas en orden inverso al diseño de estas y se hace un debug cuando se encuentra algún error volviendo a ejecutar el tipo de pruebas anterior.

95

Aprobando Ingeniería del Software II 2010 Además de estos modelos hemos estudiado las pruebas como disciplina de desarrollo en el modelo UP haciéndose estas a lo largo de todas las iteraciones y fases, desde el comienzo al final de las fases. Eso sí, en cada fase haremos un tipo de pruebas adecuado para lo que se está haciendo. Así, en las fases tempranas, a partir del modelado del sistema, podemos hacer pruebas estáticas y una vez vamos integrando componentes, antes de ello hacer pruebas de unidad. Etc. En el modelo XP, como vimos, se sigue una metodología de desarrollo dirigida por las pruebas, de esta manera primero se crea la prueba de unidad y se desarrolla el código necesario para pasar estas pruebas. Si falla la prueba puede simplificarse el código o cambiar de parejas para detectar los errores. Se sigue programando entonces para satisfacer la prueba. Además se va haciendo una integración constante probando el 100% de las pruebas de unidad al sistema.

96

Aprobando Ingeniería del Software II 2010 Uso de Stubs. Como vimos en el tema 6 con JUnit se pueden automatizar las pruebas pero había un problema cuando el método a probar llamaba a métodos u objetos no implementados. Para eso se usan los Stubs, para sustituir el código de esas llamadas. Partimos de que está TOTALMENTE PROHIBIDO modificar la clase a probar. Los stubs, como se decía, son implementaciones ficticias de aquellos métodos a los que invoca el componente a probar.

Los stubs proporcionan respuestas predefinidas para las unidades a probar, de forma que se pueden hacer aserciones sobre la forma en que dicha unidad reacciona ante dichas respuestas. Se hace una verificación de los resultados obtenidos basada en el ESTADO, es decir, se comprueba que la unidad funciona correctamente examinando el resultado de la ejecución de dicha unidad. No importa lo que pase dentro del metodoB, sino lo que devuelve y como se comporta la UP con ese valor de vuelta. Ejemplo de Stub: Queremos probar un método que representa un pedido a un almacén, concretamente se trata de Order.fill(warehouse). Si hay suficientes unidades del producto en el almacén el pedido es procesado y se descuentan las unidades del producto correspondiente en el almacén. Si no hay suficientes, no se procesa.

97

Aprobando Ingeniería del Software II 2010 Existen también los Mocks, aunque no los vamos a usar siempre es bueno saber que pinta tienen. La diferencia fundamental con los Stubs es que se realiza una verificación de la corrección basada en el comportamiento, lo que significa que se comprueba si el Mock realiza las llamadas en el orden correcto.

Los stubs son buenos usarlos porque pueden simular el comportamiento de objetos complejos y por lo tanto, resultan útiles cuando no es práctico o resulta imposible incorporar objetos reales en dicha unidad de prueba. Es conveniente usarlos cuando el objeto real: -

Proporciona resultados no deterministas. Contiene estados difíciles de crear o reproducir. Es lento (base de datos compleja). No existe o puede cambiar su comportamiento. Puede tener que incluir métodos solo para las pruebas.

Los stubs se pueden implementar de dos maneras. Mediante Interfaces. Suponemos que tenemos una clase que gestiona unos pedidos. El método recibirPedido envía un email cuando completa la recepción de un pedido.

98

Aprobando Ingeniería del Software II 2010

Refactorizamos el código real de la clase a probar de la siguiente manera.

La distribución de código quedaría algo así.

Y luego a la hora de probar con JUnit.

99

Aprobando Ingeniería del Software II 2010

Mediante Herencia. Tenemos una clase que procesa pedidos. El método process calcula y aplica un descuento sobre el pedido. El descuento se obtiene consultando el servicio PricingService que no tenemos implementado.

100

Aprobando Ingeniería del Software II 2010

101

Aprobando Ingeniería del Software II 2010 Ejercicio planteado en clase del examen de Diciembre 2009.

Dada esa clase, implementar con JUnit las pruebas para recorrer todos los caminos del método calculaConsumo. Indicar todo el código necesario para automatizar las pruebas. Asumir que DIURNA y NOCTURNA son dos valores globales. Yo asignaré a DIURNA 5cents y a NOCTURNA 2cents. Heredo de la clase a probar para sobreescribir el método getHoraActual ya que usa una llamada al sistema, lo sobrescribo para lo que yo quiero.

102

Aprobando Ingeniería del Software II 2010 Ahora con JUnit implementamos las pruebas sobre esta nueva clase.

103