Front-end test development tools -- the use of mock

content

1. Background

2. What is Mock

3. What Mock can do

4. Mock implementation

5. Common solutions in the Mock market

6. Using unittest.mock under Python


1. Background

In the actual product development process, a service or front-end depends on a service interface, which may depend on multiple underlying services or modules, or third-party interfaces. For example, service A depends on service B, and service B depends on service C, as shown in the following figure shown:

This kind of dependency problem will cause the original requirement to verify service A, but because the dependent service B or service C is unstable or not developed, the work cannot be carried out normally.

So as test engineers, what should we do in the face of such a situation? The core idea to solve this kind of problem is to introduce a dependent service stand-in, more commonly known as a Mock service.

Today, combined with the unittest framework, I will share with you some common uses of Mock.

2. What is Mock

There may be some readers who have not been in contact with Mock before and do not know what Mock is.

Mock simply understands that during the testing process, for some objects that are not easy to construct or obtain, a virtual object is created for testing. And this virtual object is the mock object. Mock objects are substitutes for real objects during debugging.

Sometimes the Mock service is also called a test service stand-in, or a test service baffle. The following figure vividly describes the role of Mock.

3. What Mock can do

As far as the Mock function is concerned, there are many applicable scenarios, but in practical projects, several categories that Mock is commonly used to solve are introduced. To sum up, the main ones are:

  • Interdependence between interfaces
  • unit test
  • third-party interface call

1. Front-end and back-end joint debugging

For example, you are a front-end page developer, and now you need to develop a function:
the next order, the interface of the payment page, according to the payment result, the payment is successful, the payment success page is displayed, the payment fails, and the payment failure page is displayed. To complete this function, you need to call the backend interface to display different pages according to the results returned to you. At this time, the back-end interface has not been developed. As a front-end developer, you can't wait for others to develop it. If you develop it, then you will only have to work overtime. In order to complete the task of synchronous development, at this time, you can pass the address and input parameters of the interface according to the provisions of the interface document, and then mock the different return interfaces of the interface to complete the front-end development tasks.

2. Unit testing

Since the unit test is only tested for the current unit, it requires that all internal or external dependencies should be stable. Using the mock method to simulate other units that depend on this unit can focus the test on the current unit function and exclude the outside world. factor interference and improve the test accuracy.

3. Third-party interface dependencies

When doing interface automation, sometimes you need to call third-party interfaces, but the interface services of other companies are not under your control. It is possible that the test environment provided by others is open for you today, but others are turned off and automated. Interface testing brings a lot of trouble. At this time, you can use mock to simulate the return data of the interface, such as simulating the return of various third-party exceptions.

4. Mock implementation

Although Mock is a substitute for dependent services, it does not need to construct and implement a complete service logic as it is. For example, now there is a service A that depends on service B, and Mock needs to be used to replace service B (make a fake service B).

Then, when we make a mock service, we actually make a simple service B. It does not need to implement the processing logic of the original service B load, as long as the corresponding return data can be given according to the processing logic that service A needs to return from service B.

At present, there are two main common service or interface protocols, one is RPC , and the other is HTTP/HTTPS . The principles of mocking are similar. Either modify the original service address to the Mock service address, or intercept the request Mock return value of the original service. In short, it is to construct a fake service to replace the original service.

5. Common solutions in the Mock market

If you don't want to build a mock solution yourself, there are many existing mock solutions available on the market.
Commonly used are: EasyMock, Mockito , WireMock, JMockit, Mock, Moco.

If your team's technical foundation is relatively weak, I recommend you to take a look at Mocothis solution. The official website is as follows:

https://github.com/dreamhead/moco/

Next, focus on the use of the Mock scheme under the Python system.

6. Using unittest.mock under Python

unittest.mock is a library for unit testing in Python. As the name suggests, the main function of this library is to mock something. Its main function is to replace the specified Python object with a mock object to achieve the behavior of the mock object.

It should be noted that in the Python2.x version, Mock needs to be installed separately

pip install -U mock

