¿Las pruebas unitarias habrían ayudado a Citigroup a evitar este costoso error?


86

Leí sobre este problema: el error de programación le cuesta a Citigroup $ 7 millones después de transacciones legítimas confundidas con datos de prueba durante 15 años .

Cuando se introdujo el sistema a mediados de la década de 1990, el código del programa filtró las transacciones que recibieron códigos de sucursal de tres dígitos del 089 al 100 y utilizó esos prefijos para fines de prueba.

Pero en 1998, la compañía comenzó a usar códigos de sucursal alfanuméricos a medida que expandía su negocio. Entre ellos estaban los códigos 10B, 10C, etc., que el sistema trató como dentro del rango excluido, por lo que sus transacciones se eliminaron de cualquier informe enviado a la SEC.

(Creo que esto ilustra que usar un indicador de datos no explícito es ... subóptimo. Hubiera sido mucho mejor poblar y usar una Branch.IsLivepropiedad semánticamente explícita ).

Aparte de eso, mi primera reacción fue "Las pruebas unitarias habrían ayudado aquí" ... pero ¿lo harían?

Recientemente leí ¿Por qué la mayoría de las pruebas unitarias son desperdicio con interés? Entonces , mi pregunta es: ¿cómo serían las pruebas unitarias que habrían fallado en la introducción de códigos de ramificación alfanuméricos?



17
Parece que también se perdieron una prueba de integración que verificó la cantidad de transacciones exportadas a la SEC. Si crea una función de exportación, sería una comprobación razonable.
Luc Franken

31
El autor del artículo no parece entender las pruebas unitarias. Algunas afirmaciones son simplemente ridículas ( "es poco probable que las pruebas unitarias prueben más de una billonésima parte de la funcionalidad de cualquier método" ), otras destruirían la posibilidad de obtener regresiones ( "mire las pruebas que nunca han fallado en un año y considere tirarlos " ). ¿O sugerencias como "convertir las pruebas unitarias en afirmaciones" , que se supone que cambian las pruebas fallidas para excepciones de tiempo de ejecución?
Groo

25
@gnat No leí el enlace externo, y todavía encuentro esta pregunta significativa
Jeutnarg

23
Por lo que vale, estoy bastante en desacuerdo con todo en "Por qué la mayoría de las pruebas unitarias son desperdicios". Escribiría una refutación, pero este margen es demasiado pequeño para contenerlo.
Robert Harvey

Respuestas:


19

¿Realmente está preguntando, "las pruebas unitarias habrían ayudado aquí?", O está preguntando, "¿podría algún tipo de prueba haber ayudado aquí?".

La forma más obvia de prueba que habría ayudado es una afirmación previa en el código mismo, de que un identificador de rama consta solo de dígitos (suponiendo que este es el supuesto en el que se basa el codificador para escribir el código).

Esto podría haber fallado en algún tipo de prueba de integración, y tan pronto como se introducen los nuevos identificadores de ramificación alfanuméricos, la afirmación explota. Pero esa no es una prueba unitaria.

Alternativamente, podría haber una prueba de integración del procedimiento que genera el informe SEC. Esta prueba garantiza que cada identificador de sucursal real informe sus transacciones (y, por lo tanto, requiere una entrada del mundo real, una lista de todos los identificadores de sucursal en uso). Así que tampoco es una prueba unitaria.

No puedo ver ninguna definición o documentación de las interfaces involucradas, pero puede ser que las pruebas unitarias no puedan haber detectado el error porque la unidad no estaba defectuosa . Si se permite que la unidad asuma que los identificadores de sucursal consisten solo en dígitos, y los desarrolladores nunca tomaron una decisión sobre qué debería hacer el código en caso de que no lo hiciera, entonces no deberíanescriba una prueba unitaria para imponer un comportamiento particular en el caso de identificadores que no sean dígitos porque la prueba rechazaría una implementación hipotética válida de la unidad que manejó correctamente los identificadores de rama alfanuméricos, y generalmente no desea escribir una prueba unitaria que impida futuras implementaciones y extensiones. O tal vez un documento escrito hace 40 años implícitamente definido (a través de algún rango lexicográfico en EBCDIC sin procesar, en lugar de una regla de clasificación más amigable para los humanos) que 10B es un identificador de prueba porque de hecho cae entre 089 y 100. Pero entonces Hace 15 años, alguien decidió usarlo como un identificador real, por lo que la "falla" no reside en la unidad que implementa correctamente la definición original: se encuentra en el proceso que no se dio cuenta de que 10B se define como un identificador de prueba y, por lo tanto, no debe asignarse a una rama. Lo mismo sucedería en ASCII si definiera 089-100 como un rango de prueba y luego introdujera un identificador 10 $ o 1.0. Simplemente sucede que en EBCDIC los dígitos vienen después de las letras.

