FastAPI actual development of online course learning system -- landing interface test

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~

Posted by simn_stv on Mon, 22 Nov 2021 21:29:51 -0800