Introduction to Airtest and scripting¶
By reading this section of the tutorial, you will know the following:
- Getting Started: Detailed Analysis of an Airtest Script
- How to call Airtest interface in Python script
- How to consult platform-related interface documents and call API
- Parameters of picture statement
Airtest is a cross-platform UI automation testing framework based on Python. It is based on the principle of image recognition and is suitable for games and apps.
Visit Airtest source address on Github for more information. Everyone is welcome to help to improve the project. You can submit a PR or submit a bug or suggestion in the issues page.
How to get started quickly¶
First, if you want to write Airtest scripts, you need to have basic Python syntax knowledge.Although the recording function provided by our AirtestIDE can also be used to simply record the script that can be played back according to the operating steps, but generally speaking, proficiency in Python syntax can help us write scripts that are more widely used and less error-prone.
If you are not familiar with Python syntax, there are many excellent Python tutorials on the web that you can learn, such as Liao Xuefeng's Python Beginners Tutorial.
For the installation, basic usage and simple examples of the Airtest project, please check the Quick Start section of the Airtest documentation page.
A simple .air script parsing¶
What is .air script¶
After downloading the Airtest IDE, the exclusive IDE for Airtest scripts, decompress it and click the "New Script" button. By default, you can create a script file with the suffix
.air. This is the exclusive suffix for Airtest scripts.
Let's open the folder of the newly created script. You can see that the
.air script file is actually an ordinary folder with a
.py file with the same name. When AirtestIDE executes the script, it actually executes the
.py file inside.In other words, although the Airtest script comes with a suffix name, it is still essentially a Python script and follows the Python syntax. We can freely
import other Python third-party libraries according to actual needs.
It is worth noting that there must be a
.py file with the same name in the
.air folder, otherwise running command such as
airtest run test.air on the command line will cause failure.
How to record Airtest scripts using AirtestIDE¶
Before watching this tutorial, if you have read our quick start tutorial, you should know that we need to connect a device before recording the script.This device can be an Android phone, a Windows window, or an iOS device, etc. Please refer to our Device Connection document and connect a device in AirtestIDE as needed.
After successfully connecting the device, you can record the script content you need according to the two functions described in the Airtest Script Recording document: manual key recording and automatic recording.
At the same time, you can use Python's judgment, loop and other syntax to make the script achieve more complex functions and complete the requirements of automated testing.
Airtest script example¶
This is a simple script example. In AirtestIDE, the display effect is shown in the figure:
In fact, the script content is such a Python script (
Template (xxxx) is automatically rendered into an image in AirtestIDE):
# -*- encoding=utf8 -*- __author__ = "user" # Initialize the environment from airtest.core.api import * auto_setup(__file__) start_app("org.cocos2d.blackjack") # Simulated click touch(Template(r"tpl1556019871196.png", record_pos=(0.204, -0.153), resolution=(1280, 720))) sleep(2) swipe(Template(r"tpl1561952588795.png", record_pos=(-0.067, 0.134), resolution=(1280, 720)), vector=[0.2783, 0.0374]) wait(Template(r"tpl1561952704834.png", record_pos=(-0.186, -0.093), resolution=(1280, 720))) keyevent("BACK") # Some simple logical judgments if exists(Template(r"tpl1559100640980.png", record_pos=(-0.33, -0.105), resolution=(1920, 1080))): text("test") # assertion assert_exists(Template(r"tpl1561952631660.png", record_pos=(-0.373, -0.108), resolution=(1280, 720)), "验证内容存在") stop_app("org.cocos2d.blackjack")
Next we explain in detail what each line of code in the example script does.
Initialize the environment¶
First of all, just like an ordinary Python script, we need to write
from airtest.core.api import * at the very beginning of the code file, and import the main API of Airtest in order to use these API in subsequent scripts.
auto_setup is an interface used to initialize the environment, the interface documentation is here.It accepts 4 parameters, we can set the path where the current script is located, specify the device to run the script, set the default log path, and set the script parent path.
auto_setupdoes not pass any parameters, Airtest will read the parameters passed in the command line at runtime to initialize the environment.
- When creating a script in AirtestIDE, the default generated code is the simplest initialization code
auto_setup (__file__), which means that the script file is passed as the script path, and other parameters are read by default.
- Please try to call the
auto_setupinterface during script initialization as much as possible to ensure that the environment is initialized as accurately as possible and log files are generated, otherwise log content is not generated by default.
There are two forms of running scripts on the command line. The parameters on the command line include
log, etc :
- Example of running Airtest script from the command line:
> airtest run untitled.air --device Android:///mobile device number --log log/。
For more information on running scripts using the command line, please refer to Documentation。
- When using AirtestIDE to run the script, a usable command line will be automatically generated in the "Log view window" for your reference.
"D:\AirtestIDE-path\AirtestIDE" runner "D:\script-path\untitled.air" --device Android://127.0.0.1:5037/5PZTQWQOGES8RWUG --log "C:\Users\username\AppData\Local\Temp\AirtestIDE\scripts\aa8c71acdfa70c3068b862cb42ffb8dc"
- If a device parameter like
--device Android: ///is passed in the command line at runtime, the script will automatically connect to the corresponding device during initialization, and no additional code is required to connect.
- If the device is not connected during initialization, you can use the
connect_deviceinterface in the script code to connect the device.
- Airtest supports simultaneous connection of multiple devices in a single script. Use the
set_currentinterface to switch between multiple devices, and the
device ()interface can get the currently used device. Use this interface to easily write the use case code for interaction between multiple phones, such as using two phones to add friends to each other.
Airtest, as an automated testing framework, simulates human operations. Common interfaces are:
touchClick on a location. It can set parameters such as clicked position, number of times, duration of holding
swipeSwipe from one position to another
textCall input method to input specified content
keyeventEnter a key response, such as Enter, Delete
waitWaiting for a specified picture element to appear
snapshotTake a picture of the current picture
Please see this documentfor core API.The API that appear in this documentation page are cross-platform API. Since we have imported all the interfaces in
airtest.core.api in the first line of the code, these API can be implemented directly in the code. Like this:
from airtest.core.api import * touch((x, y))
In many interfaces, the picture object
Template is supported as a parameter. At runtime, the picture will be clicked on the screen, similar to this:
# Equivalent to touch ((x, y)), (x, y) is the center point of the picture touch(Template(r"tpl1556019871196.png", record_pos=(0.204, -0.153), resolution=(1280, 720)))
Among them, the
Template object is a picture class. Airtest will first try to find a position in the current screen that can match this picture. If it finds it, it will click on this coordinate. If it cannot find it, it will throw a recognition exception .We will introduce the
Template picture class in more detail later.
The interfaces in the
airtest.core.api mentioned just now are cross-platform, but the specific platforms supported by each interface may be different.For example, the install interface is only
Android in the
Supported Platform column of the document, which means that when a
Windows device (a certain Windows window) is connected, this interface cannot be used to install applications.
For details on the support of the interface under the platform, please refer to
Platform-Related API in the documentation directory.Find the corresponding interface according to the specific platform. At the same time, you can also find that there are some unique interfaces that can be called under different platforms, for example, under Android platform:
from airtest.core.api import * # The touch interface on the Android platform supports additional parameter duration to control the duration of the screen tap. # Check the touch method included in Android in airtest.core.android.android for more parameter information touch((600, 500), duration=1) # In Android, there is a platform-specific interface list_app that can list all installed applications dev = device() # Get the current device object first, where dev is an Android object print(dev.list_app()) # Then you can call the platform-specific interface
Assertion is very important in the unit test code, so it is recommended to use assert statements in our script to determine whether the current state of the tested application is the state we expected.
Airtest provides two interfaces,
assert_not_exists, to assert that an image exists or does not exist in the current screen.
At the same time,
assert_not_equal statements are provided to assert that the two values passed in are equal or unequal.
How to use Airtest in a Python script¶
When creating a new script, AirtestIDE can also directly create a
.py script file, but before the creation, a setting window will pop up asking you to fill in some specified parameters.
After we understand the
auto_setup interface, we will know that these parameters are used to pass to it, and then initialize the Airtest operating environment. Therefore, the initialization code for a pure
.py script could look like this:
from airtest.core.api import * from airtest.cli.parser import cli_setup if not cli_setup(): auto_setup(__file__, logdir=True, devices=[ "Android:///?cap_method=javacap&ori_method=adbori", ]) # do something # touch((x, y))
The above code means that when using
python xxx.py to run this file without any command line parameters, the interface
auto_setup is automatically used to initialize airtest related parameters.In this way, you only need to fill in the specified parameters when writing the py script, and you can directly use the
python xx.py instruction to run the script.
At the same time, the original traditional command line operation mode
airtest run xx.air –-devices Android:/// is also not affected. As long as the script detects the command line parameters passed in (that is, the
if not cli_setup () judgment in the code), the command line parameters are still used to initialize the Airtest environment .
Of course, everyone who is proficient in API can also call the Airtest API in their own Python scripts according to actual needs, which is the same as using the normal Python third-party library method.
Introduction to picture class-
In AirtestIDE, statements with screenshots can show the corresponding pictures, so everyone knows what screenshots this statement uses.In the editor, you can click the
Image/Code Mode Switch in the right-click menu to switch the code in the current editing window to a plain text code. Then we will see a
touch (picture) statement. It might become like this:
touch(Template(r"tpl1556019871196.png", record_pos=(0.204, -0.153), resolution=(1280, 720)))
Template is the image class encapsulated by Airtest. When running, it will first read this image, then find the coordinate point that best matches this image in the current screen, and then execute
The image captured in AirtestIDE comes with 3 parameters by default, the first parameter is the picture name, the second
record_pos records the location where the image was taken, and the third
resolution records the resolution of the current screen when taking a picture.
- The role of
record_posis to allow Airtest to search near the location during recording when playing back the script. If no picture is found that meets the conditions, then the search range is expanded to the entire screen. This can improve the speed and accuracy of finding pictures.
resolutionrecords the resolution of the screen. If the script is played back on different devices, Airtest will scale the resolution of the current screen in proportion to facilitate cross-resolution matching of pictures.
- Although using the image path to initialize a
Templateclass, you can run the code. But in order to be able to adapt to more resolution devices and improve the image search rate, it is recommended that you fill in the parameters as much as possible. The images captured by AirtestIDE will automatically generate corresponding parameters. If you are not satisfied with the captured picture, you can use the Photo Editor function to further modify the picture.
In addition to the above three parameters, the picture also supports more parameters, such as modifying the image recognition threshold, click position, and whether to modify the gray level during operation. Among them, the
threshold value of image matching is closely related to the success rate of image recognition.Please read document for more details.
Global configuration items of image recognition¶
In the previous section, we introduced the parameters of the image template class
Template. When we modify those parameters, only the corresponding image will take effect. For example:
In this line of code, we set the recognition threshold
threshold of an image to 0.9, which means that when the reliability of the recognition result is greater than or equal to 90%, we think that the image recognition match is successful this time. This is a fairly strict setting.
If we want to be able to extend this setting to all pictures in the entire script, and we don't want to modify the code of each picture one by one, we can consider modifying the global configuration of Airtest to achieve this requirement:
from airtest.core.api import * # airtest.core.api contains a variable named ST, which is a global setting ST.THRESHOLD = 0.8 # If the image threshold is not specified, 0.8 in ST.THRESHOLD is used by default touch(Template(r"tpl1532588127987.png", record_pos=(0.779, 0.382), resolution=(407, 264))) # If you manually specify the threshold of the picture, the 0.6 set by the picture shall prevail touch(Template(r"tpl1532588127987.png", record_pos=(0.779, 0.382), resolution=(407, 264), threshold=0.6))
There are more customizable global configuration items, please check the Global Configuration of Scripts document for more configuration item introductions.
After reading the tutorial in this section, I hope everyone can have a deeper impression of the Airtest script. It can not only generate recording scripts with a few mouse clicks on AirtestIDE, but also can combine Python and use programming skills to write code to achieve more complex requirements .
Therefore, using Airtest is the same as using other third-party Python libraries. You need to read the Airtest API documentation. And the source code on Github is clear and easy to understand. Welcome to read the source code or communicate with us.