Una prueba unitaria (o posiblemente una prueba funcional) que posiblementepodría haber salvado el día, es una prueba de la unidad que genera o valida nuevos identificadores de rama. Esa prueba afirmaría que los identificadores deben contener solo dígitos y se escribirían para permitir que los usuarios de los identificadores de rama asuman lo mismo. O tal vez hay una unidad en algún lugar que importa identificadores de rama reales pero nunca ve los de prueba, y eso podría probarse de forma unitaria para garantizar que rechaza todos los identificadores de prueba (si los identificadores son solo tres caracteres, podemos enumerarlos todos y comparar el comportamiento de el validador al del filtro de prueba para asegurarse de que coinciden, que se ocupa de la objeción habitual a las pruebas puntuales). Luego, cuando alguien cambió las reglas, la prueba unitaria habría fallado ya que contradice el comportamiento recién requerido.

Dado que la prueba estuvo allí por una buena razón, el punto en el que debe eliminarlo debido a los requisitos comerciales cambiados se convierte en una oportunidad para que alguien reciba el trabajo ", encuentre cada lugar en el código que se base en el comportamiento que queremos cambio". Por supuesto, esto es difícil y, por lo tanto, poco confiable, por lo que de ninguna manera garantizaría salvar el día. Pero si captura sus suposiciones en las pruebas de las unidades de las que está asumiendo propiedades, entonces se ha dado una oportunidad y, por lo tanto, el esfuerzo no se desperdicia por completo .

Por supuesto, estoy de acuerdo en que si la unidad no se hubiera definido en primer lugar con una entrada de "forma divertida", entonces no habría nada que probar. Las divisiones de espacio de nombres complicadas pueden ser difíciles de probar correctamente porque la dificultad no radica en implementar su definición divertida, sino en asegurarse de que todos entiendan y respeten su definición divertida. Esa no es una propiedad local de una unidad de código. Además, cambiar algún tipo de datos de "una cadena de dígitos" a "una cadena de caracteres alfanuméricos" es similar a hacer que un programa basado en ASCII maneje Unicode: no será simple si su código está fuertemente acoplado a la definición original, y cuando el tipo de datos es fundamental para lo que hace el programa, entonces a menudo está fuertemente acoplado.

es un poco inquietante pensar que es un esfuerzo en gran medida desperdiciado

Si las pruebas unitarias a veces fallan (mientras está refactorizando, por ejemplo), y al hacerlo le brindan información útil (su cambio es incorrecto, por ejemplo), entonces el esfuerzo no se desperdició. Lo que no hacen es probar si su sistema funciona. Entonces, si está escribiendo pruebas unitarias en lugar de tener pruebas funcionales y de integración, entonces puede estar usando su tiempo de manera subóptima.


¡Las afirmaciones son buenas!

3
@nocomprende: como Reagan lo tenía, "confía, pero verifica".
Steve Jessop

1
Yo también iba a decir "¡Las pruebas de unidad son malas!" pero pensé que la mayoría de la gente se perdería la referencia a Animal Farm y comenzaría a criticarme en lugar de pensar en lo que estaba diciendo (las respuestas instintivas no son efectivas) pero no dije eso. Tal vez una persona que es más inteligente y tiene mayor erudición puede hacer ese punto.

2
"Todas las pruebas están pasando, ¡pero algunas pruebas pasan MÁS que otras!"
Graham

1
la prueba es un arenque rojo. Estos tipos simplemente no sabían cómo se definía el "código de sucursal". Esto sería como si la Oficina de Correos de los EE. UU. No supiera que estaba cambiando la definición del código postal cuando agregó 4 dígitos.
radarbob

120

Las pruebas unitarias podrían haber detectado que los códigos de rama 10B y 10C se clasificaron incorrectamente como "ramas de prueba", pero encuentro improbable que las pruebas para esa clasificación de rama hayan sido lo suficientemente extensas como para detectar ese error.

Por otro lado, las comprobaciones puntuales de los informes generados podrían haber revelado que 10B y 10C ramificados no aparecían en los informes mucho antes de los 15 años en que ahora se permitía que el error permaneciera presente.

