I used TDD to write the code.
These are the tests using Pytest:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pytest | |
from password_validator import PasswordValidator | |
@pytest.fixture | |
def validator(): | |
return PasswordValidator(8) | |
def test_a_strong_password(validator): | |
assert validator.is_strong_password("#Ab3cccc") is True | |
def test_that_only_passwords_with_the_minimum_length_are_strong(validator): | |
assert validator.is_strong_password("#Ab3ccc") is False | |
def test_that_only_passwords_including_numbers_are_strong(validator): | |
assert validator.is_strong_password("#Abccccc") is False | |
def test_that_only_passwords_including_upper_case_letters_are_strong(validator): | |
assert validator.is_strong_password("#ab3cccc") is False | |
def test_that_only_passwords_including_lower_case_letters_are_strong(validator): | |
assert validator.is_strong_password("#AB3CCCC") is False | |
def test_that_only_passwords_including_special_characters_are_strong(validator): | |
assert validator.is_strong_password("cAb3cccc") is False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
class PasswordValidator(object): | |
def __init__(self, minimum_length): | |
self.minimum_length = minimum_length | |
def is_strong_password(self, password): | |
includes_special_characters = self._includes_any( | |
self.REQUIRED_SPECIAL_CHARACTERS, password | |
) | |
includes_lower_case_letters = self._includes_any( | |
self.LOWER_CASE_LETTERS, password | |
) | |
includes_upper_case_letters = self._includes_any( | |
self.UPPER_CASE_LETTERS, password | |
) | |
includes_numbers = self._includes_any(self.NUMBERS, password) | |
has_minimum_length = len(password) >= self.minimum_length | |
return \ | |
has_minimum_length and \ | |
includes_numbers and \ | |
includes_upper_case_letters and \ | |
includes_lower_case_letters and \ | |
includes_special_characters | |
@staticmethod | |
def _includes_any(pattern, password): | |
return re.search(pattern, password) is not None | |
REQUIRED_SPECIAL_CHARACTERS = '[%#]' | |
UPPER_CASE_LETTERS = '[A-Z]' | |
LOWER_CASE_LETTERS = '[a-z]' | |
NUMBERS = '[0-9]' |
If you want to follow the process step by step, have a look at the commits.
You can find all the code in GitHub.
No comments:
Post a Comment