preface
We shared it last time FastAPI (83) actual development of online course learning system -- registered interface unit test This time, let's test the login interface through the interface.
text
Relevant code of login interface FastAPI (66) practical development interface development of online course learning system -- user login interface development , the corresponding design documents can be viewed, FastAPI (62) actual development of online course learning system combs the interface required by the system . So let's see how to test the corresponding interface.
Then we design the corresponding login use case. Since the interface has been developed before, we refer to the code developed by the previous interface for use case design.
1. The login user does not exist.
Input parameters:
self.parame = { "username": "liwanle1i33333", "password": "123456" }
expect:
message='user does not exist' code=100205
2. Successful login
Parameters:
self.parame = { "username": "liwanle1i", "password": "123456" }
expect:
message='success' code=200
3. The password is correct. Log in again and directly return to the previous token. The expectation is the same.
4. Wrong password
Parameters:
self.parame = { "username": "liwanle1i", "password": "123452336" }
expect:
code=100206 message='Password error'
We designed four case s
import unittest, requests class UserLoginCase(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.url = 'http://127.0.0.1:8000/user/login' @classmethod def tearDownClass(cls) -> None: ''' Restore test environment, testing url :return: ''' cls.client = None cls.url = '' def setUp(self) -> None: ''' Initialization parameters :return: ''' self.parame = { "username": "liwanle1i", "password": "123456" } def tearDown(self) -> None: '''Final cleanup parameters''' self.parame.clear() def test_login_usernot_exict(self): parame = { "username": "liwanle1i33333", "password": "123456" } reponse = requests.post(self.url, json=parame) status = reponse.status_code reslut = reponse.json() self.assertEqual(status, 200) self.assertEqual(reslut['code'], 100205) self.assertEqual(reslut['message'], 'user does not exist') def test_login_success(self): reponse = requests.post(self.url, json=self.parame) status = reponse.status_code reslut = reponse.json() self.assertEqual(status, 200) self.assertEqual(reslut['code'], 200) self.assertEqual(reslut['message'], 'success') def test_login_success_two(self): reponse = requests.post(self.url, json=self.parame) status = reponse.status_code reslut = reponse.json() self.assertEqual(status, 200) self.assertEqual(reslut['code'], 200) self.assertEqual(reslut['message'], 'success') def test_login_error(self): self.parame['password']='2222222222' reponse = requests.post(self.url, json=self.parame) status = reponse.status_code reslut = reponse.json() self.assertEqual(status, 200) self.assertEqual(reslut['message'], "Password error") if __name__ == "__main__": unittest.main()
So let's run the test results
Let's take a look at our test case. At present, there are two scenarios missing. There are more than 10 password errors, but the time is less than 30min. One is more than 30min. How can we implement it? The simplest is to cycle for 10 times. In fact, this can't be done. Because there is no, what should we do? We can do it directly. You can modify redis directly.
def test_log_error_big(self): red = redis.Redis(host='localhost', port=6379, db=0) red.hset("liwanle1i_password",'num',11) red.hset("liwanle1i_password", 'time', "2021-11-17 22:16:57") self.parame['password'] = '2222222222' reponse = requests.post(self.url, json=self.parame) status = reponse.status_code print(reponse.text) reslut = reponse.json() self.assertEqual(status, 200) self.assertEqual(reslut['code'],100204) self.assertEqual(reslut['message'], "The number of incorrect password entries is too many, and the account is temporarily locked. Please 30 min Log in again") red.hdel("liwanle1i_password",'num') def test_log_error_bigtime(self): red = redis.Redis(host='localhost', port=6379, db=0) red.hset("liwanle1i_password",'num','1') red.hset("liwanle1i_password", 'time', "2021-10-17 22:16:57") self.parame['password'] = '2222222222' reponse = requests.post(self.url, json=self.parame) status = reponse.status_code print(reponse.text) reslut = reponse.json() print(reslut) self.assertEqual(status, 200) self.assertEqual(reslut['message'], "Password error") red.hdel("liwanle1i_password", 'time') def test_log_error_bigtime_success(self): red = redis.Redis(host='localhost', port=6379, db=0) red.hset("liwanle1i_password", 'num', '1') red.hset("liwanle1i_password", 'time', "2021-10-17 22:16:57") reponse = requests.post(self.url, json=self.parame) status = reponse.status_code print(reponse.text) reslut = reponse.json() print(reslut) self.assertEqual(status, 200) self.assertEqual(reslut['message'], "success") red.hdel("liwanle1i_password", 'time') red.hdel("liwanle1i_password", 'num')
We have also added an error password, but the number of times is no more than 10 and the time is more than 30min. We can log in normally, but we also found problems with the interface.
@usersRouter.post("/login") async def login(request: Request, user: UserLogin, db: Session = Depends(get_db)): db_crest = get_user_username(db, user.username) if not db_crest: logger.info("login: " + user.username + "non-existent") return reponse(code=100205, message='user does not exist', data="") verifypassowrd = verify_password(user.password, db_crest.password) if verifypassowrd: useris = await request.app.state.redis.get(user.username) if not useris: try: token = create_access_token(data={"sub": user.username}) except Exception as e: logger.exception(e) return reponse(code=100203, message='produce token fail', data='') request.app.state.redis.set(user.username, token, expire=ACCESS_TOKEN_EXPIRE_MINUTES * 60) return reponse(code=200, message='success', data={"token": token}) return reponse(code=200, message='success', data={"token": useris}) else: result = await request.app.state.redis.hgetall(user.username + "_password", encoding='utf8') if not result: times = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S") request.app.state.redis.hmset_dict(user.username + "_password", num=0, time=times) return reponse(code=100206, data='', message='Password error') else: errornum = int(result['num']) numtime = (datetime.now() - datetime.strptime(result['time'], '%Y-%m-%d %H:%M:%S')).seconds / 60 if errornum < 10 and numtime < 30: # Number of update errors errornum += 1 request.app.state.redis.hmset_dict(user.username + "_password", num=errornum) return reponse(code=100206, data='', message='Password error') elif errornum < 10 and numtime > 30: # The number of times is set to 1, and the time is set to the current time errornum = 1 times = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S") request.app.state.redis.hmset_dict(user.username + "_password", num=errornum, time=times) return reponse(code=100206, data='', message='Password error') elif errornum > 10 and numtime < 30: # Set the maximum number of times and return errornum += 1 request.app.state.redis.hmset_dict(user.username + "_password", num=errornum) return reponse(code=100204, message='The number of incorrect password entries is too many, and the account is temporarily locked. Please 30 min Log in again', data='') else: errornum = 1 times = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S") request.app.state.redis.hmset_dict(user.username + "_password", num=errornum, time=times) return reponse(code=100206, data='', message='Password error')
With the modified code, the basic business requirements have been met.
Postscript
Find and solve problems. If you encounter problems, you can solve them slowly.
Welcome to Leizi's test development. We will continue to share more technical knowledge for you in the future
If you have any questions, you can leave a message or add me to wechat: 952943386.
2021, a cow turns to Qian Kun and a cow forces.
If you think this article is good, let's have a [share, like and watch] three links to let more people see it~