1. 程式人生 > 其它 >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,那麼對應的完整的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='密碼錯誤')

  我們的介面測試就是在不斷的去發現問題改造問題。

這裡提供了一個demo,所有的程式碼都放在了

https://gitee.com/liwanlei/fastapistuday

  用例設計是門藝術,我們在不斷的測試中調整去修改優化我們的程式碼。