前言
我们上一次分享了FastAPI(八十三)实战开发《在线课程学习系统》--注册接口单元测试,这次我们来通过接口的方式对于登陆接口进行测试。
正文
登陆接口的相关代码FastAPI(六十六)实战开发《在线课程学习系统》接口开发--用户登陆接口开发,对应的设计文档可以看,FastAPI(六十二)实战开发《在线课程学习系统》梳理系统需要接口。那么我们看来看下对应的接口怎么测试。
那么我们去设计对应的登陆用例,由于接口我们之前开发过,我们参照之前的接口开发的代码进行用例设计。
1.登陆用户不存在。
输入参数:
self.parame = {
"username": "liwanle1i33333",
"password": "123456"
}
期望:
message='用户不存在'
code=100205
2.登陆成功
参数:
self.parame = {
"username": "liwanle1i",
"password": "123456"
}
预期:
message='成功'
code=200
3.密码正确再次登陆直接返回之前的token,预期还是一样的。
4.输入密码错误
参数:
self.parame = {
"username": "liwanle1i",
"password": "123452336"
}
预期:
code=100206
message='密码错误'
我们设计了四条case
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:
'''
还原测试环境,测试url
:return:
'''
cls.client = None
cls.url = ''
def setUp(self) -> None:
'''
初始化参数
:return:
'''
self.parame = {
"username": "liwanle1i",
"password": "123456"
}
def tearDown(self) -> None:
'''最后清理参数'''
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'], '用户不存在')
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'], '成功')
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'], '成功')
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'], "密码错误")
if __name__ == "__main__":
unittest.main()
那么我们执行下测试结果
我们来看下我们的测试用例,目前少了二个场景,密码错误超过10次但是时间小于30min,一个是时间大于30min,那么我们如何实现呢,最简单的就是for循环10次,其实这样做不可以,因为没有了,那么应该怎么做呢,我们可以直接这么来做。直接修改redis即可。
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'], "输入密码错误次数过多,账号暂时锁定,请30min再来登录")
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'], "密码错误")
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'], "成功")
red.hdel("liwanle1i_password", 'time')
red.hdel("liwanle1i_password", 'num')
我们还在增加了一个当有错误密码,但是次数不大于10,时间大于30min的可以正常登陆成功,不过我门也发现了接口存在问题。
@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 + "不存在")
return reponse(code=100205, message='用户不存在', 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='产生token失败', data='')
request.app.state.redis.set(user.username, token, expire=ACCESS_TOKEN_EXPIRE_MINUTES * 60)
return reponse(code=200, message='成功', data={"token": token})
return reponse(code=200, message='成功', 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='密码错误')
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:
# 更新错误次数
errornum += 1
request.app.state.redis.hmset_dict(user.username + "_password", num=errornum)
return reponse(code=100206, data='', message='密码错误')
elif errornum < 10 and numtime > 30:
# 次数置于1,时间设置现在时间
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='密码错误')
elif errornum > 10 and numtime < 30:
# 次数设置成最大,返回
errornum += 1
request.app.state.redis.hmset_dict(user.username + "_password", num=errornum)
return reponse(code=100204, message='输入密码错误次数过多,账号暂时锁定,请30min再来登录', 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='密码错误')
修改后的代码,基本业务需求已经满足。
后记
发现问题,解决问题。遇到问题,慢慢解决问题即可。
欢迎关注雷子说测试开发,后续将会持续为大家分享更多的技术知识
如果你有问题可以留言或者加我微信:952943386。
2021,一起牛转钱坤,一起牛逼。
如果觉得这篇文章还不错,来个【分享、点赞、在看】三连吧,让更多的人也看到~