Finalmente, esta es una buena ilustración de por qué es una mala idea mezclar datos de prueba con los datos de producción reales en una base de datos. Si hubieran utilizado una base de datos separada que contiene los datos de las pruebas, no habría sido necesario filtrar eso de los informes oficiales y habría sido imposible filtrar demasiado.


80
+1 Las pruebas unitarias nunca pueden compensar las malas decisiones de diseño (como la prueba de mezcla y los datos reales)
Jeutnarg

55
Si bien es mejor evitar mezclar datos de prueba con datos reales, puede ser difícil validar un sistema de producción si eso requiere modificar datos reales. Por ejemplo, es una mala idea validar un sistema bancario modificando los totales de cuentas bancarias en producción. Usar rangos de código para designar significado es problemático. Un atributo más explícito de los registros probablemente habría sido una mejor opción.
JimmyJames

44
@Voo Creo que hay una suposición tácita de que existe un nivel de complejidad o un requisito de confiabilidad donde probar el sistema de producción real implementado se considera útil o necesario. (Considere cuánto podría salir mal debido a una variable de configuración incorrecta). Podría ver que este es el caso de una gran institución financiera.
jpmc26

44
@Voo No estoy hablando de pruebas. Estoy hablando de la validación del sistema. En un sistema de producción real, hay muchas formas en que puede fallar que no tienen nada que ver con el código. Si está poniendo en producción un nuevo sistema bancario, es posible que tenga algún problema en la base de datos o en la red, etc., que impida que las transacciones se apliquen a las cuentas. Nunca he trabajado en un banco, pero estoy bastante seguro de que está mal visto comenzar a modificar cuentas reales con transacciones falsas. Eso te deja con la creación de cuentas falsas o espera y reza.
JimmyJames

12
@JimmyJames En el sector sanitario, es común copiar periódicamente la base de datos de producción en el entorno de prueba para realizar pruebas en datos que sean lo más reales posible; Creo que un banco puede hacer lo mismo.
dj18

75

El software tuvo que manejar ciertas reglas comerciales. Si hubiera pruebas unitarias, las pruebas unitarias habrían comprobado que el software manejó las reglas comerciales correctamente.

Las reglas del negocio cambiaron.

Aparentemente, nadie se dio cuenta de que las reglas comerciales habían cambiado, y nadie cambió el software para aplicar las nuevas reglas comerciales. Si hubiera habido pruebas unitarias, esas pruebas unitarias tendrían que cambiarse, pero nadie lo habría hecho porque nadie se dio cuenta de que las reglas comerciales habían cambiado.

Entonces no, las pruebas unitarias no habrían captado eso.

La excepción sería si las pruebas unitarias y el software hubieran sido creados por equipos independientes, y el equipo que realiza las pruebas unitarias cambiara las pruebas para aplicar las nuevas reglas comerciales. Entonces las pruebas unitarias habrían fallado, lo que con suerte habría resultado en un cambio del software.

Por supuesto, en el mismo caso si solo se cambiara el software y no las pruebas unitarias, entonces las pruebas unitarias también fallarían. Cuando una prueba unitaria falla, no significa que el software esté mal, significa que el software o la prueba unitaria (a veces ambos) están mal.


2
¿Es factible tener diferentes equipos donde uno está trabajando en código y otro en pruebas de "unidad"? ¿Cómo es eso posible? ... Estoy refactorizando mi código todo el tiempo.
Sergio

2
@Sergio desde una perspectiva, la refactorización cambia los elementos internos al tiempo que preserva el comportamiento, por lo que si la prueba se escribe de una manera que pruebe el comportamiento sin depender de elementos internos, entonces no necesita actualización.
Daenyth

1
He visto que esto suceda varias veces. El software está en producción sin quejas, luego, de repente, los usuarios explotan con las quejas de que ya no funciona y ha estado fallando gradualmente a lo largo de los años. Eso es lo que sucede cuando decides ir y cambiar tus procedimientos internos sin seguir el proceso de notificación estándar ...
Brian Knoblauch

42
"Las reglas de negocios cambiaron" es la observación crítica. Las pruebas unitarias validan que implementó la lógica que pensó que implementó , no que su lógica fuera correcta .
Ryan Cavanaugh

55
Si estoy en lo cierto sobre lo que sucedió, es poco probable que se escriban pruebas unitarias para detectar esto. El principio básico para seleccionar pruebas es probar algunos casos "buenos", algunos casos "malos" y casos que delimitan cualquier límite. En este caso, probaría "099", "100" y "101". Dado que "10B" estaba cubierto por las pruebas de "rechazo sin números" en el sistema anterior, y es mayor que 101 (y así lo cubre al probar eso) en el nuevo sistema, no hay razón para probarlo, excepto que en EBCDIC, "10B" clasifica entre "099" y "100".
Mark

