这些帖子将分为三个部分。
1.密码验证功能
2.重构密码验证函数
3.对密码验证功能进行单元测试
这是Python系列中自定义密码验证的第三部分,也是最后一部分。我们将看看对密码验证功能进行单元测试 .
下面是重构后的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
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 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字符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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
1
2
|
def get_valid_chars(): return "".join(valid_chars) |
进行测试。
让我们检查中的有效字符is_valid_password通过在return True中的语句try封锁。
1
2
|
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类似于下面的代码片段:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
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类似于下面的代码片段:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
import unittest from app import (contains_character, is_valid_size, is_valid_password) 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" )) 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&" )) 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密码验证的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/weixin_52994140/article/details/123003338