¿Debería haber pruebas unitarias para expresiones regulares complejas?

34

¿Debo escribir pruebas unitarias para expresiones regulares complejas en mi aplicación?

  • Por un lado: son fáciles de probar porque el formato de entrada y salida a menudo es simple y bien definido, y a menudo pueden volverse tan complejos que las pruebas de ellos específicamente son valiosas.
  • Por otro lado: ellos mismos rara vez forman parte de la interfaz de alguna unidad. Sería mejor probar solo la interfaz y hacerlo de una manera que implícitamente pruebe las expresiones regulares.

EDITAR:

Estoy de acuerdo con Doc Brown, quien en su comentario señala que este es un caso especial de pruebas unitarias de componentes internos .

Pero como los componentes internos regexes tienen algunas características especiales:

  1. Una expresión regular de una sola línea puede ser realmente compleja sin ser realmente un módulo separado.
  2. Las expresiones regulares asignan la entrada a la salida sin ningún efecto secundario y, por lo tanto, son realmente fáciles de probar por separado.
Lii
fuente
12
"ellos mismos rara vez forman parte de la interfaz de alguna unidad". - si sus clases tienen un código interesante enterrado en lo profundo de la interfaz, divida sus clases. Este es un ejemplo de cómo pensar en tess puede mejorar el diseño.
Nathan Cooper
3
La misma pregunta de una manera más general: ¿qué componentes internos deben ser probados en unidades? Ver programmers.stackexchange.com/questions/16732/…
Doc Brown
Sorta relacionado, ver Regex101. Tienen una sección para escribir pruebas unitarias para su expresión regular. Por ejemplo: regex101.com/r/tR3mJ2/2
David dice Reinstate Monica
3
Descargo de responsabilidad: este comentario es mi humilde opinión: 1 en primer lugar, creo que las expresiones regulares complejas son pura maldad - también vea blog.codinghorror.com/… 2 el valor real de probar tales expresiones viene cuando las prueba en una gran base de datos de data blog.codinghorror.com/testing-with-the-force 3 Tengo la extraña sensación de que estas pruebas no son pruebas unitarias exactamente
Boris Treukhov

Respuestas:

101

Dejando a un lado el dogmatismo, la verdadera pregunta es si proporciona valor para la prueba unitaria de expresiones regulares complejas. Parece bastante claro que proporciona valor (independientemente de si la expresión regular es parte de una interfaz pública) si la expresión regular es lo suficientemente compleja, ya que le permite encontrar y reproducir errores y evitar regresiones.

JacquesB
fuente
25
1, aunque si una expresión regular es bastante compleja que esto es un problema, entonces es probable que tenga sentido para moverlo en una unidad de "contenedor" con los métodos adecuados ( isValid, parse, tryParse, o lo que sea, dependiendo exactamente cómo se está utilizando), por lo que el código del cliente no tiene que saber que está implementado actualmente usando una expresión regular. La unidad de envoltura tendría pruebas detalladas que, una vez más, no necesitarían conocer la implementación actual. Estas pruebas, por supuesto, son pruebas de facto de la expresión regular, pero de una manera independiente de la implementación.
ruakh
1
Un reg ex es un programa, aunque en un lenguaje especializado y muy conciso. Como tal, la prueba es apropiada para expresiones no triviales ... Y ciertamente el código que invoca la expresión debe ser probado, lo que puede probar implícitamente lo reservado.
keshlam
66
@ruakh Bien dicho. El beneficio de una clase de contenedor para una expresión regular es que puede reemplazarla con un código normal si es necesario. El código con entrada / salida compleja siempre debe tener pruebas unitarias, porque es notablemente difícil de depurar sin él. Si necesita consultar la documentación para comprender los efectos del código, debe tener pruebas unitarias. Si es solo un mapeo rápido 1: 1 como conversión de tipo, entonces no hay problema. Las expresiones regulares superan ese punto de requerir documentos muy rápidamente.
Aaron3468
44
@Lii: Regexes no merece ningún tratamiento especial. La expresión regular es la unidad en este caso, por lo que la prueba unitaria.
JacquesB
1
@ruakh Estaba a punto de escribir una respuesta a ese efecto. Estoy de acuerdo en que usar regex es un detalle de implementación. Lo que importa es que las cosas se validen cuando se supone que deben hacerlo, y no se validan cuando se supone que deben hacerlo. Pruebe FooValidatorsus entradas y salidas, luego no le preocupa cómo se está haciendo. ++
RubberDuck
21

Regex puede ser una herramienta poderosa, pero no es una herramienta en la que pueda confiar para que funcione si realiza cambios menores en expresiones regulares complejas.

Por lo tanto, cree muchas pruebas que documenten los casos que debe cubrir. Y cree muchas pruebas que documenten casos en los que debería fallar, si se usa para la validación.

Cada vez que necesite cambiar sus expresiones regulares, agregue los nuevos casos como pruebas, modifique sus expresiones regulares y espere lo mejor.

Si estuviera en una organización que en general no usara pruebas unitarias, aún escribiría un programa de prueba que probaría cualquier expresión regular que usaríamos. Incluso lo haría en mi propio tiempo si tuviera que hacerlo, mi cabello no necesita perder más color.

Doblado
fuente
3

Las expresiones regulares son código junto con el resto de su aplicación. Debe probar que el código en general hace lo que espera que haga. Esto tiene varios propósitos:

  • Las pruebas son documentación ejecutable. Demuestra claramente lo que necesita que haga el código. Si se prueba es importante.
  • Los futuros mantenedores pueden estar seguros de que si lo modifican, las pruebas garantizarán que el comportamiento no cambie.

