65.000.000.000 pruebas para ejecutar

50

Me preguntaron cómo ejecutar un conjunto de 65.000.000.000 de pruebas y me pregunto si es normal tener un proyecto con una cantidad tan grande de pruebas.

¿Has trabajado en proyectos con esta característica?

juanpavergara
fuente
32
65 mil millones (10e9) pruebas? ¿Es este un problema práctico o una pregunta de entrevista?
40
Me interesaría saber quién escribió 65 mil millones de pruebas y cuántos años les llevó.
Plataforma
46
Con 65 mil millones de pruebas, si puede ejecutar 1000 pruebas / segundo, tardará aproximadamente 2 años en ejecutarse. 10,000 pruebas / segundo es un poco más de dos meses. 100,000 pruebas / segundo tomarán aproximadamente una semana. Esto describe un poder de procesamiento serio para ejecutar las pruebas en un plazo razonable.
20
No quiero ser el tipo que escribe la matriz de trazabilidad ...
mouviciel
23
@DanPichelman - Claramente, necesitas escribir otros 500 millones de pruebas para comprobar que el generador de pruebas genera las pruebas correctamente.
Bobson

Respuestas:

103

Con 65 mil millones de pruebas, parece que le piden que pruebe todas las entradas posibles. Esto no es útil: esencialmente estaría probando que su procesador funciona correctamente, no que su código sea correcto.

Deberías probar las clases de equivalencia en su lugar. Esto reducirá drásticamente su rango de entradas de prueba.

También considere si puede subdividir su sistema en partes más pequeñas. Cada pieza será más fácil de probar de forma aislada, y luego puede realizar algunas pruebas de integración que reúnen todas las piezas.

Si aún desea tener la seguridad de que algunas de esas combinaciones de entrada funcionan, tal vez podría intentar la prueba de fuzz . Obtendrá algunos de los beneficios de probar muchas entradas diferentes, pero sin ejecutar los 65 mil millones de ellas.

M. Dudley
fuente
12
+1, especialmente para "esencialmente estarías probando que tu procesador funciona correctamente"
Doc Brown
44
Para funciones bastante simple (bit de tocar el violín, etc.) que no tiendo a probar todos los valores posibles. Es infalible y, por lo tanto, me da mucha más confianza que las clases de equivalencia de prueba (derivadas y, por lo tanto, potencialmente erróneas). Por supuesto, eso ya no funciona cuando sus posibles aportes llegan a miles de millones.
Konrad Rudolph
39

Si este es un conjunto de pruebas real, entonces no querrás llegar a trabajar en él.

El trabajo completo de un probador es lograr un equilibrio entre las pruebas lo suficientemente exhaustivas como para estar seguro de que tiene los resultados "correctos" y escribir pocas pruebas suficientes para que puedan ejecutarse en un período de tiempo razonable.

Muchas pruebas pueden resumirse en "clases de equivalencia", lo que significa que, en lugar de ejecutar 3 mil millones de pruebas, ejecuta 1 que le da un nivel razonable de confianza de que todas las demás pruebas en esa clase de equivalencia se ejecutarían con éxito, si decidiera desperdiciar el el tiempo los corre.

Debe decirle a quien esté pensando en ejecutar 65 mil millones de pruebas que necesitan hacer un mejor trabajo abstrayendo las pruebas en clases de equivalencia.

dsw88
fuente
+1 en pruebas exhaustivas pero eficientes.
Marco
23

Lo más probable es que haya llegado a su cifra de 65 mil millones de pruebas calculando todas las combinaciones posibles de entradas en el sistema bajo prueba, o calculando la complejidad ciclomática y suponiendo que se debe escribir una prueba para cada una de estas rutas de ejecución únicas.

No es así como se escriben las pruebas reales, porque como lo han indicado otros afiches y comentaristas, el poder técnico requerido para ejecutar 65 mil milloneslas pruebas son asombrosas. Esto sería como escribir una prueba que ejercita un método para agregar dos enteros conectando cada permutación posible de dos valores de 32 bits y verificando el resultado. Es una locura absoluta. Debe trazar la línea e identificar un subconjunto de todos los casos de prueba posibles, que entre ellos garantizarían que el sistema se comportará como se espera en todo el rango de entradas. Por ejemplo. prueba agregar algunos números "normales", prueba algunos escenarios de números negativos, prueba límites técnicos como escenarios de desbordamiento y prueba cualquier escenario que pueda dar lugar a un error. Como se mencionó, estos diversos tipos de pruebas ejercen "clases de equivalencia"; le permiten tomar una muestra representativa de las posibles entradas, junto con cualquier "valor atípico" conocido,

Considere uno de los katas de código básico, el generador de números romanos. La tarea, que se realizará utilizando técnicas TDD en un estilo de "dojo", es escribir una función que pueda aceptar cualquier número del 1 al 3000 y producir el número romano correcto para ese valor numérico.

No resuelve este problema escribiendo 3000 pruebas unitarias, una a la vez, y pasándolas sucesivamente. Eso es locura; el ejercicio normalmente toma entre una y dos horas, y estarías allí durante días probando cada valor individual. En cambio, te vuelves inteligente. Comienza con el caso base más simple (1 == "I"), implementa eso usando una estrategia de "código mínimo" ( return "I";), y luego busca cómo el código que tienes se comportará incorrectamente en otro escenario esperado (2 == " II "). Enjuague y repita; Lo más probable es que haya reemplazado su implementación inicial con algo que repita el carácter "I" tantas veces como sea necesario (como return new String('I',number);). Obviamente, pasará una prueba para III, por lo que no se molestará; en su lugar, escribe la prueba para 4 == "IV", que sabe que la implementación actual ganó '

