PDL Driver

This section aims to explain how the Property Definition Language driver PDL of Kea is designed and implemented.

Functional Design of PDL Driver

The PDL driver is a driver that interacts with the device during property-based testing where users execute properties on the device. The PDL driver includes PDL drivers for Android devices (based on uiautomator2) and HarmonyOS devices (based on hmdriver2).

Note

The design of the PDL driver references uiautomator2 and hmdriver2.

uiautomator2: https://github.com/openatx/uiautomator2

hmdriver2: https://github.com/codematrixer/hmdriver2

The usage syntax of the PDL driver is d(Selector(**kwargs)).attr(args). Here Selector(**kwargs) is the control selector, which specifies the properties of the control in dictionary form, such as resourceId and className in Android, and id and bundlename in HarmonyOS. attr refers to the operations on the selected control, including click, longClick, etc. The args in attr(args) are the parameters passed to the method. For example, in input_text("Hello"), the string “Hello” is passed as the input.

Our PDL driver is essentially an intermediary layer between Kea and the corresponding automation testing tools (uiautomator2, hmdriver2), with syntax consistent with the target testing tools. It is mainly used to perform some additional operations, such as saving current events, taking screenshots, etc., to facilitate Kea’s access to the corresponding operational data and generate error reports.

Implementation of the PDL Driver for Android Devices

The PDL driver for Android devices is implemented through uiautomator2. It is mainly used to enable interaction between the properties written by users and the application.

The Android PDL driver inherits from the Driver class of uiautomator2. A simplified implementation of some Android PDL in Python style is as follows:

class Android_PDL_Driver(Uiautomator2.Driver):

    def __call__(self, **kwargs: Any) -> Ui:
        return Ui(self, Selector(**kwargs), droidbot=self.droidbot)

    def set_droidbot(self, droidbot:DroidBot):
        self.droidbot = droidbot

    ...

class Ui(Uiautomator2.UiObject):
    def __init__(self, session:Android_PDL_Driver, selector: Selector, droidbot:DroidBot):
        super().__init__(session, selector)
        self.droidbot=droidbot

    def click(self, offset=None):
        self.droidbot.device.save_screenshot_for_report(event_name="click", event = self)
        print(f"Property Action: click({str(self.selector)})")
        super().click(offset)

    ...

    def child(self, **kwargs):
        return Ui(self.session, self.selector.clone().child(**kwargs), self.droidbot)

    def sibling(self, **kwargs):
        return Ui(self.session, self.selector.clone().sibling(**kwargs), self.droidbot)

The analysis of the core functionality of PDL is as follows:

1. 使 PDL 能按 d(Selectors(**kwargs)).attr(*args) 的方式调用:

    def __call__(self, **kwargs: Any) -> Ui:
        return Ui(self, Selector(**kwargs), droidbot=self.droidbot)

    python的函数是一等对象,定义driver对象的 __call__ 魔术方法可以让对象可以通过函数的方式调用,完成形如d(**kwargs)的调用方法。

    UI是uiautomator2中的UI对象类,可以调用 .attrs() 方法。通过定义驱动的 __call__ 返回一个UI对象可以完成如此的调用。

2. 使PDL驱动能和kea主体的其他功能进行资源共享:

    kea调用本PDL类的set_droidbot方法设置Droidbot,让本类可以访问droidbot。以此,需要的资源可以通过调用droidbot的方法返回给kea。

3. 发送资源到kea。

    def click(self, offset=None):
        self.droidbot.device.save_screenshot_for_report(event_name="click", event = self)

    在执行点击操作的时候,调用droidbot中的对应方法保存截图和当前的事件操作。其他的控件操作方法定义类似。

4. 让PDL能使用uiautomator2中的.child等相对控件获取方法。

    定义 child、 sibling方法内容,根据功能返回对应的相对控件。

Implementation of the PDL Driver for HarmonyOS Devices

The PDL driver for HarmonyOS devices is implemented through hmdriver2. It is mainly used to enable interaction between the properties written by users and the application.

The HarmonyOS PDL driver inherits from the Driver class of hmdriver2. A simplified implementation of some HarmonyOS PDL in Python style is as follows:

class HarmonyOS_PDL_Driver(hmdriver2.Driver):

    def __call__(self, **kwargs: Any) -> Ui:
        return Ui(self, **kwargs)

    def set_droidbot(self, droidbot:Droidbot):
        self.droidbot = droidbot


class Ui(hmdriver2.UiObject):
    def __init__(self, session:HarmonyOS_PDL_Driver, **kwargs) -> None:
        client = session._client
        droidbot = session.droidbot
        self.droidbot = droidbot
        super().__init__(client, **kwargs)

    def click(self, offset=None):
        self.droidbot.device.save_screenshot_for_report(event_name="click", event = self)
        super().click()
1. 使 PDL 能按 d(Selectors(**kwargs)).attr(*args) 的方式调用:

    def __call__(self, **kwargs: Any) -> Ui:
        return Ui(self, **kwargs)

    python的函数是一等对象,定义driver对象的 __call__ 魔术方法可以让对象可以通过函数的方式调用,完成形如d(**kwargs)的调用方法。

    UI是hmdriver2中的UI对象类,可以调用 .attrs() 方法。通过定义驱动的 __call__ 返回一个UI对象可以完成如此的调用。

2. 使PDL驱动能和kea主体的其他功能进行资源共享:

    kea调用本PDL类的set_droidbot方法设置Droidbot,让本类可以访问droidbot。以此,需要的资源可以通过调用droidbot的方法返回给kea。

3. 发送资源到kea。

    def click(self, offset=None):
        self.droidbot.device.save_screenshot_for_report(event_name="click", event = self)

    在执行点击操作的时候,调用droidbot中的对应方法保存截图和当前的事件操作。其他的控件操作方法定义类似。