Como hay un obstáculo adicional que superar al tener el código en un idioma diferente incrustado con el resto, lo más probable es que debas prestar esta atención adicional en beneficio del mantenimiento.

Thorbjørn Ravn Andersen
fuente
1

En resumen, debe probar su aplicación, punto. Ya sea que pruebe su expresión regular con pruebas automáticas que lo ejecutan de forma aislada, como parte de una caja negra más grande o si simplemente juega con ella a mano, es secundario para asegurarse de que funcione.

La principal ventaja de las pruebas unitarias es que ahorran tiempo. Te permiten probar la cosa tantas veces como quieras ahora o en cualquier momento en el futuro. Si hay alguna razón para creer que su expresión regular se refactorizará, ajustará, obtendrá más restricciones, etc., entonces sí, es probable que desee algunas pruebas de regresión, o cuando lo cambie, tendrá que ir a través de una hora de pensar en todos los casos límite para que no lo rompas. Eso, o aprendes a vivir con el miedo a tu código y simplemente nunca lo cambias.

sara
fuente
3
Una regla general que me he dado cuenta; Si necesitaba documentos para escribir e inspeccionar el código, necesitaré una prueba unitaria. Me han ahorrado muchos dolores de cabeza, atrapando punteros nulos, ninguno y resultados incorrectos. También le dan al usuario final la capacidad de reparar su código según las especificaciones con un mínimo esfuerzo cuando inevitablemente se rompe.
Aaron3468
-1

Por otro lado: ellos mismos rara vez forman parte de la interfaz de alguna unidad. Sería mejor probar solo la interfaz y hacerlo de una manera que implícitamente pruebe las expresiones regulares.

Creo que con esto lo respondiste tú mismo. Las expresiones regulares en una unidad son muy probablemente un detalle de implementación.

Lo que vale para probar tu SQL probablemente también va para expresiones regulares. Cuando cambia un pedazo de SQL, probablemente lo ejecute a través de un cliente SQL a mano para ver si produce lo que espera. Lo mismo ocurre cuando cambio una expresión regular, uso alguna herramienta de expresión regular con alguna entrada de muestra para ver si hace lo que esperaba.

Lo que encuentro útil es un comentario cerca de la expresión regular con una muestra de texto que debe coincidir.

Christiaan
fuente
" Cuando cambia una pieza de SQL, probablemente la ejecute a través de un cliente SQL a mano para ver si produce lo que espera " . Pero este tipo de respuesta responde a la pregunta de otra manera ... Si necesito o creo que es útil prueba las expresiones regulares a mano, entonces debería hacer una prueba unitaria para eso. ¡Exactamente esto es lo que hace que sea algo difícil de decidir!
Lii
Realmente depende Lo que desea que su unidad pruebe es la capacidad de realizar cambios. ¿Con qué frecuencia cambia una expresión regular específica? Si la respuesta es a menudo, entonces crea una prueba para ello.
Christiaan
8
En igualdad de condiciones, es mejor tener una prueba automatizada que una "prueba a mano".
Robert Harvey
1
¿Por qué no probarías una expresión regular utilizando la automatización?
Tony Ennis
1
Es parte de un método y todo lo que intentaba decir es que no hay necesidad de probar específicamente la expresión regular si ya probó ese método. Pero si lo hace, probablemente sea mejor extraer la expresión regular en una función separada que pruebe de forma aislada.
Christiaan
-5

Si tiene que preguntar, la respuesta es sí.

Supongamos que aparece un FNG y cree que puede "mejorar" su expresión regular. Ahora, él es un FNG, así que automáticamente un idiota. ¡Exactamente el tipo de persona que nunca debe tocar su precioso código bajo ninguna circunstancia! Pero tal vez esté relacionado con el PHB o algo así, así que no hay nada que puedas hacer.

Excepto que sabes que el PHB te arrastrará pateando y gritando de nuevo a este proyecto para "tal vez darle al chico algunos consejos sobre cómo hiciste este desastre" cuando todo va mal. Entonces, escribe todos los casos que ha considerado cuidadosamente al construir su hermosa obra maestra de expresión.

Y dado que los ha escrito todos, tiene dos tercios del camino para tener un conjunto de casos de prueba, ya que, seamos sinceros, los casos de prueba de expresiones regulares son muy fáciles de ejecutar una vez que se ha creado el marco.

Entonces, ahora tiene un conjunto de condiciones de borde, alternativas y resultados esperados. Y de repente, los casos de prueba son la documentación tal como se prometió en todas esas publicaciones de blog de Agile. Simplemente le señala a la FNG que si su "mejora" no supera los casos de prueba existentes, no es una gran mejora, ¿verdad? ¡Y dónde están sus nuevos casos de prueba propuestos que demuestran algún problema con el código original, que ya que funciona, no necesita modificarse, nunca!

Austin Hastings
fuente
3
¿Qué es el FNG? Esto no me parece una mala respuesta, pero me falta la definición de FNG (Google solo da resultados que no están relacionados, ¿tal vez esta respuesta fue rechazada debido a FNG?)
GameDeveloper
1
Sospecho que Google te llevó al lugar correcto. ;-) ( en.wikipedia.org/wiki/FNG_syndrome )
Austin Hastings
A menos que seas un genio de la programación absoluta, habrá programadores más experimentados que considerarán lo que haces al mirar al nuevo chico. Es posible que desee considerar ser más humilde.
Thorbjørn Ravn Andersen