sábado, 6 de diciembre de 2014

EJEMPLO PRUEBA CAJA BLANCA






Ejemplo Número Primo

public boolean esPrimo(String[] args)
{
    if(args.length==0)
        throw new ErrorFaltaParametro();
    else if(args.length>1)
        throw new ErrorSoloUnParametro();
    else{
        try{
            int num=Integer.parseInt(args[0]);
            if(num<0)
                throw new ErrorNumeroNoPositivo();
            else{
                for(int i=2;i<num;i++)
                    if(num%i==0)
                        return false;
                return true;
            }
    }
    catch(NumberFormatException e)
    {
        throw new ErrorNoNumero();
    }
}

Pruebas de Caja Blanca

Entrada
Resultado
Ejecuciones

Falta parámetro
args.length==0 true
xx yy
Solo 1 parámetro
args.length==0 false args.length>1 true
-2
Número no positivo
args.length==0 false args.length>1 false
num<=0 true
2
Primo
Num<=0 false
Ejecuta bucle 0 veces
3
Primo
Num<=0 false
Ejecuta bucle 1 vez
4
No Primo
Num<=0 false
Ejecuta bucle 2 veces
Num%i==0
23
Primo
Num<=0 false
Ejecuta bucle N veces
Num%i=0 false
Palabra
No es un número
Excepción



OTRAS PRUEBAS



Regresión (regression testing)

Todos los sistemas sufren una evolución a lo largo de su vida activa. En cada nueva versión se supone que o bien se corrigen defectos, o se añaden nuevas funciones, o ambas cosas. En cualquier caso, una nueva versión exige una nueva pasada por las pruebas. Si éstas se han sistematizado en una fase anterior, ahora pueden volver a pasarse automáticamente, simplemente para comprobar que las modificaciones no provocan errores donde antes no los había.

Las pruebas de regresión son particularmente espectaculares cuando se trata de probar la interacción con un agente externo. Existen empresas que viven de comercializar productos que "graban" la ejecución de una prueba con operadores humanos para luego repetirla cuantas veces haga falta "reproduciendo la grabación". Y, obviamente, deben monitorizar la respuesta del sistema en ambos casos, compararla, y avisar de cualquier discrepancia significativa. 

Recorridos (walkthroughs)

Quizás es una técnica más aplicada en control de calidad que en pruebas. Consiste en sentar alrededor de una mesa a los desarrolladores y a una serie de críticos, bajo las órdenes de un moderador que impida un recalentamiento de los ánimos. El método consiste en que los revisores se leen el programa línea a línea y piden explicaciones de todo lo que no está meridianamente claro. Puede que simplemente falte un comentario explicativo, o que detecten un error auténtico o que simplemente el código sea tan complejo de entender/explicar que más vale que se rehaga de forma más simple. Para un sistema complejo pueden hacer falta muchas sesiones.

Esta técnica es muy eficaz localizando errores de naturaleza local; pero falla estrepitosamente cuando el error deriva de la interacción entre dos partes alejadas del programa. Nótese que no se está ejecutando el programa, sólo mirándolo con lupa, y de esta forma sólo se ve en cada instante un trocito del listado. 


Aleatorias (random testing)

Ciertos autores consideran injustificada una aproximación sistemática a las pruebas. Alegan que la probabilidad de descubrir un error es prácticamente la misma si se hacen una serie de pruebas aleatoriamente elegidas, que si se hacen siguiendo las instrucciones dictadas por criterios de cobertura (caja negra o blanca).

Como esto es muy cierto, probablemente sea muy razonable comenzar la fase de pruebas con una serie de casos elegidos al azar. Esto pondrá de manifiesto los errores más patentes. No obstante, pueden permanecer ocultos errores más sibilinos que sólo se muestran ante entradas muy precisas.

Si el programa es poco crítico (una aplicación personal, un juego, ...) puede que esto sea suficiente. Pero si se trata de una aplicación militar o con riesgo para vidas humanas, es de todo punto insuficiente.

Solidez (robustness testing)

Se prueba la capacidad del sistema para salir de situaciones embarazosas provocadas por errores en el suministro de datos. Estas pruebas son importantes en sistemas con una interfaz al exterior, en particular cuando la interfaz es humana.

Por ejemplo, en un sistema que admite una serie de órdenes (commands) se deben probar los siguientes extremos:

·         órdenes correctas, todas y cada una
·         órdenes con defectos de sintaxis, tanto pequeñas desviaciones como errores de bulto
·         órdenes correctas, pero en orden incorrecto, o fuera de lugar
·         la orden nula (línea vacía, una o más)
·         órdenes correctas, pero con datos de más
·         provocar una interrupción (BREAK, ^C, o lo que corresponda al sistema soporte) justo después de introducir una orden.
·         órdenes con delimitadores inapropiados (comas, puntos, ...)
·         órdenes con delimitadores incongruentes consigo mismos (por ejemplo, esto]

Aguante (stress testing)

En ciertos sistemas es conveniente saber hasta dónde aguantan, bien por razones internas (¿hasta cuantos datos podrá procesar?), bien externas (¿es capaz de trabajar con un disco al 90%?, ¿aguanta una carga de la CPU del 90?, etc.)

Prestaciones (performance testing)

A veces es importante el tiempo de respuesta, u otros parámetros de gasto. Típicamente nos puede preocupar cuánto tiempo le lleva al sistema procesar tantos datos, o cuánta memoria consume, o cuánto espacio en disco utiliza, o cuántos datos transfiere por un canal de comunicaciones, o ... Para todos estos parámetros suele ser importante conocer cómo evolucionan al variar la dimensión del problema (por ejemplo, al duplicarse el volumen de datos de entrada).

Mutación (mutation testing)

Es una técnica curiosa consistente en alterar ligeramente el sistema bajo pruebas (introduciendo errores) para averiguar si nuestra batería de pruebas es capaz de detectarlo. Si no, más vale introducir nuevas pruebas. Todo esto es muy laborioso y francamente artesano. 



ACTIVIDAD 1 (OBLIGATORIA) 
  • Consulta los siguientes enlaces. Elige un error de cada enlace y elabora un documento donde los expliques con tus palabras.

 ACTIVIDAD 2 (VOLUNTARIA)
¨     Intenta describir ejemplos prácticos que encuentres por la red sobre las distintas pruebas vistas en este punto
 

TIPOS DE PRUEBAS





  • En función de qué conocemos:
    • Pruebas de caja negra (Pruebas Funcionales): no conocemos la implementación del código, sólo la interfaz. Tan sólo podemos probar dando distintos valores a las entradas y salidas.
    • Pruebas de caja blanca (Pruebas Estructurales): conocemos el código (la implementación de éste) que se va a ejecutar y podemos definir las pruebas que cubran todos los posibles caminos del código.
  • Según el grado de automatización:
    • Pruebas manuales: son las que se hacen normalmente al programar o las que ejecuta una persona con la documentación generada durante la codificación (P. ej.- comprobar cómo se visualiza el contenido de una página web en dos navegadores diferentes).
    • Pruebas automáticas: se usa un determinado software para sistematizar las pruebas y obtener los resultados de las mismas (P. ej.- verificar un método de ordenación).
  • En función de qué se prueba:
    • Pruebas unitarias: se aplican a un componente del software. Podemos considerar como componente (elemento indivisible) a una función, una clase, una librería, etc. En nuestro caso, generalmente hablaremos de una clase como componente de software.
    • Pruebas de integración: consiste en construir el sistema a partir de los distintos componentes y probarlo con todos integrados. Estas pruebas deben realizarse progresivamente. Se centran en probar la coherencia semántica entre los diferentes módulos, tanto de semántica estática (se importan los módulos adecuados; se llama correctamente a los procedimientos proporcionados por cada módulo), como de semántica dinámica (un módulo recibe de otro lo que esperaba). Normalmente estas pruebas se van realizando por etapas, englobando progresivamente más y más módulos en cada prueba.
o        Pruebas funcionales: sobre el sistema funcionando se comprueba que cumple con la especificación (normalmente a través de los casos de uso).
    • Pruebas de rendimiento: los tres primeros tipos de pruebas de los que ya se ha hablado comprueban la eficacia del sistema. Las pruebas de rendimiento se basan en comprobar que el sistema puede soportar el volumen de carga definido en la especificación, es decir, hay que comprobar la eficiencia (P. ej.- Se ha montado una página web sobre un servidor y hay que probar qué capacidad tiene, estado de aceptar peticiones).
    • Pruebas de aceptación: son las únicas pruebas que son realizadas por los usuarios, todas las anteriores las lleva a cabo el equipo de desarrollo. Podemos distinguir entre dos pruebas:
      • Pruebas alfa: las realiza el usuario en presencia de personal de desarrollo del proyecto haciendo uso de una máquina preparada para tal fin.
      • Pruebas beta: las realiza el usuario después de que el equipo de desarrollo les entregue una versión casi definitiva del producto.

El cliente final decide qué pruebas va a aplicarle al producto antes de darlo por bueno y pagarlo. De nuevo, el objetivo del que prueba es encontrar los fallos lo antes posible, en todo caso antes de pagarlo y antes de poner el programa en producción.




1.4 Otros conceptos relacionados con las pruebas de software

  • Completitud: nos da una idea del grado de fiabilidad de las pruebas y por consiguiente la fiabilidad del software. No es posible llegar al 100% puesto que nunca llegaremos a realizar todas las pruebas posibles al software, puesto que las pruebas tienen un coste (P. ej.- Bug del Excel).

  • Depuración: ejecución controlada del software que nos permite corregir un error (P. ej.- Usar el debugger de nuestra máquina). 

TIPOS DE ENTORNOS DE DESARROLLO




No es fácil establecer una clasificación dentro de la variedad de entornos de desarrollo existentes. En algún momento se describieron las siguientes clases de entornos, no excluyentes:




Ejercicio1: Busca los distintos tipos de entornos de desarrollo enumerados anteriormente, defínelos y pon 2 ejemplos de cada uno de ellos.

Ejercicio2: Clasifica entornos de desarrollo en comerciales y libres (los más utilizados), comentando las ventajas e inconvenientes de cada uno de ellos

COMPONENTES DE UN ENTORNO DE DESARROLLO





En las primeras etapas de la informática, la preparación de programas se
realizaba mediante una cadena de operaciones tales como las que se muestra en la figura para un lenguaje procesado mediante compilador. Cada una de las herramientas debía invocarse manualmente por separado. En estas condiciones no puede hablarse propiamente de un entorno de desarrollo

Componentes Entorno Desarrollo
    • El editor es un editor de texto simple
    • El compilador traduce cada fichero de código fuente a código objeto
    • El montador (linker / builder / loader) combina varios ficheros objeto para generar un fichero ejecutable
    • El depurador maneja información en términos de lenguaje de máquina
Un entorno de programación propiamente dicho combina herramientas como
éstas, mejoradas y mejor integradas. Los componentes cuya evolución ha sido más aparente son los que realizan la interacción con el usuario:
    • El editor ya no es un simple editor de texto, sino que tiene una clara orientación al lenguaje de programación usado (reconoce y maneja determinados elementos sintácticos)
    • El depurador no presenta información en términos del lenguaje de máquina, sino del lenguaje fuente
    • El editor está bien integrado con las demás herramientas (se posiciona directamente en los puntos del código fuente en los que hay errores de compilación, o que se están ejecutando con el depurador en un momento dado.

Podemos concluir, enumerando los componentes que incorpora cualquier
entorno de desarrollo:

-          Un editor de texto
-          Un compilador
-          Un intérprete
-          Un depurador
-          Posibilidad de ofrecer un sistema de control de versiones
-          Factibilidad para ayuda en la construcción de interfaces gráficas de usuario

FUNCIONES DE UN ENTORNO DE DESARROLLO




Antes de enumerar las funciones de un entorno de desarrollo, tendremos que
definir en qué consiste un entorno de desarrollo.

            Un entorno de desarrollo o IDE (Integrated Development Environment) es un programa informático que tiene el objetivo de asistir al programador en la difícil tarea de diseñar y codificar un software mediante la inclusión de múltiples herramientas destinadas para dichas tareas.

            Ahora pasamos a enumerar las funciones que podemos utilizar en un entorno de desarrollo:


  •      Las tareas esenciales de la fase de codificación:

o       Edición (creación y modificación del código fuente)
o       Proceso/Ejecución del programa

  •   Interpretación directa (código fuente)
  •   Compilación (código máquina)-montaje-ejecución
  • Compilación (código intermedio)-interpretación

  •        Otras funciones

o       Examinar (hojear) el código fuente
o       Analizar consistencia, calidad, etc.
o       Ejecutar en modo depuración
o       Ejecución automática de pruebas
o       Control de versiones
o       Generar documentación
o       Reformar (refactorizar) código
o       Etc…


LENGUAJES DE PROGRAMACIÓN



1.1           TIPOS DE LENGUAJES DE PROGRAMACIÓN
Los lenguajes de programación se pueden clasificar según varios criterios. Hay que tener en cuenta también, que en la práctica, la mayoría de lenguajes no pueden ser puramente clasificados en una categoría, pues surgen incorporando ideas de otros lenguajes y de otras filosofías de programación, pero no importa al establecer las clasificaciones, pues el auténtico objetivo de las mismas es mostrar los rangos, las posibilidades y tipos de lenguajes que hay.
1. Nivel de abstracción.
Según el nivel de abstracción, es decir, según el grado de cercanía a la máquina:
·         Lenguajes de bajo nivel: La programación se realiza teniendo muy en cuenta las características del procesador. Ejemplo: Lenguajes ensamblador.
·         Lenguajes de nivel medio: Permiten un mayor grado de abstracción pero al mismo tiempo mantienen algunas cualidades de los lenguajes de bajo nivel. Ejemplo: C puede realizar operaciones lógicas y de desplazamiento con bits, tratar todos los tipos de datos como lo que son en realidad a bajo nivel (números), etc.
·         Lenguajes de alto nivel: Más parecidos al lenguaje humano. Manejan conceptos, tipos de datos, etc., de una manera cercana al pensamiento humano ignorando (abstrayéndose) del funcionamiento de la máquina. Ejemplos: Java, Ruby.
Hay quien sólo considera lenguajes de bajo nivel y de alto nivel, (en ese caso, C es considerado de alto nivel).
2. Propósito.
Según el propósito, es decir, el tipo de problemas a tratar con ellos:
·         Lenguajes de propósito general: Aptos para todo tipo de tareas: Ejemplo: C.
·         Lenguajes de propósito específico: Hechos para un objetivo muy concreto. Ejemplo: Csound (para crear ficheros de audio).
·         Lenguajes de programación de sistemas: Diseñados para realizar sistemas operativos o drivers. Ejemplo: C.
·         Lenguajes de script: Para realizar tareas varias de control y auxiliares. Antiguamente eran los llamados lenguajes de procesamiento por lotes (batch) o JCL (“Job Control Languages”). Se subdividen en varias clases (de shell, de GUI, de programación web, etc.). Ejemplos: bash (shell), mIRC script, JavaScript (programación web).
3. Evolución histórica.
Con el paso del tiempo, se va incrementando el nivel de abstracción, pero en la práctica, los de una generación no terminan de sustituir a los de la anterior:
·         Lenguajes de primera generación (1GL): Código máquina.
·         Lenguajes de segunda generación (2GL): Lenguajes ensamblador.
·         Lenguajes de tercera generación (3GL): La mayoría de los lenguajes modernos, diseñados para facilitar la programación a los humanos. Ejemplos: C, Java.
·         Lenguajes de cuarta generación (4GL): Diseñados con un propósito concreto, o sea, para abordar un tipo concreto de problemas. Ejemplos: NATURAL, Mathematica.
·         Lenguajes de quinta generación (5GL): La intención es que el programador establezca el qué problema ha de ser resuelto y las condiciones a reunir, y la máquina lo resuelve. Se usan en inteligencia artificial. Ejemplo: Prolog.
4. Manera de ejecutarse.
Según la manera de ejecutarse:
·         Lenguajes compilados:
·         Lenguajes interpretados:
·         También los hay mixtos,
5. Manera de abordar la tarea a realizar.
Según la manera de abordar la tarea a realizar, pueden ser:
·         Lenguajes imperativos: Indican cómo hay que hacer la tarea, es decir, expresan los pasos a realizar. Ejemplo: C.
·         Lenguajes declarativos: Indican qué hay que hacer. Ejemplos: Lisp, Prolog. Otros ejemplos de lenguajes declarativos, pero que no son lenguajes de programación, son HTML (para describir páginas web) o SQL (para consultar bases de datos).
6. Paradigma de programación.
El paradigma de programación es el estilo de programación empleado. Algunos lenguajes soportan varios paradigmas, y otros sólo uno. Se puede decir que históricamente han ido apareciendo para facilitar la tarea de programar según el tipo de problema a abordar, o para facilitar el mantenimiento del software, o por otra cuestión similar, por lo que todos corresponden a lenguajes de alto nivel (o nivel medio), estando los lenguajes ensambladores “atados” a la arquitectura de su procesador correspondiente. Los principales son:
·         Lenguajes de programación procedural: Divide el problema en partes más pequeñas, que serán realizadas por subprogramas (subrutinas, funciones, procedimientos), que se llaman unas a otras para ser ejecutadas. Ejemplos: C, Pascal.
·         Lenguajes de programación orientada a objetos: Crean un sistema de clases y objetos siguiendo el ejemplo del mundo real, en el que unos objetos realizan acciones y se comunican con otros objetos. Ejemplos: C++, Java.
·         Lenguajes de programación funcional: La tarea se realiza evaluando funciones, (como en Matemáticas), de manera recursiva. Ejemplo: Lisp.
·         Lenguajes de programación lógica: La tarea a realizar se expresa empleando lógica formal matemática. Expresa qué computar. Ejemplo: Prolog.
Hay muchos paradigmas de programación: Programación genérica, programación reflexiva, programación orientada a procesos, etc.
7. Lugar de ejecución.
En sistemas distribuidos, según dónde se ejecute:
·         Lenguajes de servidor: Se ejecutan en el servidor. Ejemplo: PHP es el más utilizado en servidores web.
·         Lenguajes de cliente: Se ejecutan en el cliente. Ejemplo: JavaScript en navegadores web.



 Fuentes: 

ENTORNOS DE DESARROLLO. CFGS CASADO IGLESIAS, CARLOS, 2012

    , 978-84-9964-169-0  RA-MA EDITORIAL



   ENTORNOS DE DESARROLLO (En papel)
   ALICIA RAMOS MARTIN , GARCETA GRUPO EDITORIAL, 2014
  ISBN 9788415452973