O, en un estilo más analítico, examina cada decisión condicional que toma el código (o debe ser) y escribe una prueba diseñada para ingresar el código para cada posible resultado de cada decisión. Si tiene 5 declaraciones if (cada una con una rama verdadera y falsa), cada una de ellas completamente independiente de la otra, codifica 10 pruebas, no 32. Cada prueba estará diseñada para afirmar dos cosas sobre una posible decisión particular; primero que se toma la decisión correcta, y luego que el código ingresado dada esa condición es correcto. Usted no codificar una prueba para cada posible permutación de decisiones independientes. Si las decisiones son dependientes, entonces debe probar más de ellas en combinación, pero hay menos combinaciones de este tipo porque algunas decisiones solo se toman cuando otra decisión tuvo un resultado particular.

KeithS
fuente
5

¿Es esto "normal" ?, no. Donde "normal" se define como la experiencia promedio o típica. No puedo decir que alguna vez haya tenido que trabajar en un proyecto como ese, pero he estado en un proyecto en el que uno de cada pocos millones de bits se voltea. Probar eso fue ... un desafío.

¿Es potencialmente necesario? Bueno, eso depende de las garantías y detalles del proyecto. Es un poco incrédulo de comprender al principio, pero su pregunta es ligera en detalles.

Como otros (MichaelT) han señalado, el tiempo para completar esta tarea con pruebas en serie hace que esto sea poco práctico. Entonces la paralelización se convierte en su primera consideración. ¿Cuántos sistemas de prueba puede arrojar a este problema y qué soporte tiene para recopilar los resultados de esos múltiples sistemas?

¿Qué garantías tiene de que el dispositivo o algoritmo que está probando se está replicando de manera confiable? El software es bastante confiable en la replicación, pero los dispositivos de hardware (especialmente la primera generación) pueden tener problemas de fabricación. Una falla de prueba falsa en ese caso podría indicar un algoritmo incorrecto o que el dispositivo no se ensambló correctamente. ¿Necesita distinguir entre esos dos casos?

También deberá considerar cómo va a validar los propios sistemas de prueba. Presumiendo una razón legítima para tantos casos de prueba, necesitará mucha automatización. Es necesario inspeccionar esa automatización para asegurarse de que no se equivoque al generar sus casos de prueba. Las comprobaciones puntuales de errores realmente serían el equivalente a encontrar una aguja en el pajar.

Este enlace arstechnica puede o no arrojar algo de información sobre sus consideraciones de prueba. Los clústeres de GPU se usan comúnmente para contraseñas de descifrado de fuerza bruta. El que se cita en el artículo puede can cycle through as many as 350 billion guesses per second, por lo que eso pone sus pruebas 65B en perspectiva. Es probable que sea un dominio diferente, pero muestra cómo abordar la tarea desde diferentes ángulos puede proporcionar una solución viable.


fuente
3

No creo que sea factible mantener 6.5e + 10 pruebas en primer lugar, por lo que ejecutarlos puede ser discutible. Incluso los proyectos más grandes, como Debian con todos sus paquetes, tienen solo varios cientos de millones de SLOC en total.

Pero si tiene que ejecutar una gran cantidad de pruebas de todos modos, hay algunas estrategias.

  • No los ejecutes a todos. Lo más probable es que no todas las pruebas dependan de cada ruta de código. Defina dependencias entre subsistemas y sus pruebas, y entre conjuntos de pruebas, y solo podrá ejecutar pruebas unitarias relevantes para un cambio en particular, solo las pruebas de integración que dependen de estas pruebas unitarias, etc.

  • Ejecútelos en paralelo. Con una base de código tan grande, es probable que tenga una granja de compilación masiva (en JetBrains, una operación relativamente pequeña, solíamos tener 40-50 agentes de compilación ejecutándose solo en la granja de integración / compilación continua IDEA). Como las pruebas unitarias son independientes y las pruebas de integración pueden reutilizar el código ya construido, las pruebas son relativamente fáciles de paralelizar.

  • Deja de correr temprano. Si sabe que un conjunto de pruebas en particular depende de su funcionamiento razonable de la corrección de otro conjunto de pruebas, puede cortar toda la cadena una vez que vea que falla un enlace.

Descargo de responsabilidad: no soy un ingeniero de pruebas profesional. Tome lo anterior con un grano de sal.

9000
fuente
55
... Por supuesto, en JetBrains, esos agentes de compilación son gratuitos porque desarrollan TeamCity y lo poseen directamente. Otras "operaciones relativamente pequeñas" probablemente tendrían un ataque al corazón con la idea de un costo inicial de aproximadamente $ 15,000 (solo para el software; agregue 40-50 unidades de montaje en cuchillas y otro hardware, e incluso usando una distribución gratuita de Linux para alojarlo todo ' se trata fácilmente del salario anual de un desarrollador sénior) y de las tarifas anuales de mantenimiento de $ 6500, más el tiempo y la habilidad del personal de TI necesarios para mantener la granja en funcionamiento.
KeithS
0

Aunque ha habido varias buenas sugerencias aquí sobre cómo tratar de escabullirse con menos pruebas, dudo seriamente que su sistema tenga solo 65 mil millones de combinaciones de entrada. Eso es menos de 36 bits de entrada. Supongamos que ya ha tomado todos los consejos anteriores.

Si cada prueba tarda aproximadamente un milisegundo en ejecutarse y distribuye las pruebas en solo 10 procesadores (una PC normal), la prueba se ejecutará en poco más de 69 días. Eso es un tiempo, pero no completamente irrazonable. Distribuya entre 100 procesadores (una docena de PC normales o una PC de servidor razonable) y las pruebas se completarán en menos de 7 días. Puede ejecutarlos todas las semanas para verificar regresiones.

Paul Scherf
fuente