【unittest单元测试框架】(10)poium 测试库


poium 测试库

1、基础介绍

  poium 是一个基于 Selenium/appium 的 Page Object 测试库,最大的特点是简化了 Page层元素的定义。   项目地址:https://github.com/SeldomQA/poium
  支持 pip 安装:
 pip install poium

   使用 poium 重写 baidu_page.py

# -*- coding:utf-8 -*-
# filename: baidu_page.py

from poium import Page, Element


class BaiduPage(Page):
    """百度 Page 层,百度页面封装操作到的元素"""
    search_input = Element(id="kw")
    search_button = Element(id="su")
    
  创建 BaiduPage 类,使其继承 poium 库中的 Page 类。调用 PageElement 类定义元素定位,并赋值给变量 search_input 和 search_button。这里仅封装元素的定位,并返回元素对象,元素的具体操作仍然在测试用例中完成,这也更加符合 Page Object 的思想,将元素定位与元素操作分层。   在测试用例中的使用如下:   创建baiduPage.py
# -*- coding:utf-8 -*-
# filename: baiduPage.py

from poium import Page, Element


class BaiduPage(Page):
    """百度 Page 层,百度页面封装操作到的元素"""
    input = Element(id_="kw", timeout=1, index=0, describe="搜索输入框")
    button = Element(id_="su", timeout=1, index=0, describe="搜索按钮")

   创建test_BaiduPage.py

# -*- coding:GBK -*-
# filename:test_BaiduPage.py
# https://github.com/SeldomQA/poium

import unittest
from time import sleep
from selenium import webdriver
from baiduPage import BaiduPage