Since Python 3.3 and later, the mock has been merged into the unittest module, which is part of the unittest unit test. Just import it directly.

from unittest import mock

Official documentation:

https://docs.python.org/dev/library/unittest.mock.html

The most commonly used in the unittest.mock module is the Mock class.

The Mock class library is a class library specially used to make (forge) and modify (tamper) test objects in the unittest process, to avoid these objects from relying on external resources (network resources, database connections, other services and time-consuming) during the unit test process. too long, etc.)

Case:
The following scenario: payment is an independent interface, provided by other developers, according to the payment interface return status to display failure or success, this is the function you need to implement, the code is stored in the pay.py script:

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Mike Zhou
# @Email : 公众号:测试开发技术
# @File : pay.py

def zhifu():
    '''假设这里是一个支付的功能,未开发完
    支付成功返回:{"result": "success", "msg":"支付成功"}
    支付失败返回:{"result": "fail", "msg":"余额不足"}
    '''
    pass

def zhifu_statues():
    '''根据支付的结果success or fail,判断跳转到对应页面'''
    result = zhifu()
    try:
        if result["result"] == "success":
            return "支付成功"
        elif result["result"] == "fail":
            return "支付失败"
        else:
            return "未知错误异常"
    except:
        return "Error, 服务端返回异常!"

In the zhifu_statues method, the zhifu method is relied on, but since the interface of the zhifu payment method is developed by another colleague, under normal circumstances, you cannot control the progress of your colleague's development. Responsible for the zhifu_statues interface, so we can solve this problem by introducing Mock.

Unit test case code after the introduction of mock

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Mike Zhou
# @Email : 公众号:测试开发技术

import unittest
from unittest import mock
import pay

class TestZhifuStatues(unittest.TestCase):
    '''单元测试用例'''
    def test_01(self):
        '''测试支付成功场景'''
        # mock一个支付成功的数据
        pay.zhifu = mock.Mock(return_value={"result": "success", "msg":"支付成功"})
        # 根据支付结果测试页面跳转
        statues = pay.zhifu_statues()
        print(statues)
        self.assertEqual(statues, "支付成功")

    def test_02(self):
        '''测试支付失败场景'''
        # mock一个支付失败的数据
        pay.zhifu = mock.Mock(return_value={"result": "fail", "msg": "余额不足"})
        # 根据支付结果测试页面跳转
        statues = pay.zhifu_statues()
        print(statues)
        self.assertEqual(statues, "支付失败")

if __name__ == "__main__":
    unittest.main()

After the above code is introduced Mock, we can successfully complete the verification of the two scenarios of successful payment and abnormal payment. (actually you can add more)

mockThere is another way to do it in , through patchthe use of a decorator, patchas a function decorator that creates a mock for you and passes it to the decorated function.

Use mock.patch to achieve the following:

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Mike Zhou
# @Email : 公众号:测试开发技术


import unittest
from unittest import mock
import pay

class TestZhifuStatues(unittest.TestCase):
    '''单元测试用例'''

    @mock.patch("pay.zhifu")
    def test_001(self, mock_zhifu):
        '''测试支付成功场景'''
        # 方法一:mock一个支付成功的数据
        # pay.zhifu = mock.Mock(return_value={"result": "success", "msg":"支付成功"})
        # print(pay.zhifu())

        # 方法二:mock.path装饰器模拟返回结果
        mock_zhifu.return_value = {"result": "success", "msg":"支付成功"}

        # # 根据支付结果测试页面跳转
        statues = pay.zhifu_statues()
        print(statues)
        self.assertEqual(statues, "支付成功")

    @mock.patch("pay.zhifu")
    def test_002(self, mock_zhifu):
        '''测试支付失败场景'''
        # mock一个支付失败的数据

        mock_zhifu.return_value = {"result": "fail", "msg": "余额不足"}
        # 根据支付结果测试页面跳转
        statues = pay.zhifu_statues()
        self.assertEqual(statues, "支付失败")

if __name__ == "__main__":
    unittest.main()

Guess you like

Origin blog.csdn.net/weixin_59519449/article/details/123669873