current position:Home>Interface testing uses Python decorators

Interface testing uses Python decorators

2022-05-15 05:49:19Highbury simple

Write the interface case when , Sometimes you need to be right about cae Do some common operations , The most typical scenes are : obtain case execution time 、 Print log etc. .

Is there a way to focus on common operations so as to avoid them in every case Write the same code in ( Such as : Every case All need to write the same code to get the execution time ) Well ?

Python The decorator can do this .

The decorator can be understood in this way , The decorator decorates the objective function with closures ( The reference of the objective function as the external function of the closure ), That is, before executing the objective function 、 Then execute some specified code to complete the desired business logic .

Concepts always seem obscure , Go straight to grammar .

First step , Let's first look at the syntax of closures :

def outer(a): b = 10
    
    # inner It's an internal function 
    def inner(): #  In the inner function   We use the temporary variable of the external function 
        print(a + b) #  The return value of the outer function is a reference to the inner function 
    return inner

The second step , Let's look at the syntax of the decorator version of closures

There is only one difference between... And the above example : The outer part of the reference function is an integer a, This is a function reference ( The reference of the function is Function name ).

#  The decorator uses the closure principle : An inner function is defined inside the outer function , The inner function uses the local variables of the outer function , And the outer function returns the reference of the inner function 
def outer(target):   #  Decorator function   Pass in an object function that you want to decorate   quote , Use... In the inner function .
  
b = 10 c = 1 d = 5 # inner It's an internal function def inner(): print(b + c) # Parameters passed in by external functions target, Is the reference of the objective function you want to decorate target() # The objective function is actually executed here , Want to decorate this function , So do something before and after the function is executed , The specific operation depends on the business logic print(c + d) # The return value of the outer function is a reference to the inner function return inner

Be careful :target Just a reference to a function ( The reference points to the location of the function in memory ), Not execute . belt () when ( target()  ) Will execute the function .

The last step , Take another look at the grammar of the decorator :

@decorator def test_01():

So it can be concluded that : Decorator decorator Is an external function of a closure , namely outer() ( Decorator It's a function , namely External functions of closures ), Decorated function test_01 Is the parameter passed in by the closure , namely target.

for instance :

Take the time-consuming statistics of each interface request as an example .

Decorator (decorat.py):

import time def time_consume(func): def inner(): time_start = time.time()  #  Take the time before the objective function starts 
        print("\n The time before the interface request is ", time_start) func() time_end = time.time()  #  Take the time after the end of the objective function 
        print(" The time after the interface request is ", time_end) t = time_end - time_start  #  Calculate how long the objective function takes to execute 
        print(" The interface takes :", t) return inner

Interface (test_case.py):

import requests import decorat @decorat.time_consume def test_demo(): res = requests.get("https://www.baidu.com") assert res.status_code == 200

effect :

Let's summarize the whole process of this example :

''' @decorat.time_consume It's actually executing : test_demo = @decorat.time_consume(test_demo)  Because programming languages are parsed and executed from right to left , So what happens to this code is : 1 、 Put the objective function test_demo( It's a variable name , There is a reference to the objective function )  Pass in time_consume function , By parameter func receive , At this time func It is also a reference to the objective function  func and test_demo Point to the same function object  2 、time_consume Function defines the inner function inner, stay inner Call inside func,  This uses the principle of closure ( Closure principle : When the outer function ends, it will bind its own reference to the inner function ), When the outer function ends, it will put func Bound to inner functions , For inner functions  3、  At the end of the outer function, reference the inner function you created inner Return to test_demo receive ,  At this time test_demo It is not the original objective function ,test_demo It can be understood as a inner The instance object of the function , Re execution test_demo()  In fact, it was executed inner() An object of  4、  Re execution test_demo()  When   Actually inner() :  Execute fetch time first , Print   After performing func(), Is to execute the objective function , The perform test_demo() In itself   Finally, take the time again , Print the results  '''

Great vernacular version :

 In fact, just a word : 
The decorated function is passed in as a parameter of the decorator's external function , Execute the decorated function in the internal function of the decorator , Plus other
code snippet A,
 In addition to having its own logic , It also has the inner function of the decorator  code snippet A The logic of . So that there is no need to modify the decorated function ,

This enhances the function of the decorated function .

Let's look at two scenarios .

first : The decorated function has parameters

General interface test test_case I don't want to mention a function in the above example , But as a method of a class , such as :

The operation report is wrong , The error log means inner() need 0 Input parameters , But it was introduced 1 individual . The error report proves the conclusion mentioned above

as a result of test_demo() With parameters self, and inner() No input parameters defined . How to solve it , to inner() Define a variable input parameter ? Let's start with the second question , Finally, let's prove our conjecture .

the second : The decorated function has a return value

The problem arises , The return value printed out is None, because inner() There are no variables to receive test_demo Return value of and return ? Speculation with the first question , Let's change the code .

do 2 There are two changes :

1、inner() Define variable input parameters

2、inner() To define variables test_demo Return value of and return The variable

test_case As a class method, the problem is solved .

The printed value can also be returned as normal .

The modified decorator can be used as a general template to define the decorator , Basically, it can be decorated with various functions .

def decorat_demo(func): def inner(*args, **kwargs):   # inner() Receive variable parameters 
        # any code before #  Operations before defining the objective function 
        #  Call target function 
        res = func(*args, **kwargs)  #  Define the variable to receive the return value of the objective function 
        # any code after #  Operation after defining the objective function 
        return res     #  Return the return value of the objective function 
    return inner

 

copyright notice
author[Highbury simple],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/135/202205142240455358.html

Random recommended