class TestBaidu(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()

    def test_baidu_search_case1(self):
        page = BaiduPage(self.driver)
        page.open("https://www.baidu.com")
        page.input.send_keys("selenium")
        page.button.click()
        sleep(3)
        self.assertEqual(page.get_title, "selenium_百度搜索")

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()


if __name__ == "__main__":
    unittest.main(verbosity=2)

 2、Page 和 Element

 通过Page类和 Element类实现Page层元素层的封装。
# page层封装
from poium import Page, Element

class BaiduPage(Page):
    input = Element(id_="kw", describe="搜索输入框")
    button = Element(id_="su", describe="搜索按钮")
  • 创建页面类继承Page类。
  • 通过Element类定义元素。

2.1element类参数

Element类提供了几个参数:
from poium import Page, Element

class BaiduPage(Page):
    input = Element(id_="kw", timeout=1, index=0, describe="搜索输入框")
    button = Element(id_="su", timeout=1, index=0, describe="搜索按钮")

 第一个参数: 支持所有Selenium/appium的定位方式

# selenium
css = "xx"
id_ = "xx"
name = "xx"
xpath = "xx"
link_text = "xx"
partial_link_text = "xx"
tag = "xx"
class_name = "xx"

# appium
ios_uiautomation = "xx"
ios_predicate = "xx"
ios_class_chain = "xx"
android_uiautomator = "xx"
android_viewtag = "xx"
android_data_matcher = "xx"
android_view_matcher = "xx"
windows_uiautomation = "xx"
accessibility_id = "xx"
image = "xx"
custom = "xx"
  • timeout: 设置超时检查次数,默认为5
  • index: 设置元素索引,当你的定位方式默认匹配到多个元素时,默认返回第1个,即为0.
  • describe: 设置元素描述,默认为undefined, 建议为每个元素增加描述

2.2 Elements类

有时候,我们poium返回的是一组元素对象,可以使用Elements类。

from poium import Page, Element, Elements

class BaiduPage(Page):
    input = Element(id_="kw", describe="搜索输入框")
    button = Element(id_="su", describe="搜索按钮")
    results = Elements(xpath="//div/h3/a", describe="搜索结果") # 返回一组元素

3、Element类元素操作方法

当我们定位到一个元素之后,Elements 类除了提供click点击和send_keys输入,还可以丰富的操作。

  • selenium 常规操作
page.elem.clear()
"""Clears the text if it's a text entry element."""

page.elem.send_keys(value)
"""
Simulates typing into the element.
"""

page.elem.click()
"""Clicks the element."""

page.elem.submit()
"""Submits a form."""

page.elem.tag_name
"""This element's ``tagName`` property."""

page.elem.text
"""Clears the text if it's a text entry element."""

page.elem.size
"""The size of the element."""

page.elem.get_property(, name)
"""
Gets the given property of the element.
"""

page.elem.get_attribute(, name)
"""Gets the given attribute or property of the element."""

page.elem.is_displayed()
"""Whether the element is visible to a user."""

page.elem.is_selected()
"""
Returns whether the element is selected.
Can be used to check if a checkbox or radio button is selected.
"""

page.elem.is_enabled()
"""Returns whether the element is enabled."""

page.elem.switch_to_frame()
"""
selenium API
Switches focus to the specified frame
"""

page.elem.move_to_element()
"""
selenium API
Moving the mouse to the middle of an element
"""

page.elem.click_and_hold()
"""
selenium API
Holds down the left mouse button on an element.
"""

page.elem.double_click()
"""
selenium API
Holds down the left mouse button on an element.
"""

page.elem.context_click()
"""
selenium API
Performs a context-click (right click) on an element.
"""

page.elem.drag_and_drop_by_offset(x, y)
"""
selenium API
Holds down the left mouse button on the source element,
    then moves to the target offset and releases the mouse button.
:param x: X offset to move to.
:param y: Y offset to move to.
"""

page.elem.refresh_element(, timeout=10)
"""
selenium API
Refreshes the current page, retrieve elements.
"""
  • Select 下拉框操作
page.elem.select_by_value(value)
"""
selenium API
Select all options that have a value matching the argument. That is, when given "foo" this
    would select an option like:

    

    :Args:
    - value - The value to match against

    throws NoSuchElementException If there is no option with specisied value in SELECT
"""

page.elem.select_by_index(index)
"""
selenium API
Select the option at the given index. This is done by examing the "index" attribute of an
    element, and not merely by counting.

    :Args:
    - index - The option at this index will be selected

    throws NoSuchElementException If there is no option with specisied index in SELECT
"""

page.elem.select_by_visible_text(text)
"""
selenium API
Select all options that display text matching the argument. That is, when given "Bar" this
    would select an option like:

    

    :Args:
    - text - The visible text to match against

    throws NoSuchElementException If there is no option with specisied text in SELECT
"""
  • appium 扩展操作
page.elem.set_text(keys)
"""
appium API
Sends text to the element.
"""

page.elem.location_in_view
"""
appium API
Gets the location of an element relative to the view.
Returns:
    dict: The location of an element relative to the view
"""

page.elem.set_value(value)
"""
appium API
Set the value on this element in the application
"""
  • 模拟键盘操作
page.elem.input(text="")

page.elem.enter()

page.elem.select_all()

page.elem.cut()

page.elem.copy()

page.elem.paste()

page.elem.backspace()

page.elem.delete()

page.elem.tab()

page.elem.space()

4、CSSElement类

有时我们需要借助JavaScript实现一些特殊的操作。poium提供了CSSElement类,已经帮你封装了这些操作。

from poium import Page, CSSElement

class BaiduIndexPage(Page):
    elem = CSSElement('#kw')
    elem2 = CSSElement('#su')

注:CSSElement类不需要指定定位方式,仅支持CSS定位。

4.1CSSElement类提供的操作

page.elem.clear()
"""
JavaScript API, Only support css positioning
Clears the text if it's a text entry element, Only support css positioning
"""

page.elem.set_text(value)
"""
JavaScript API, Only support css positioning
Simulates typing into the element.
:param value: input text
"""

page.elem.click()
"""
JavaScript API, Only support css positioning
Click element.
"""


page.elem.click_display()
"""
JavaScript API, Only support css positioning
Click on the displayed element, otherwise skip it.
"""

page.elem.display()
"""
JavaScript API, Only support css positioning
Display hidden elements
"""

page.elem.remove_attribute(attribute)
"""
JavaScript API, Only support css positioning
Remove element attribute, Only support css positioning
:param attribute:
"""

page.elem.set_attribute(attribute, value)
"""
JavaScript API, Only support css positioning
Setting element attribute, Only support css positioning
:param attribute:
:param value:
"""

page.elem.clear_style()
"""
JavaScript API, Only support css positioning
Clear element styles.
"""
    
page.elem.clear_class()
"""
JavaScript API, Only support css positioning
Clear element class
"""

page.elem.inner_text(text)
"""
JavaScript API, Only support css positioning
The innerText property sets the text content of the specified element, Only support css positioning
:param text: Inserted text
"""

page.elem.remove_child(child=0)
"""
JavaScript API, Only support css positioning
Remove a node from the child node list
:param child: child of the child node
"""

page.elem.click_parent()
"""
JavaScript API, Only support css positioning
Click the parent element of the element
"""

page.elem.scroll(top=0, left=0)
"""
JavaScript API, Only support css positioning
scroll the div element on the page
"""

page.elem.move_to()
"""
JavaScript API, Only support css positioning
Move the mouse over the element
""" 

5、在 Selenium 中使用 poium

from time import sleep
from poium import Page, Element, Elements
from poium import Browser
from selenium import webdriver

# page层定义
class BaiduPage(Page):
    input = Element(id_="kw", describe="搜索输入框")
    button = Element(id_="su", describe="搜索按钮")
    results = Elements(xpath="//div/h3/a", describe="搜索结果")


dr = webdriver.Firefox()
page = BaiduPage(dr)
page.get("https://www.baidu.com")
page.input.send_keys("baidu")
page.button.click()
sleep(2)

elem = page.results
for e in elem:
    print(e.text)

dr.close()

运行结果:

? python se_demo.py
2021-01-04 23:57:48,449 INFO ? Find element: id=kw
2021-01-04 23:57:49,396 INFO ?? input element: 搜索输入框
2021-01-04 23:57:49,461 INFO ? Find element: id=su
2021-01-04 23:57:50,393 INFO ?? click element: 搜索按钮
2021-01-04 23:57:52,624 INFO ? Find 10 elements through: xpath=//div/h3/a, describe:搜索结果
百度一下,你就知道
官方
百度新闻——海量中文资讯平台
百度[BIDU]美股实时行情_东方财富网
北京百度网讯科技有限公司 - 企业信息
百度官方吧_百度贴吧
百度智能云-计算无限可能
百度知道 - 全球最大中文互动问答平台
关于百度
百度地图