开发者

详解Python中的自定义密码验证

目录
  • 在测试:nut_and_bolt:️之前
  • 试验contains_character
    • TestContainsCharacter字符
  • 试验is_valid_size
    • TestIsValidSize
  • 试验is_valid_password
    • TestIsValidPassword
    • 重构is_valid_password
  • 结论

    这些帖子将分为三个部分。

    1.密码验证功能

    2.重构密码验证函数

    3.对密码验证功能进行单元测试

    这是python系列中自定义密码验证的第三部分,也是最后一部分。我们将看看对密码验证功能进行单元测试 .

    下面是重构后的代码:

    from string import (
        ascii_lowercase, ascii_uppercase,
        digits, punctuation, whitespace)
        
    def contains_character(password: str = "", sack: str = "") -> bool:
        has_char = False
        for char in password:
            if char in sack:
                has_char = True
                break
        return has_char
        
    def is_valid_size(password: str = "") -> bool:
        MIN_SIZE = 6
        MAX_SIZE = 20
        password_size = len(password)
    
        return MIN_SIZE <= password_size <= MAX_SIZE
        
    def get_invalid_chars():
        valid_chars = {'-', '_', '.', '!', '@', '#', '$', '^', '&', '(', ')'}
        invalid_chars = set(punctuation + whitespace) - valid_chars
    
        return "".join(invalid_chars)
    
    def is_valid_password(password: str = "") -> bool:
        try:
            if not password:
                return False
    
            new_password = password.strip()
    
            if not is_valid_size(new_password):
                return False
    
       gzsXh     invalid_chars = get_invalid_chars()
    
            if contains_character(new_password, invalid_chars):
                return False
    
            if not contains_character(new_password, digits):
                return False
    
            if not contains_character(new_password, ascii_lowercase):
                return False
    
            if not contains_character(new_password, ascii_uppercase):
                return False
    
            return True
        except:
            return False

    我们的目标是为上面的代码片段编写单元测试。我们可以捕捉隐藏的错误,并在修复代码以通过测试时继续重构。

    在测试:nut_and_bolt:️之前

    有些事你应该知道:

    • 这将是一个单元测试
    • 我们将利用python的内置编程客栈测试模块,unittest
    • 我们将测试,contains_character , is_valid_size和is_valid_password整齐
    • 测试将在test.py所以上面的片段可能在app.py(你选择你想要的名字)
    • 我们将参考

    试验contains_character

    contains_character返回bool,要么True或者False。所以我们可以使用assertTrue还有assertFalse方法。

    我们将测试:

    • 如果既没有传递密码也没有传递sack(无参数)
    • 为了角色"i"在字符串中,"python"
    • 为了角色"py"在字符串中,"python"
    • 为了角色"python"在字符串中,"python"

    有些情况下,比如int作为传递password或者当一个list作为传递sack。我们不会测试这种情况。(您应该为此进行测试)

    TestContainsCharacter字符

    import unittest
    from app import contains_character
    
    
    class TestContainsCharacter(unittest.TestCase):
        def test_empty_password_or_and_empty_sack(self):
            self.assertFalse(contains_character())
    
        def test_char_i_in_str_python(self):
            self.assertFalse(contains_character("i", "python"))
    
        def test_str_py_in_str_python(self):
            self.assertTrue(contains_character("py", "python"))
    
        def test_str_python_in_str_python(self):
            self.assertTrue(contains_character("python", "python"))
    
    if __name__ == "__main__":
        unittest.main()

    我们能击中ctrl + F5运行此脚本(test.py)无需调试。我们可以像下面这样运行这个脚本python3 test.py或者python3 -m unittest test.py。所有这些测试都应该通过。

    试验is_valid_size

    is_valid_size返回bool,要么True或者False。所以我们可以使用assertTrue还有assertFalse方法。

    我们将测试:

    • 对于空密码或没有传递参数时
    • 四个字符的密码
    • 六个字符的密码
    • 十六个字符的密码
    • 二十个字符的密码
    • 21个字符的密码

    TestIsValidSize

    import unittest
    from app import is_valid_size
    
    
    class TestIsValidSize(unittest.TestCase):
        def test_empty_password(self):
            self.assertFalse(is_valid_size(""))
    
        def test_4_char_password(self):
            self.assertFalse(is_valid_size("pass"))
    
        def test_6_char_password(self):
            self.assertTrue(is_valid_size("passwd"))
    
        def test_16_char_password(self):
            self.assertTrue(is_valid_size("ThisIs1Password!"))
    
        def test_20_char_password(self):
            self.assertTrue(is_valid_size("ThisIs1Password!+20"))
    
        def test_21_char_password(self):
            self.assertFalse(is_valid_size("ThisIs1Password!+20&"))
    
    
    if __name__ == "__main__":
        unittest.main()

    所有这些测试都应该通过。

    试验is_valid_password

    is_valid_password返回bool,要么True或者False。所以我们可以使用assertTrue还有assertFalse方法。

    我们将测试:

    1.对于空密码

    2.三个字符的密码

    3.十个字符的密码

    4.二十个字符的密码

    5.对于包含无效特殊字符(如分号)的密码

    6.对于没有数字的密码

    7.对于没有小写字母的密码

    8.对于没有大写字母的密码

    9.对于没有有效特殊字符的密码

    10.对于有效的密码

    • 一个尺寸以内,[6-20]
    • 至少一个小写和大写字符
    • 至少一个数字
    • 没有无效的特殊字符

    TestIsValidPassword

    class TestIsValidPassword(unittest.TestCase):
        def test_empty_password(self):
            self.assertFalse(is_valid_password())
    
        def test_password_of_size_three(self):
            self.assertFalse(is_valid_password("pas"))
    
        def test_password_of_size_ten(self):
            self.assertFalse(is_valid_password("Password12"))
            self.assertTrue(is_valid_password("Password1_"))
    
        def test_password_of_size_twenty(self):
            self.assertFalse(is_valid_password("Password12Password_$"))
    
        def test_password_with_invalid_special_character_semicolon(self):
            self.assertFalse(is_valid_password("Password1_;"))
            self.assertFalse(is_valid_password("Password1;"))
    
        def test_password_with_no_digit(self):
            self.assertFalse(is_valid_password("Password_"))
    
        def test_password_with_no_lowercase(self):
            self.assertFalse(is_valid_password("PASSWORD1_"))
    
        def test_password_with_no_uppercase(self):
            self.assertFalse(is_valid_password("password1_"))
    
        def test_password_without_valid_special_character(self):
            self.assertFalse(is_valid_password("Password1"))
    
        def test_valid_password(self):
            self.assertTrue(is编程客栈_valid_password("Password1_"))
            self.assertTrue(is_valid_password("PassWord34$"))
    
    
    if __name__ == "__main__":
        unittest.main()

    不是所有的测试都通过了。这些测试用例不应该通过——我们期望它们不会通过。所以当我们期待False我们得到True。某处存在缺陷或错误。

    这些测试没有通过:

    • test_password_of_size_ten : self.assertFalse(is_valid_password("Password12"))应该是False因为即使大小有效,它也没有特殊字符。
    • test_password_without_valid_special_character : self.assertFalse(is_valid_password("Password1"))应该是False因为没有有效的特殊字符。

    这is_valid_password函数不检查是否存在有效的特殊字符。它检查无效字符,但不检查有效字符。这是由有缺陷的假设造成的,即只要密码不包含无效字符,它就包含有效字符(包括有效的特殊字符)。

    重构is_valid_password

    既然我们已经指出了我们的bug,我们应该做出改变并重新运行测试。

    要进行的更改:

    在…里get_invalid_chars,我们有set有效的特殊字符,valid_chars。让我们让它对所有函数都是全局的(例如,把它从get_invalid_chars函数并将其放在函数的顶部)。为了确保某处没有损坏,运行测试(我们预计有两种情况会失败)。请注意,即使我们移动valid_chars由于get_invalid_chars , get_invalid_chars应该还能正常工作。

    这valid_chars是一个set,它可以用作中的一组get_invalid_chars . contains_character需要一段时间string sack作为论据。我们必须解析valid_chars如同string。让我们在下面创建一个函数get_invalid_chars返回一个string版本valid_chars 

    def get_valid_chars():
        return "".join(valid_chars)
    

    进行测试。

    让我们检查中的有效字符is_valid_password通过在return True中的语句try封锁。

    if not contains_character(new_password, get_valid_chars()):
        return False
    

    进行测试。现在,所有的测试都通过了。万岁!!:clap:️:clap:️:clap:️

    这更多的是重新排列代码is_valid_password在另一种环境中自然运行良好。我们将重新排列代码is_valid_password按此顺序分别为:size, lower case, upper case, digit, invalid special character and valid special character进行测试。

    结论

    这is_valid_password会在app.py类似于下面的代码片段:

    from string import (ascii_lowercase, ascii_uppercase, digits, punctuation,
                        whitespace)
    valid_chars = {'-', '_', '.', '!', '@', '#', '$', '^', '&', '(', ')'}
    
    
    def contains_character(password: str = "", sack: str = "") -> bool:
        has_char = False
    
        for char in password:
            if char in sack:
                has_char = True
                break
    
        return has_char
    
    
    def is_valid_size(password: str = "") -> bool:
        MIN_SIZE = 6
        MAX_SIZE = 20
        password_size = len(password)
    
        return MIN_SIZE <= password_size <= MAX_SIZE
    
    
    def get_invalid_chars():
        invalid_chars = set(punctuation + whitespace) - valid_chars
        return "".join(invalid_chars)
    
    
    def get_valid_chars():
        return "".join(valid_chars)
    
    
    def is_valid_password(password: str = "") -> bool:
        try:
            if not password:
                return False
    
            new_password = password.strip()
    
            if not is_valid_size(new_password):
                return False
    
            if not contains_character(new_password, ascii_lowercase):
                return False
    
            if not contains_character(new_password, ascii_uppercase):
                return False
    
            if not contains_character(new_password, digits):
                return False
    
            if contains_character(new_password, get_invalid_chars()):
                return False
    
            if not contains_character(new_password, get_valid_chars()):
                return False
    
            return True
        except:
            return False

    单元测试将会在test.py类似于下面的代码片段:

    import unittest
    from app import (contains_character, is_valid_size, is_valid_password)
    
    
    class TestContainsCharacter(unittest.TestCase):
        def test_emptgzsXhy_password_or_and_empty_sack(self):
            self.assertFalse(contains_character())
    
        def test_char_i_in_str_python(self):
            self.assertFalse(contains_character("i", "python"))
    
        def test_str_py_in_str_python(self):
            self.assertTrue(contains_character("py", "python"))
    
        def test_str_python_in_str_python(self):
            self.assertTrue(contains_character("python", "python"))
    
    
    class TestIsValidSize(unittest.TestCase):
        def test_empty_password(self):
            self.assertFalse(is_valid_size(""))
    
        def test_4_char_password(self):
            self.assertFalse(is_validwww.cppcns.com_size("pass"))
    
        def test_6_char_password(self):
            self.assertTrue(is_valid_size("passwd"))
    
        def test_16_char_password(self):
            self.assertTrue(is_valid_size("ThisIs1Password!"))
    
        def test_20_char_password(self):
            self.assertTrue(is_valid_size("ThisIs1Password!/+20"))
    
        def test_21_char_password(self):
            self.assertFalse(is_valid_size("ThisIs1Password!/+20&"))
    
    
    class TestIsValidPassword(unittest.TestCase):
        def test_empty_password(self):
            self.assertFalse(is_valid_password())
    
        def test_password_of_size_three(self):
            self.assertFalse(is_valid_password("pas"))
    
        def test_password_of_size_ten(self):
            self.assertFalse(is_valid_password("Password12"))
            self.assertTrue(is_valid_password("Password1_"))
    
        def test_password_of_size_twenty(self):
            self.assertTrue(is_valid_password("Password12Password_$"))
    
        def test_password_with_invalid_special_character_semicolon(self):
            self.assertFalse(is_valid_password("Password1_;"))
            self.assertFalse(is_valid_password("Password1;"))
    
        def test_password_with_no_digit(self):
            self.assertFalse(is_valid_password("Password_"))
    
        def test_password_with_no_lowercase(self):
            self.assertFalse(is_valid_password("PASSWORD1_"))
    
        def test_password_with_no_uppercase(self):
            self.assertFalse(is_valid_password("password1_"))
    
        def test_password_without_valid_special_character(self):
            self.assertFalse(is_valid_password("Password1"))
    
        def test_valid_password(self):
            self.assertTrue(is_valid_password("Password1_"))
            self.assertTrue(is_valid_password("PassWord34$"))
    
    
    if __name__ == "__main__":
        unittest.main()

    以上就是详解Python中的自定义密码验证的详细内容,更多关于Python密码验证的资料请关注我们其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