This article comes from the official official account of the project: “AirtestProject” copyright statement: reprint is allowed, but reprint must retain the original link; Do not use for commercial or illegal purposes

preface

Have you ever encountered these scenes?

The case failed because of network fluctuations? At the last minute, the system pops up a harassing text message blocking a key location, and the script just doesn’t get there? Or did the script accidentally fail because the alarm went off on your phone?

I believe that many students will think of using code to handle these exceptions, because we can’t always watch the script running, and then manually handle the exception when it occurs, but the code can help us achieve automatic handling of exceptions.

But a lot of you, because you’ve copied and pasted a lot of code to handle exceptions, you’ll see exception handling code all over your use case scripts. So today we will teach you how to use decorators to handle exceptions and implement case retries without changing the original use case script

(PS: already can use the decorator classmate, can directly pull to the end of the article to view the practical application oh ~)

1. Decorator definition

Decorators can add functionality they don’t have without changing the code of the original function. Simply put, a function that modifies the function of another function. By using decorators, we can make a function more powerful and make our code shorter and cleaner.

2. Get started with decorators with a simple example

First, we define the test function, which prints out the following statement: This is a generic function.

The function is defined as follows:

Def test(): print(" this is a normal function ") test() >>Copy the code

If I had to print it twice, how would you do that? Print (); for (); for ();

Def test(): for I in range(2): print(" this is a normal function ") Print (" this is a bland function ") test() >>> output: # This is a bland function # This is a bland functionCopy the code

Suppose we want to repeat print twice, but we don’t want to change the code of the original function. What do we do? Yes, we can define decorators to do this:

Def loop(func): def wrapper(*args, **kw): for I in range(2): func(*args, **kw) return wrapperCopy the code

As you can see, we didn’t change the function, but we changed the function with the decorator, which helps us repeat the function twice.

So let’s go ahead and look at how to use decorators:

Method 1: Call a method without the syntax sugar @ symbol:
Loop (test)() >>> output: # This is a bland function # This is a bland functionCopy the code
Method 2: Use the syntax sugar @ symbol to call a method:
@loop def test(): print(" this is a bland function ") test() >>> output: # This is a bland function # This is a bland functionCopy the code

Decorators can actually be stacked multiple times, such as:

@loop @loop def test(): print(" this is a normal function ") test() >>> output: # This is a normal function # This is a normal function # This is a normal function # This is a normal function # This is a normal function # This is a normal function # This is a normal function # This is a normal function # This is a normal functionCopy the code

Now, one of the things that’s interesting about this is, guess what, if we stack the decorators three times, what happens? (Students who see here can think about it first, and then start to run to see if you expect the result)

@loop @loop @loop def test(): Print (" this is a normal function ") test() >>> output: # This is a common function # this is a common function # This is a common function # This is a common function #Copy the code

As you can see, instead of 6 times, the output is 8 times. Why? Let’s analyze it in the ordinary way of calling:

This code is equivalent to: loop(loop(loop(test)))(), with the outermost layer actually called. When you call multiple times, the decorator loops through the function with the decorator itself as an argument, so the actual number of executions is 2× (2×2), or 8 times.

If you need to specify how many times to execute, you can do so by passing an argument to the decorator as follows:

def loop(times): def decorator(func): def wrapper(*args, **kw): for i in range(times): func(i, **kw) return wrapper return decorator @loop(6) def test(num): Print (f" {num+1} run ") test() print(f" {num+1} run ") # This is a bland function, first run # this is a bland function, second run # this is a bland function, third run # this is a bland function, fourth run # this is a bland function, Run # 5 this is a mundane function, run # 6Copy the code

3. Apply decorator to implement automatic rerunning of Airtest script failure

For example, you are running an automated test script and suddenly the device’s alarm clock goes off. The interface of the alarm clock covers the button you are trying to operate, causing the script to fail. You have no choice but to turn off the alarm and run the script again.

In this test scenario, how do we apply decorators to help us resolve the alarm clock exception and then rerun our test case? The answers are as follows:

We created a new decorator that will try to run our use case. If the alarm clock is blocked, it will automatically handle the alarm clock and run the use case again. It will print out the result of the run as follows:

As you can see, we added a decorator without changing the use-case function, so that the original function can handle exceptions and reruns. This is the beauty of the decorator function.

Finally, to borrow the words of some unknown big guy: don’t think you can understand it just by looking at it, just run the code, and everything is suddenly clear.


Airtest website: airtest.netease.com/ Airtest tutorial website: airtest.doc.io.netease.com/ build enterprise private cloud service: airlab.163.com/b2b

Airtest official Q group: 654700783

Ah, so serious all see here, help in the left side of the article click like and collection, give me a support, ash often thanks ~