PO模式中基于行为驱动的UI自动化测试

在传统的PO模式设计的UI自动化测试中,我们需要为每个页面建模,一个页面可以封装成一个类,页面中要测试的功能对应该类中封装的方法,基于行为驱动的UI自动化就是把在页面中用户的行为操作从代码中剥离出来,通过YAML或者EXCEL单独维护,在代码中通过在基础类中封装一个能解析YAML或者EXCEL操作的方法来实现用户行为驱动的页面元素与代码低耦合的UI自动化框架,这样设计的优点就是更低的代码维护量,以最小的更改来响应频繁的业务以及页面元素的变更。

示例:

appium自动化项目中page文件夹下的base_page.py代码如下:

import yaml
from
appium import webdriver from appium.webdriver.common.mobileby import MobileBy from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.wait import WebDriverWait from xueqiu_testframe.handle_black import handle_black class BasePage: def __init__(self, driver:webdriver = None): self.driver = driver def teardown(self): self.driver.quit() @handle_black def find(self, by, locator): by_locator = (by, locator) ele = WebDriverWait(self.driver, 10).until(expected_conditions.element_to_be_clickable(by_locator)) return ele def find_and_click(self, by, locator): self.find(by, locator).click() def find_and_send(self, by, locator, text): self.find(by, locator).send_keys(text) def find_and_clear(self, by, locator): self.find(by, locator).clear() def scroll_find_click(self, target): element = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiScrollable(new UiSelector().' 'scrollable(true).instance(0)).' 'scrollIntoView(new UiSelector().' f'text("{target}").instance(0));') self.find_and_click(*element) def finds(self, by, locator): return self.driver.find_elements(by, locator)
def run_steps(self, yaml_path, operation, text=None): with open(yaml_path, "r", encoding="UTF-8") as f: datas = yaml.load(f) steps = datas[operation] for step in steps: action = step["action"] if action == "find_and_click": self.find_and_click(*step["locator"]) elif action == "find_and_send": if text: arg = text self.find_and_send(*step["locator"], arg) else: print("find_and_send 方法中需要传入arg参数") elif action == "find_and_clear": self.find_and_clear(*step["locator"]) elif action == "scroll_find_click": self.scroll_find_click(step["target"])

该base_page.py文件中的run_steps方法就是用于解析对应页面剥离于代码的YAML格式的用户行为

YAML格式的用户行为示例:

search:
  - action: find_and_click
    locator:  [id, "com.xueqiu.android:id/action_search"]

  - action: find_and_send
    locator:  [id, "com.xueqiu.android:id/search_input_text"]

 该YAML文件中定义了两个用户行为,find_and_click:在locator对应页面元素上进行点击操作;find_and_send:在locator对应页面元素上进行输入字符并提交操作

对应页面代码如下:

from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait

from xueqiu_testframe.page.base_page import BasePage


class HangQingPage(BasePage):

def search(self, text):
self.run_steps("../page/hangqing_page.yaml", "search", text)
return self.search_results_list()

def search_results_list(self):
memberlist = []
locator = (MobileBy.XPATH, '//*[@class="android.widget.TextView"]')
WebDriverWait(self.driver, 10).until(expected_conditions.element_to_be_clickable(locator))
elements = self.finds(*locator)
for element in elements:
try:
ele_text = element.get_attribute("text")
memberlist.append(ele_text)
except:
print("该元素无text属性")
print(memberlist)
return memberlist

 类HangQingPage对应的是雪球APP的行情页面,在行情页面有搜索这一功能,该类继承了BasePage,因此该类能够直接调用BasePage中的run_steps方法,解析该HangQingPage.py对应的hangqing_page.yaml来进行相应的功能操作,并return一个操作后的行为结果即:self.search_results_list()。

这里显而易见的能看出行情页面的搜索功能通过一行代码:self.run_steps("../page/hangqing_page.yaml", "search", text) 就完成了输入搜索字符点击搜索的具体操作,并返回一个搜索结果集,供后面的测试用例调用。

测试用例代码如下:

import pytest

from xueqiu_testframe.page.app import App


class TestSearch:

    def setup(self):
        self.app = App()
        self.app_start = self.app.start()

    def teardown(self):
        self.app.stop()

    @pytest.mark.parametrize("text", ["阿里巴巴", "字节跳动", "腾讯"])
    def test_search(self, text):
        results = self.app_start.goto_hangqing_page().search(text)
        exc = text
        assert exc in results


if __name__ == "__main__":

    pytest.main(['-v', '-s', 'test_search.py'])

 

posted @ 2021-03-08 21:53  smilepassed  阅读(252)  评论(0)    收藏  举报