29

No. Este es uno de los grandes problemas con las pruebas unitarias: te inducen a una falsa sensación de seguridad.

Si pasan todas sus pruebas, no significa que su sistema esté funcionando correctamente; significa que todas tus pruebas están pasando . Significa que las partes de tu diseño en las que pensaste y escribiste pruebas conscientemente funcionan como creías conscientemente que lo harían, lo que en realidad no es un gran problema: eso fue lo que realmente estabas prestando mucha atención a, así que es muy probable que lo hayas hecho bien de todos modos! Pero no hace nada para detectar casos en los que nunca pensó, como este, porque nunca pensó en escribir una prueba para ellos. (Y si lo hubiera hecho, habría sabido que eso significaba que los cambios de código eran necesarios, y los habría cambiado).


17
Mi padre solía preguntarme eso: ¿Por qué no pensaste en lo que no pensaste? (Solo él solía hacerlo confuso diciendo "¡Si no lo sabes, pregunta !") Pero, ¿cómo sé que no lo sé?

77
"Significa que las partes de tu diseño en las que pensaste y escribiste pruebas conscientemente funcionan como creías que lo harían". Exactamente correcto. Esta información es invaluable si está refactorizando, o si algo cambia en otro lugar del sistema que rompe sus suposiciones. Los desarrolladores que tienen una falsa sensación de seguridad simplemente no entienden las limitaciones de las pruebas unitarias, pero eso no hace que las pruebas unitarias sean una herramienta inútil.
Robert Harvey

12
@MasonWheeler: Al igual que usted, el autor cree que las pruebas unitarias de alguna manera deben demostrar que su programa funciona. No lo hace. Permítanme repetir eso: las pruebas unitarias no prueban que su programa funcione. Las pruebas unitarias demuestran que sus métodos cumplen con su contrato de prueba, y eso es todo lo que hace. El resto del documento se cae, porque se basa en esa única premisa inválida.
Robert Harvey

55
Naturalmente, los desarrolladores que tienen esa falsa creencia se sentirán decepcionados cuando la prueba unitaria les falle completamente, pero eso es culpa del desarrollador, no de la prueba unitaria, y no invalida el valor genuino que proporciona la prueba unitaria.
Robert Harvey

55
o_O @ tu primera oración. Las pruebas unitarias le dan una falsa sensación de seguridad mientras codifica, como tener las manos en el volante le da una falsa sensación de seguridad mientras conduce.
djechlin

10

No, no necesariamente

El requisito original era usar códigos de ramificación numéricos, por lo que se habría producido una prueba unitaria para un componente que aceptara varios códigos y rechazara cualquiera como 10B. El sistema habría pasado como funcionando (que era).

Entonces, el requisito habría cambiado y los códigos actualizados, pero esto habría significado que el código de prueba de la unidad que proporcionó los datos incorrectos (que ahora son buenos datos) tendría que modificarse.

Ahora suponemos que las personas que administran el sistema sabrían que este es el caso y cambiarían la prueba de la unidad para manejar los nuevos códigos ... pero si supieran que está ocurriendo, también habrían sabido cambiar el código que manejó estos códigos de todos modos ... y no hicieron eso. Una prueba unitaria que originalmente rechazó el código 10B hubiera dicho felizmente "todo está bien aquí" cuando se ejecuta, si no supiera actualizar esa prueba.

Las pruebas unitarias son buenas para el desarrollo original pero no para las pruebas del sistema, especialmente no 15 años después de que los requisitos se hayan olvidado por mucho tiempo.

Lo que necesitan en este tipo de situación es una prueba de integración de extremo a extremo. Uno donde puede pasar los datos que espera que funcionen y ver si lo hace. Alguien habría notado que sus nuevos datos de entrada no producían un informe y luego investigarían más a fondo.


Correcto. Y el problema principal (¿solo?) Con las pruebas unitarias. Me salvó la redacción de mi propia respuesta, ya que habría dicho exactamente lo mismo (¡pero probablemente peor!) :)
Lightness Races in Orbit

8

Las pruebas de tipo (el proceso de probar invariantes utilizando datos válidos generados aleatoriamente, como lo ejemplifica la biblioteca de pruebas de Haskell QuickCheck y varios puertos / alternativas inspirados en otros idiomas) pueden haber detectado este problema, las pruebas unitarias casi seguramente no habrían hecho .

