Artículo

Cómo implementar un validador de contraseñas en Python aplicando TDD (II)

Tech & innovation

Cómo implementar un validador de contraseñas en Python aplicando TDD (II)

Ha llegado la hora de terminar nuestro validador de contraseñas en Python. En este artículo vamos a ver cómo podemos asegurarnos de que nuestra contraseña tenga letras mayúsculas y minúsculas, números y caracteres especiales. Puesto que en la primera parte de esta guía vimos algunos conceptos básicos sobre TDD, y nos hicimos a la idea de cómo ponerlo en práctica, en esta segunda parte iré un poco más al grano. En mi cuenta de GitHub tienes acceso a más información. ¡Manos a la obra!  

Validar la presencia de minúsculas

Antes de avanzar más recordemos brevemente qué es lo que habíamos hecho. Estos eran nuestros tests: [gist id="8b85317e5522b2cf8300"] Y esta era nuestra clase PasswordValidator: [gist id="5d0e38c1b596826ddf80"] Lo primero que haremos es asegurarnos de que nuestra contraseña tenga letras minúsculas. Para ello, añadiremos otro test: [gist id="bd27aa02e4a1976b10bb"] Como la clase PasswordValidator no contiene ninguna función llamada containsLowerLetters vamos a implementarla: [gist id="6e9b199e4064a445bf48"] No hay nada que refactorizar en la clase pero sí en los tests. El token 'abcdefghij', usado en el primer y tercer test, puede moverse a una variable en el método setUp. A continuación necesitaremos un nuevo test que compruebe que la contraseña no contiene letras minúsculas: [gist id="dfcd543e84bc7d961a85"] Y ahora, para que la función containsLowerLetters pase ambos tests, cambiaremos su código: [gist id="69effc0b5ebf0b65ed87"] Y con eso, nuestra función containsLowerLetters ya estará lista.  

¿Y las mayúsculas, números y caracteres especiales?

Para implementar funciones que comprueben la presencia de mayúsculas, números y caracteres especiales, podemos seguir los mismos pasos que ya hemos visto con la validación de minúsculas. Por esta razón, y para no repetirme demasiado, simplemente te invito a que repitas el procedimiento que hemos seguido aquí, pero comprobando una cosa diferente en cada ocasión. Al final, seguramente, tendrás unos tests similares a estos: [gist id="24130c142c9d6e6e6862"] Y un código parecido a este: [gist id="597756f7ca1551c077be"] Con eso, nuestro validador de contraseñas ya estaría listo... o casi. Todavía podemos mejorarlo un poco más:

  • Tal y como tenemos actualmente nuestra clase PasswordValidator, para validar una contraseña tenemos que declarar una instancia de la clase y usar todos los métodos que nos proporciona, lo cual no es demasiado práctico.
  • Peor aún, existe duplicación en los métodos que validan la presencia de mayúsculas, minúsculas, números y caracteres especiales. Todos ellos hacen uso de la función re.search, y la única diferencia es la expresión regular que se usa para validar.

Para solucionar ambos problemas, podemos hacer lo siguiente:

  • Crear un nuevo método llamado isStrongPassword, que será el que haga todas las validaciones.
  • Incluir una función auxiliar que se encargue de validar una expresión regular. Usaremos esta función dentro del método anterior.

Así quedaría la clase PasswordValidator tras los cambios: [gist id="2cacbb7bb38cc3a6ab45"] Puesto que ahora todas las validaciones se encuentran dentro del método isStrongPassword, ya no nos hace falta el método hasMinimumLength. Naturalmente, los tests fallan, de modo que tenemos que actualizarlos: [gist id="a5ee20b1db28c5688ae1"] Gracias a este cambio no sólo hemos eliminado duplicación, sino que además hemos reducido bastante la cantidad de tests necesarios.  

Reflexión final

Cabe destacar que el código que hemos escrito siguiendo esta guía no es necesariamente el mejor. Es simplemente mi enfoque personal sobre cómo resolver el problema. Otro desarrollador podría haber optado por otra alternativa igualmente válida. En la primera parte de esta guía vimos que, antes de empezar a escribir una sola línea de código, teníamos que tomar decisiones sobre cómo iba a ser nuestra API. Este tipo de decisiones tienen que ver únicamente con el diseño del software, que depende por completo de los conocimientos y la experiencia del desarrollador. Si a esto le sumamos que la refactorización en el paso 3 nos puede salir mejor o peor, dependiendo de nuestras habilidades, tenemos que TDD no es garantía de escribir software de calidad ya que podemos partir de un buen diseño y acabar convirtiéndolo en uno mediocre. No obstante, a pesar de esto, TDD sigue siendo una de las metodologías de desarrollo de software más extendidas porque aplicarlo tiene múltiples ventajas. Si quieres saber más te invito a que eches un vistazo a este post sobre Test-Driven Development (TDD) que escribí en mi blog donde explico, en más profundidad, los conceptos básicos y muestro algunos ejemplos más. ¿Qué opinas? ¿Cómo resolverías tú el problema de la validación de contraseñas?

¡Hablemos!