Airtest API refined assertions

Posted by Jeroen_nld on Sun, 02 Jan 2022 20:29:31 +0100

Last review: Global variable of Airtest

Based on
python3.8;airtestIDE1.2.11;airtest1.2.2;pocoui1.0.83

Assertions are common to every test framework and can be understood as test point verification. Airtest has four assertion API s, which support all Android, iOS and Windows platforms, respectively:

  • assert_exists: verify that the picture exists

  • assert_not_exists: the inspection picture does not exist

  • assert_equal: judge whether the expected value is equal to the actual value

  • assert_not_equal: judge that the expected value is not equal to the actual value

Source code analysis

Let's start with assert_exists() source code (if you don't want to see the source code, you can directly jump to the following demonstration example):

#File location: your_python_path/site-packages/airtest/core/api.py
def assert_exists(v, msg=""):
    try:
        pos = loop_find(v, timeout=ST.FIND_TIMEOUT, threshold=ST.THRESHOLD_STRICT or v.threshold)
        return pos
    except TargetNotFoundError:
        raise AssertionError("%s does not exist in screen, message: %s" % (v, msg))

parameter
v: Picture object to judge
msg: assertion description information will be displayed in the report

The source code is very simple. It mainly calls loop_find(), which was found in Airtest source code analysis -- the overall process of image recognition After talking about it, I won't start here. I just mention two points:
1.timeout=ST.FIND_TIMEOUT, the timeout for finding a map, the default is 20s. Global variables have been mentioned before. See the details Global variable of Airtest
2.threshold=ST.THRESHOLD_STRICT or v.threshold means: if the global variable st.threshold is configured_ Strict, then take its value; otherwise, take the threshold value in the image Template instance (which will be demonstrated later in the example)
The overall logic is to find and return the coordinates of the picture; If the picture is not found, loop_find() will report a TargetNotFoundError error error. Catch it with except ion and throw an AssertionError instead.

Let's continue to look at assert_not_exists() source code:

def assert_not_exists(v, msg=""):
    try:
        pos = loop_find(v, timeout=ST.FIND_TIMEOUT_TMP)
        raise AssertionError("%s exists unexpectedly at pos: %s, message: %s" % (v, pos, msg))
    except TargetNotFoundError:
        pass

And assert_exists() on the contrary, if it matches the picture, it will throw the error of AssertionError; If no match is found, loop_find() will report a TargetNotFoundError error error, catch it with except, and then pass to make it not report an error.

assert_equal() source code:

def assert_equal(first, second, msg=""):
    if first != second:
        raise AssertionError("%s and %s are not equal, message: %s" % (first, second, msg))

parameter
first: expected value
second: actual value
msg: assertion description information will be displayed in the report

The code is just two lines. It is very simple. If the expected value is inconsistent with the actual value, an assertion error will be thrown.

assert_ not_ Source code:

def assert_equal(first, second, msg=""):
    if first == second:
        raise AssertionError("%s and %s are not equal, message: %s" % (first, second, msg))

If the expected value is consistent with the actual value, an assertion error is thrown.

Example demonstration

# -*- encoding=utf8 -*-
__author__ = "Test engineer station"

from airtest.core.api import *

# adopt IDE Grab official account Icon
icon70 = Template(r"tpl1637984484238.png", record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# I copied the picture above, just threshold If it is changed to 1, the actual matching degree cannot reach 100%
icon100 = Template(r"tpl1637984484238.png", threshold=1, record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# Assert default threshold=0.7 The picture exists through
assert_exists(icon70, "Test engineer station icon exists")
# Assert threshold=1 The picture of does not exist and cannot be passed
assert_exists(icon100, "Test engineer station icon similarity 1 exists")
#Assert that the picture with threshold=1 does not exist, pass
assert_not_exists(icon100, "Test engineer station icon similarity 1 does not exist")

After execution, it fails at the second assertion and the last assertion is not executed. Let's see the following report:

Line 1: the first assertion passed
Line 2: the second assertion failed
Line 3: execution failed, and detailed error message will be displayed

There is a problem. After an error is reported, my subsequent use cases are not executed. I hope that the assertion fails but can continue to be executed. Just add try. If an error is reported, only the error information will be printed. The modified code is as follows:

# -*- encoding=utf8 -*-
__author__ = "Test engineer station"

from airtest.core.api import *

# adopt IDE Grab official account Icon
icon70 = Template(r"tpl1637984484238.png", record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# I copied the picture above, just threshold If it is changed to 1, the actual matching degree cannot reach 100%
icon100 = Template(r"tpl1637984484238.png", threshold=1, record_pos=(-0.376, -0.787), resolution=(1080, 2340))
# Assert default threshold=0.7 The picture exists through
assert_exists(icon70, "Test engineer station icon exists")
# Assert threshold=1 The picture of does not exist and cannot be passed
try:
    assert_exists(icon100, "Test engineer station icon similarity 1 exists")
except Exception as e:
    print(str(e))
#Assert that the picture with threshold=1 does not exist, pass
assert_not_exists(icon100, "Test engineer station icon similarity 1 does not exist")

Execute again, and all the use cases can be executed. See the following report:

The first assertion that threshold=0.7 exists is passed
The second assertion that threshold=1 exists fails. Click to see the detailed error message on the right

The third assertion that threshold=1 does not exist passes

Continue to look at two other assertion examples:

# -*- encoding=utf8 -*-
__author__ = "Test engineer station"

import re
from airtest.core.api import *
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

# The name of the official account is taken as the test engineer's station.@,I don't know why there are so many@
name = poco("com.tencent.mm:id/a_g").get_text()
# take@The former text, the real name of the official account: Test Engineer's station.
name = name[:-1]
# The official account is asserted as "test engineer". adopt
assert_equal(name, "Test engineer station", "The name of the official account is correct.")

# Take and introduce the following original content, namely: 129 original content  36 A friend pays attention 
num_str = poco("com.tencent.mm:id/a5m").get_text()
# Regular search for the first value, 129
searchObj = re.search(r'(\d+)', num_str)
count = searchObj.group(1)
#Assert that the original article is not 999, it is 129, so it passed
assert_not_equal(int(count), 999, "The official account number is not 999.")

After running, see the following report:
The first assertion determines equality by

The second assertion determines the inequality through

So for the implementation of poco framework, can you assert the existence or non existence of elements like the picture? Using assert_equal(),assert_not_equal() is also possible. First, the wait() of poco itself returns coordinates when judging the existence of an element. We need to encapsulate it twice to return True if it exists and False if it does not exist. Then we can compare assertions with Boolean values.

# -*- encoding=utf8 -*-
__author__ = "Test engineer station"

from airtest.core.api import *
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

def my_wait(poco_obj):
    """
    Pass in a poco Object to determine whether it exists and return True,No return False
    """
    if poco_obj.wait():
        return True
    return False

name = poco("com.tencent.mm:id/a_g")
assert_equal(my_wait(name), True, "Test Engineer name element does not exist")

So, after execution, my_wait() returns True, which is equivalent to assert_equal(True, True, "test engineer name element exists")
Look at the report:

 

 

 

---------------------------------------------------------------------------------

Pay attention to WeChat official account mobile phone and check more.

Topics: Testing