I build a simple function that control if a password have:
I built a simple function that checks if a password contains:
The function is:
import re
class Password():
def validate(password):
while True:
if len(password) < 8:
print("False")
elif re.search('[0-9]', password) is None:
print("False")
elif re.search('[A-Z]', password) is None:
print("False")
else:
print("Your password seems fine")
break
This function is saved in a file called password.py
Now I want do a unit test that control each condition:
import Password
import unittest
class TestPassword(unittest.TestCase):
def test_password(self):
valid = Password.Password()
self.assertEqual("asdfA1qw",valid.validate())
if __name__ == '__main__':
unittest.main()
But I don't know how. How can i set a control for each if?
First, validate
can just be a bare function that returns True
or False
as appropriate.
def validate(password):
if len(password) < 8:
return False
elif re.search('[0-9]', password) is None:
return False
elif re.search('[A-Z]', password) is None:
return False
else:
return True
Now the tests are trivial:
import Password
import unittest
class TestPassword(unittest.TestCase):
def test_password(self):
self.assertTrue(Password.validate("asdfA1qw"))
def test_short_password(self):
self.assertFalse(Password.validate("foo"))
You would define separate tests with various invalid passwords to trigger each of your conditions. (One with a too-short password, another without any numbers, etc.)
The task of actually inputting a password until it validates does not belong in validate
; it should be a separate loop that uses validate
:
while True:
password = input("Enter a password: ")
if Password.validate(password):
break
print("Password invalid, try again", file=sys.stderr)
You cannot directly set control on each if
statement. You have to provide right value to valid.validate()
in your test function to force it to go into right if
.
If you want to test your function properly, you could make it return an individual value for each case:
def validate(password):
if len(password) < 8:
return 'password must have at least 8 characters'
elif re.search('[0-9]', password) is None:
return 'password must at least contain a numeric character'
elif re.search('[A-Z]', password) is None:
return 'password must aat least contain an upper case character'
else:
return "Your password seems fine"
Then you can check those branches by coming up with a password that will break one of these rules. eg: abcdefg
, abcdefgh
, 4bcdefgh
, 4Bcdefgh
Then have another method use that function an make it have a reasonable return value, too.
(Opinionated note: If you write your test first, you don't run into such problems, since you will already design your code in a way that it is easy testable)
Your approach is very weird, I suppose that you prefer Java programming language:
True
or False
in your case). None
is not a Pythonic way. while True:
and break
is meaningless in this situation. elif
are useless if you will use return
. So it's sufficient to rewrite is as
import re
def validate(password):
if len(password) < 8:
return False
if not re.search('[0-9]', password):
return False
if not re.search('[A-Z]', password):
return False
return True
Now, because your UnitTest is probably in an another module than your tested code (because PyCharm creates it for you in that way), you first have to import password
- as your tested function is in the password.py
file.
In UnitTest you must define a test class (as you did), and test methods (as you did). You may define as many tests in a single test method as you wish, but much better is to define different test method for every test.
Tests themselves (in your testing methods) will be now - after refactoring your original code - very simple: We will test only for return values True
or False
. An example:
self.assertTrue(password.validate("asdfA1qw"))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.