Esto se debe a que cuando se actualizaron las reglas para la validez de los códigos de sucursal, es poco probable que alguien hubiera pensado probar esos rangos específicos para asegurarse de que funcionaran correctamente.

Sin embargo, si la prueba de tipo hubiera estado en uso, alguien debería, en el momento en que se implementó el sistema original, haber escrito un par de propiedades, una para verificar que los códigos específicos para las ramas de prueba fueron tratados como datos de prueba y otro para verificar que no haya otros códigos fueron ... cuando se actualizó la definición del tipo de datos para el código de bifurcación (que habría sido necesario para permitir probar que alguno de los cambios para el código de bifurcación de dígito a numérico funcionó), esta prueba habría comenzado a probar valores en el nuevo rango y muy probablemente habría identificado la falla.

Por supuesto, QuickCheck se desarrolló por primera vez en 1999, por lo que ya era demasiado tarde para detectar este problema.


1
Creo que es más normal llamar a esta prueba basada en propiedades y, por supuesto, es tan posible escribir una prueba basada en propiedades que aún pasaría dado este cambio (aunque creo que es más probable que escriba una prueba que pueda encontrarla)
jk.

5

Realmente dudo que las pruebas unitarias hagan una diferencia en este problema. Parece una de esas situaciones de visión de túnel porque la funcionalidad se cambió para admitir nuevos códigos de sucursal, pero esto no se llevó a cabo en todas las áreas del sistema.

Utilizamos pruebas unitarias para diseñar una clase. Volver a ejecutar una prueba unitaria solo es necesario si el diseño ha cambiado. Si una unidad en particular no cambia, las pruebas de unidad sin cambios arrojarán los mismos resultados que antes. Las pruebas unitarias no le mostrarán los impactos de los cambios en otras unidades (si lo hacen, no está escribiendo pruebas unitarias).

Solo puede detectar razonablemente este problema a través de:

  • Pruebas de integración, pero tendría que agregar específicamente los nuevos formatos de código para alimentar a través de múltiples unidades en el sistema (es decir, solo le mostrarían el problema si las pruebas originales incluían las ramas ahora válidas)
  • Pruebas de extremo a extremo: la empresa debe ejecutar una prueba de extremo a extremo que incorpore formatos de código de sucursal antiguos y nuevos

No tener suficientes pruebas de extremo a extremo es más preocupante. No puede confiar en las pruebas unitarias como su ÚNICA o la prueba PRINCIPAL para los cambios del sistema. Parece que solo requiere que alguien ejecute un informe sobre los formatos de código de sucursal recientemente admitidos.


2

Una afirmación integrada en el tiempo de ejecución podría haber ayudado; por ejemplo:

  1. Crea una función como bool isTestOnly(string branchCode) { ... }
  2. Use esta función para decidir qué informes filtrar
  3. Reutilice esa función en una aserción, en el código de creación de rama, para verificar o afirmar que una rama no es (no puede ser) creada usando este tipo de código de rama‼
  4. Tenga esta afirmación habilitada en el tiempo de ejecución real (y no "optimizada, excepto en la versión de desarrollador del código de solo depuración")‼

Ver también:


2

La conclusión de esto es Fail Fast .

No tenemos el código, ni tenemos muchos ejemplos de prefijos que son o no prefijos de ramificación de prueba de acuerdo con el código. Todo lo que tenemos es esto:

  • 089-100 => rama de prueba
  • 10B, 10C => rama de prueba
  • <088 => presumiblemente ramas reales
  • > 100 => presumiblemente ramas reales

El hecho de que el código permita números y cadenas es más que un poco extraño. Por supuesto, 10B y 10C pueden considerarse números hexadecimales, pero si todos los prefijos se tratan como números hexadecimales, 10B y 10C quedan fuera del rango de prueba y se tratarán como ramas reales.

Esto probablemente significa que el prefijo se almacena como una cadena pero en algunos casos se trata como un número. Aquí está el código más simple que se me ocurre que replica este comportamiento (usando C # con fines ilustrativos):

bool IsTest(string strPrefix) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix))
        return iPrefix >= 89 && iPrefix <= 100;
    return true; //here is the problem
}

En inglés, si la cadena es un número y está entre 89 y 100, es una prueba. Si no es un número, es una prueba. De lo contrario, no es una prueba.

Si el código sigue este patrón, ninguna prueba unitaria lo habría detectado en el momento en que se implementó el código. Aquí hay algunos ejemplos de pruebas unitarias:

assert.isFalse(IsTest("088"))
assert.isTrue(IsTest("089"))
assert.isTrue(IsTest("095"))
assert.isTrue(IsTest("100"))
assert.isFalse(IsTest("101"))
assert.isTrue(IsTest("10B")) // <--- business rule change

La prueba unitaria muestra que "10B" debe tratarse como una rama de prueba. El usuario @ gnasher729 anterior dice que las reglas comerciales cambiaron y eso es lo que muestra la última afirmación anterior. En algún momento esa afirmación debería haber cambiado a an isFalse, pero eso no sucedió. Las pruebas unitarias se ejecutan en tiempo de desarrollo y construcción, pero luego en ningún momento posterior.


¿Cuál es la lección aquí? El código necesita alguna forma de indicar que recibió una entrada inesperada. Aquí hay una forma alternativa de escribir este código que enfatiza que espera que el prefijo sea un número:

// Alternative A
bool TryGetIsTest(string strPrefix, out bool isTest) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix)) {
        isTest = iPrefix >= 89 && iPrefix <= 100;
        return true;
    }
    isTest = true; //this is just some value that won't be read
    return false;
}

Para aquellos que no conocen C #, el valor de retorno indica si el código pudo analizar o no un prefijo de la cadena dada. Si el valor de retorno es verdadero, el código de llamada puede usar la variable isTest out para verificar si el prefijo de rama es un prefijo de prueba. Si el valor de retorno es falso, el código de llamada debe informar que no se espera el prefijo dado y que la variable isTest out no tiene sentido y debe ignorarse.

Si está bien con excepciones, puede hacer esto en su lugar:

// Alternative B
bool IsTest(string strPrefix) {
    int iPrefix = int.Parse(strPrefix);
    return iPrefix >= 89 && iPrefix <= 100;
}

Esta alternativa es más sencilla. En este caso, el código de llamada debe detectar la excepción. En cualquier caso, el código debería tener alguna forma de informar al llamante que no esperaba un strPrefix que no se pudiera convertir a un entero. De esta manera, el código falla rápidamente y el banco puede encontrar rápidamente el problema sin la multa vergonzosa de la SEC.


1

Tantas respuestas y ni siquiera una cita de Dijkstra:

Las pruebas muestran la presencia, no la ausencia de errores.

Por lo tanto, depende. Si el código se probó correctamente, lo más probable es que este error no exista.


-1

Creo que una prueba unitaria aquí habría asegurado que el problema nunca existiera en primer lugar.

Considera, has escrito la bool IsTestData(string branchCode)función.

La primera prueba unitaria que escriba debe ser para una cadena nula y vacía. Luego, para cadenas de longitud incorrectas y luego para cadenas no enteras.

Para que todas esas pruebas pasen, deberá agregar la comprobación de parámetros a la función.

Incluso si solo prueba datos `` buenos '' 001 -> 999 sin pensar en la posibilidad de 10A, la verificación de parámetros lo obligará a reescribir la función cuando comience a usar alfanuméricos para evitar las excepciones que arrojará


1
Esto no habría ayudado: la función no se modificó y la prueba no comenzaría a fallar dados los mismos datos de prueba. Alguien habría tenido que pensar en cambiar la prueba para que fallara, pero si hubieran pensado en eso, probablemente también habrían pensado en cambiar la función.
Hulk

(O tal vez me estoy perdiendo algo, ya que no estoy seguro de lo que quieres decir con "comprobación de parámetros")
Hulk

La función se vería obligada a lanzar una excepción para que las cadenas no enteras pasen la prueba de unidad de caso de borde simple. Por lo tanto, el código de producción sería un error si comenzara a utilizar códigos de rama alfanuméricos sin programarlos específicamente
Ewan

Pero, ¿no habría utilizado la función alguna IsValidBranchCodefunción para realizar esta verificación? ¿Y esta función probablemente habría cambiado sin necesidad de modificar el IsTestData? Entonces, si solo está probando 'buenos datos', la prueba no habría ayudado. La prueba de caso límite habría tenido que incluir un código de sucursal ahora válido (y no simplemente algunos aún inválidos) para comenzar a fallar.
Hulk

1
Si la verificación está en IsValidCode, de modo que la función se aprueba sin su propia verificación explícita, entonces sí es posible omitirla, pero entonces tendríamos un conjunto adicional de aún más pruebas, validadores simulados, etc., incluso más posibilidades de "estas son números de prueba "
Ewan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.