This is the 29th day of my participation in the August More Text Challenge

1. Introduction to simulation test

In the testing process, data flow is often related to the complexity of the system, the more complex the function of the system, the more complicated the process of data flow. Sometimes there will be dozens of subsystems, whose upstream and downstream services are interdependent, making the testing process very complicated and lengthy. For example, e-commerce website shopping, need to go through the selection of goods, add to the shopping cart, pay the order, receive points, refund links, interlocking, indispensable. An order can be paid only if it has been generated, and an order can be generated only if it has been selected

For such scenarios, it is more efficient to use simulated data instead of upstream processes when testing an intermediate link.

2. Use scenarios of simulated tests

The simulation test is mainly used in the following scenarios:

Interdependent function call procedures

Testing between interdependent upstream and downstream services can accurately test specific environments or functions by simulating data sources.

When the test environment is not stable or in the development stage, the simulation interface can be used to return relevant results to accelerate the test progress. Services, interfaces, and specific environments can all be simulated.

3. Introduction to Mock objects

3.1 Mock Object Definition

class Mock(CallableMixin, NonCallableMock):
    pass
Copy the code
class CallableMixin(Base):
​
    def __init__(self, spec=None, side_effect=None, return_value=DEFAULT,
                 wraps=None, name=None, spec_set=None, parent=None,
                 _spec_state=None, _new_name='', _new_parent=None, **kwargs):
        pass
Copy the code
class NonCallableMock(Base):
​
    def __init__(
            self, spec=None, wraps=None, name=None, spec_set=None,
            parent=None, _spec_state=None, _new_name='', _new_parent=None,
            _spec_as_instance=False, _eat_self=None, unsafe=False, **kwargs
        ):
        pass
Copy the code

Several parameters are explained in detail here

Spec: Mock object properties that can be set at initialization. They can be strings, lists, or objects. Of course, you don’t have to

Wraps: If this parameter is set, the result of the call is passed to the Mock object, and the access to the Mock attributes returns the wrapped object attributes. An attribute error is raised if you attempt to access a non-existent attribute.

Spec_set: This parameter is a strict spec and can only be passed parameters of the set type.

Return_value: Sets the expected return value to the Mock object, which can be used later in the test logic judgment.

3.2 Code Examples

3.2.1 Calculate the sum of the two numbers

Class SimpleCalculator(object): def sum(self, num1: int, num2: int) def sum(self, num1: int, num2: int) Class SumTest(unittest.testCase): def test(self): s = SimpleCalculator() num1 = 10 num2 = 30 sum_result = mock.Mock(return_value=40) s.sum = sum_result self.assertEqual(s.sum(num1, num2), 40) if __name__ == '__main__': sum_test = SumTest() sum_test.test()Copy the code

result:

Testing started at 12:00 ... D: \ \ software \ python python. Exe "D: \ software \ PyCharm 2019.3.4 \ plugins \ python \ helpers \ pycharm_jb_unittest_runner py" - a path D:/python_record/mock_01.py Ran 1 test in 0.002s OK Launching unittests with arguments python -m unittest D:/python_record/mock_01.py in D:\python_recordCopy the code

3.2.2 GET Request status code Test

#! /usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2021/8/8 11:19 # @Author : ywb # @Site : # @File : mock_02 # @Software: PyCharm import requests from unittest import mock import unittest class Client(object): Def send_request(self, url: STR) -> STR: """ def send_request(self, url: STR) -> STR:" Get (url) return response.status_code def visit_baidu(self) -> STR: "" Response status code """ return self.send_request('https://www.baidu.com') class TestClient(unittest.testCase): def test_success_request(self): Mock(return_value='200') client = client () client.send_request = Success_send self.assertEqual(client.visit_baidu(), '200') def test_fail_request(self): Mock(return_value='403') client = client () client.send_request = Success_send self.assertEqual(client.visit_baidu(), '403') if __name__ == '__main__': unittest.main()Copy the code

result:

Testing started at 12:01 ... D: \ \ software \ python python. Exe "D: \ software \ PyCharm 2019.3.4 \ plugins \ python \ helpers \ pycharm_jb_unittest_runner py" - a path  D:/python_record/mock_02.py Launching unittests with arguments python -m unittest D:/python_record/mock_02.py in D:\python_record Ran 2 tests in 0.002s OK Process finished with exit code 0Copy the code

Here’s an explanation of the above code. The logic here is that the object we are going to test is the send_request() method, which has not yet been developed. But we know that this method returns the response code for the GET request. Based on this information we run simulations.

TestClient extends unitTest. TestCase to facilitate use case organization and management as well as assertion judgment. TestClient has two test cases for send_request(). Test_success_request () tests whether the response code for a successful request is 200. The test_fail_request() method tests whether the response code is 403 when the request fails.

The test_SUCCESS_request () method is used as an example.

success_send = mock.Mock(return_value='200')
Copy the code

This is a mock object whose property return_value is’ 200 ‘.

client.send_request = success_send
Copy the code

This sentence is a mock object set to replace send_request, the real function we’re testing. In other words, the send_request () method is now undeveloped. We now use mock objects instead of the send_request() method. The mock object is equivalent to the send_request() method. So while we look at the send_request() method being called, the logical behavior is entirely from the mock object, not inside the send_request() method. So the return value we finally get is the return value that the mock object has already set.

4 Summary of Mock object usage steps

(1) Find the function to replace

(2) Instantiate the Mock object and set its properties or behavior. Both examples in this article set their return values

(3) Replace the function or object you want to replace

(4) Use UnitTest for assertion tests