Helium框架

2022-06-15 00:00:00 示例 元素 等待 方法 控件

基本方法及控件介绍
启动浏览器
访问网址
写入
按键
点击/双击/右击
拖拽
拖拽文件
上传文件
按住/松开左键
鼠标悬浮
向上/下/左/右滚动屏幕
查找元素组
下拉框选择
刷新页面
等待元素
配置文件—隐式等待时间
UI基础类: class GUIElement
元素基础类:class HTMLElement(GUIElement)
元素定位类:class S(HTMLElement)
控件类
弹窗Alert
坐标点Point
窗口
窗口切换switch_to
关掉浏览器
高亮highlight
与selenium配合(set_driver/get_driver)
实际应用
启动浏览器
def start_firefox(url=None, headless=False, options=None)
1
这三个参数都有默认值,为None,所以都为可选填的

url:要访问的网站网址
headless:是否隐藏浏览器,即执行脚本时,浏览器是否可见
options:浏览器配置,要使用options时需引入配置模块

例子:

start_firefox("google.com")
start_chorme(headless=True)
from selenium.webdriver import ChromeOptions
#firefox引入FirefoxOptions
options = ChromeOptions()
options.add_argument('--start-maximized')
options.add_argument('--proxy-server=1.2.3.4:5678')
start_chrome("www.baidu.com",headless=True,options=options)

访问网址
def go_to(url)
1
这个比较简单,直接用url即可

写入
def write(text, into=None)
1
顾名思义,将内容写入输入框的功能,其中into为非必填,如果没填的话,默认输入到页面找到的个输入框,如果要填的话,对应的是element。

options = ChromeOptions()
options.add_argument("--start-maximized")
start_chrome("https://www.zhihu.com/signin?next=%2F",options=options)
click(Text("密码登录"))
write("python@123.com",into=S("@username"))
write("python",into="密码")
click(Button("",below="登录"))
按键

def press(key)
1

普通字母数字直接用’key’就可以了,如果是特殊按键,这用对应的按键名即可,组合件的话,用+号连接


press('A')
press('a')
press(ENTER)
press(CONTROL + 'a')


特殊按键对应的按键名可以在selenium.webdriver.common.keys.Keys找到。具体如下:


NULL = Keys.NULL
CANCEL = Keys.CANCEL
HELP = Keys.HELP
BACK_SPACE = Keys.BACK_SPACE
TAB = Keys.TAB
CLEAR = Keys.CLEAR
RETURN = Keys.RETURN
ENTER = Keys.ENTER
SHIFT = Keys.SHIFT
LEFT_SHIFT = Keys.LEFT_SHIFT
CONTROL = Keys.CONTROL
LEFT_CONTROL = Keys.LEFT_CONTROL
ALT = Keys.ALT
LEFT_ALT = Keys.LEFT_ALT
PAUSE = Keys.PAUSE
ESCAPE = Keys.ESCAPE
SPACE = Keys.SPACE
PAGE_UP = Keys.PAGE_UP
PAGE_DOWN = Keys.PAGE_DOWN
END = Keys.END
HOME = Keys.HOME
LEFT = Keys.LEFT
ARROW_LEFT = Keys.ARROW_LEFT
UP = Keys.UP
ARROW_UP = Keys.ARROW_UP
RIGHT = Keys.RIGHT
ARROW_RIGHT = Keys.ARROW_RIGHT
DOWN = Keys.DOWN
ARROW_DOWN = Keys.ARROW_DOWN
INSERT = Keys.INSERT
DELETE = Keys.DELETE
SEMICOLON = Keys.SEMICOLON
EQUALS = Keys.EQUALS
NUMPAD0 = Keys.NUMPAD0
NUMPAD1 = Keys.NUMPAD1
NUMPAD2 = Keys.NUMPAD2
NUMPAD3 = Keys.NUMPAD3
NUMPAD4 = Keys.NUMPAD4
NUMPAD5 = Keys.NUMPAD5
NUMPAD6 = Keys.NUMPAD6
NUMPAD7 = Keys.NUMPAD7
NUMPAD8 = Keys.NUMPAD8
NUMPAD9 = Keys.NUMPAD9
MULTIPLY = Keys.MULTIPLY
ADD = Keys.ADD
SEPARATOR = Keys.SEPARATOR
SUBTRACT = Keys.SUBTRACT
DECIMAL = Keys.DECIMAL
DIVIDE = Keys.DIVIDE
F1 = Keys.F1
F2 = Keys.F2
F3 = Keys.F3
F4 = Keys.F4
F5 = Keys.F5
F6 = Keys.F6
F7 = Keys.F7
F8 = Keys.F8
F9 = Keys.F9
F10 = Keys.F10
F11 = Keys.F11
F12 = Keys.F12
META = Keys.META
COMMAND = Keys.COMMAND


点击/双击/右击

def click(element) #单击
def doubleclick(element) #双击
def rightclick(element)


示例:


click("Sign in")
click(Button("OK"))
click(Point(200, 300))
click(ComboBox("File type").top_left + (50, 0))


拖拽

def drag(element, to)


将一个元素拖拽到指定位置,这个个人使用时,自己用elment-ui写了个drag功能一直拖拽失败,比较尴尬。
官方示例:


drag("Drag me!", to="Drop here.")


拖拽文件

def drag_file(file_path, to)


将本地的文件拖入到浏览器指定的位置,挺好用的一个功能。
示例:


click("配置管理")
wait_until(Text("文件上传").exists)
click("文件上传")
drag_file(r"D:\\1.jpg",to="将文件拖到此处,或点击上传")




上传文件

def attach_file(file_path, to=None)


将文件上传,这个针对的是input type=“file”
示例:


start_chrome("file:///D:/1.html",options=options)
attach_file(r"D:\\2.jpg")





按住/松开左键

def press_mouse_on(element)
def release_mouse_over(element)
1
2

鼠标悬浮

def hover(element)


示例:


hover("File size")
hover(Button("OK"))
hover(Link("Download"))
hover(Point(200, 300))
hover(ComboBox("File type").top_left + (50, 0))


向上/下/左/右滚动屏幕

def scroll_down(num_pixels=100)
def scroll_up(num_pixels=100)
def scroll_right(num_pixels=100)
def scroll_left(num_pixels=100)


不设置参数时默认为100像素,设置参数的话直接写数字就可以


查找元素组

def find_all(predicate)


这个比较简单,就是找元素组,然后根据index来取元素。示例:


find_all(Button("Open"))
find_all(Window())
find_all(TextField("Address"))


下拉框选择

def select(combo_box, value)

从下拉选项中选择一项,示例:

select("Language", "English")
select(ComboBox("Language"), "English")

刷新页面
def refresh()

直接使用即可

等待元素
def wait_until(condition_fn, timeout_secs=10, interval_secs=0.5)
1
等待某个条件为真才继续往下执行。默认的超时时间为10s,每0.5查询一次,这俩参数选填。可以设置超时时间和轮询间隔。

注意:condition_fn等待条件直接采用函数的话,不能带()或者直接用lambda后带完整函数。

示例:

wait_until(Text("Finished!").exists)
wait_until(lambda:Text("Finished!").exists())

配置文件—隐式等待时间
等待时间:
首先要知道隐式等待时间的含义,是指执行脚本时,如果某个元素元素刚开始没找到,会默认等待一段时间,超时后才会抛出错误。显示等待这是直接在代码里写等待多久,比如time.sleep(xxx)
配置管理:
helium中有个Config类

class Config:
1
里面只介绍了隐式等待时间的设置。默认值为10s,如果要自己设置,直接调用config即可:
如果要关闭隐式等待时间,则只需要将时间设置为0即可。

UI基础类: class GUIElement
基础的UI类,用的上的只有一个函数

def exists(self)
1
用于判断某个元素是否存在,返回true或false

元素基础类:class HTMLElement(GUIElement)
界面元素类,继承GUIElement,有六个属性:

width #元素宽度
height #高度
x #元素在界面上的X轴坐标
y #y轴坐标
top_left #元素坐上角的坐标
web_element #转换为web_element,之后可以调用selenium元素的属性和方法

示例:

start_chrome("file:///D:/1.html",options=options)
element = Button("submit")
width = element.width
height = element.height
x = element.x
y = element.y
top_left = element.top_left
web_el_text = element.web_element.text
web_el_tag = element.web_element.tag_name
print("元素大小:{width}*{height},元素位置:{x},{y},元素左上角位置:{top_left},元素文本:{web_el_text},元素类别:{web_el_tag}".format(
width = width,
height = height,
x = x,
y = y,
top_left = top_left,
web_el_text = web_el_text,
web_el_tag = web_el_tag

结果如下图,可以发现x,y实际就是top_left的具体坐标值,而top_left的返回类型为Point,所以要对top_left做位置变换需要用Point数据:
此外,要关注一下__init__方法,也就是类的初始化:

def __init__(self, below=None, to_right_of=None, above=None, to_left_of=None)
1
这个是说在可以通过相对位置来实现元素及控件的查找

below #在某个元素下方
above #在某个元素上方
to_right_of #在某个元素右侧
to_left_of #在某个元素左侧

所有基于HTMLElement类的元素或者控件都可以通过这4个相对位置来实现元素查找。
例子:

Button("登录",below="password") #位于password下的登录按钮
1
元素定位类:class S(HTMLElement)
它是基于HTMLElement的,不同定位方式是通过符号来区分的

@ #对应name
. #对应class
# #对应id
// #对应xpath或者css selector

示例:

write("testname",into=S("#username"))
find_all(S("table > tr > td", below="Email"))

Helium比较特殊,元素定位类是继承HTMLElement的,而其他控件,比如Button、Link等也全都继承HTMLElement,所以这几个是并列关系,也就是说

控件无法通过定位类S来实现控件查找,只能基于控件文本和HTMLElement中的四个相对位置来实现控件查找

比如Button(S("#submit")是错误的,可以通过Button(“登录”,below=“username”)来实现查找。

控件类
所有控件类都继承HTMLElement类,所以可以试用HTMLElement和GUIElement类的方法与属性。

1. 文本控件
用于获取界面文本的控件,拥有value属性来获取控件对应的文本

class Text(HTMLElement)
@property
def value(self)

示例

Text("Do you want to proceed?").exists()
Text(below="Email", to_right_of="John").value

2. 链接控件
用于识别界面上的链接,拥有href属性可以获取链接对应的url

class Link(HTMLElement)
@property
def href(self)

示例:

click(Link("Block User", to_right_of="John Doe"))
Link("百度").href

3.序列控件
可以获取界面上的序列<li>元素

class ListItem(HTMLElement)
1
示例:

click(ListItem("List item 1", below="My first list:"))
assert ListItem("List item 1").exists()
1
2
4.按钮控件
可以获取按钮控件,具有is_enabled方法,用于判断按钮是否有被disabled

class Button(HTMLElement)
def is_enabled(self)
1
2
示例:

click(Button("OK"))
click(Button("Log In", below=TextField("Password")))
Button("OK").is_enabled()
1
2
3
5.图片控件
识别图片元素,从__init__类的初始化函数可以看到相对其他控件的text=None(,图片控件的是alt=None,也就是说要通过alt而非text来识别图片,至于什么是alt,这个是html基础,不懂得可以百度。

class Image(HTMLElement)
def __init__(self, alt=None, below=None, to_right_of=None, above=None,to_left_of=None)

示例:

click(Image(alt="logo"))
lick(Image("logo", to_left_of=ListItem("Download")))
Image("logo").exists()

6.文本框控件
可识别可以用于输入的文本框控件,它是通过label加相对位置来定位的,这个label既可以采用本文框左侧的文字,也可以采用文本框内部的提示语,也就是html的placeholder里的文本。
value属性,可以获取文本框里的文本;
is_enabled()方法,识别文本框是否被disabled,界面上显示的就是置灰
is_editable()方法,识别文本框是否可编辑,也就是是否有配置readonly,这时控件是不置灰的,但是不可编辑。

class TextField(HTMLElement)
def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None)
@property
def value(self)
<span class="token keyword">def</span> <span class="token function">is_enabled</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">is_editable</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

示例:
html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello worlds</h1>
username:<input placeholder="请输入用户名"></input>
</body>
</html>

自动化代码如下:

from helium import *
from selenium.webdriver import ChromeOptions
import time
Config.implicit_wait_secs=30

options = ChromeOptions()
options.add_argument("–start-maximized")
start_chrome(“file:///D:/1.html”,options=options)
write(“test1”,into=TextField(“username”))
time.sleep(3)
write(“test2”,into=TextField(to_right_of=“username”))
time.sleep(3)
write(“test3”,into=TextField(“请输入用户名”))
element = Button(“submit”)
上面3种方式都是可以找到input控件的,都可以成功输入。

7.下拉列表框控件
这个相对select来说范围更广,一般来说既可以指的select,也可以指dropdown控件,特别是一些可以通过输入文本来匹配选项的控件,都可以用这个控件。
查看__init__可以发现跟文本框是一样的,都是用label来识别控件,查找方法类似上面文本框控件。它本身经常和select一起使用,用于选中某一选项。
value属性:可以获取已选中项的值
options属性:可以获取所有可以选择的选项内容
is_editable()方法:判断是否可输入文本来匹配选项

class ComboBox(HTMLElement)
def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None)
<span class="token keyword">def</span> <span class="token function">is_editable</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

@<span class="token builtin">property</span>
<span class="token keyword">def</span> <span class="token function">value</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

@<span class="token builtin">property</span>
<span class="token keyword">def</span> <span class="token function">options</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>


示例:

ComboBox("Language").value
select(ComboBox(to_right_of="John Doe", below="Status"), "Active")

8.复选框控件
顾名思义,识别复选框用的。
is_enabled()方法:判断是否被disabled
is_checked()方法:判断是否被选中

class CheckBox(HTMLElement)
def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None)
<span class="token keyword">def</span> <span class="token function">is_enabled</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">is_checked</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

示例:

CheckBox("已阅读xx").is_checked()
click(CheckBox("记住登录状态", below=Button("登录")))

9.单选框控件
单选框专用
is_selected()方法:判断是否被选中

class RadioButton(HTMLElement)
def __init__(self, label=None, below=None, to_right_of=None, above=None,to_left_of=None)
<span class="token keyword">def</span> <span class="token function">is_selected</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

示例:

RadioButton("Windows").is_selected()
click(RadioButton("我同意", below="用户协议"))
1
2
弹窗Alert
这个是专门针对alert弹窗的,是继承GUIElement的,所以没法用四个相对位置来查找,不过一般alert都会位于界面顶层,所以一般也比较容易识别出来。
通过__init__可以知道它可以通过文本来查找弹窗,特别是对于多个弹窗的话,用文本来区分即可,如果只有一个弹窗,可以search_text放空一般也可以找到
text属性:获取弹窗上的文本内容
accept()方法:相当于点击弹窗上的OK / 确认键
dismiss()方法:相当于点击弹窗上的Cancel / 取消按键

class Alert(GUIElement)
def __init__(self, search_text=None)
@<span class="token builtin">property</span>
<span class="token keyword">def</span> <span class="token function">text</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">accept</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">dismiss</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

示例:

write("12",into=Alert("请输入个数"))
Alert().accept()
Alert().dismiss()

坐标点Point
通过x,y来表示元素在界面上的具体坐标,如果要偏移位置,可以用+或者-来实现。

class Point(namedtuple('Point', ['x', 'y']))
def __init__(self, x=0, y=0)
@<span class="token builtin">property</span> <span class="token comment">#X轴坐标</span>
<span class="token keyword">def</span> <span class="token function">x</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

@<span class="token builtin">property</span> <span class="token comment">#Y轴坐标</span>
<span class="token keyword">def</span> <span class="token function">y</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

<span class="token keyword">def</span> <span class="token function">__eq__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> other<span class="token punctuation">)</span> <span class="token comment"># 对比两个Point看是否相等</span>

<span class="token keyword">def</span> <span class="token function">__ne__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> other<span class="token punctuation">)</span> <span class="token comment"># 对比两个Point看是否相等</span>

<span class="token keyword">def</span> <span class="token function">__hash__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span> <span class="token comment">#hash,返回x + 7*y,暂时未知作用</span>

<span class="token keyword">def</span> <span class="token function">__add__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>delta<span class="token punctuation">)</span> <span class="token comment">#相加,delta对应某个point</span>

<span class="token keyword">def</span> <span class="token function">__radd__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>delta<span class="token punctuation">)</span> <span class="token comment">#功能和add一致,为啥叫radd未知</span>

<span class="token keyword">def</span> <span class="token function">__sub__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>delta<span class="token punctuation">)</span> <span class="token comment">#相减</span>

<span class="token keyword">def</span> <span class="token function">__rsub__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>delta<span class="token punctuation">)</span> <span class="token comment">#相减,同sub一样</span>


1
2
示例:

print(Point(100,100)+ (Point(1,2)))
print(Point(100,100).__add__(Point(1,2)))
1
2
窗口
可以用于或者窗口title也可以配合switch_to来进行窗口的切换

class Window(GUIElement)
def __init__(self, title=None)
@<span class="token builtin">property</span> <span class="token comment">#窗口的title</span>
<span class="token keyword">def</span> <span class="token function">title</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

@<span class="token builtin">property</span> <span class="token comment">#返回selenium driver的标识,本身不具备操控界面的能力</span>
<span class="token keyword">def</span> <span class="token function">handle</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span>

示例:

print(Window().title)
switch_to(Window("标题"))
switch_to(find_all(Window())[0])

窗口切换switch_to
通过窗口的title来切换窗口

def switch_to(window)
1
示例:

switch_to("Google")
switch_to(Window("Google"))
switch_to(find_all(Window())[0])

关掉浏览器
就是单纯的关掉浏览器,如果不调用该方法,执行完后浏览器会保持打开状态

def kill_browser()
1
高亮highlight
为了凸显某一元素便于查看或者在操作某一元素前,可以采用highlight来标识出来,然后再采用截图的话,可以明确知道该步骤在页面上对哪个元素进行操作。

def highlight(element)
1
示例:

highlight(TextField("username"))
1
效果图:


与selenium配合(set_driver/get_driver)
set_driver(driver)用于将selenium的driver切换到helium,这样就可以直接使用helium的api了
get_driver()用于获取helium的driver,然后driver后可以使用selenium语句

从selenium到helium:

from selenium import webdriver
from helium import *
driver = webdriver.Chrome()
set_driver(driver)
go_to("http://127.0.0.1:8080/#/login")

从helium到selenium:

from helium import *
start_chrome()
driver = get_driver() #或者直接driver = start_chrome()
element = driver.find_element_by_id('auto_test')
print(element.text)
driver.save_screenshot("D:/1.png")

实际应用
1、二次封装形成描述式测试工具
网易易测的SmartAuto应该就是基于Helium的,之前使用过,是通过中文描述来实现自动化脚本的。元素定位用左侧、右侧等方式来辅助定位,比如

在用户名右侧的输入框输入#1234
1
本质上就是Helium语句:

write("1234",into=TextField("",to_right_of="用户名"
2、直接用作自动化测试脚本
Helium本身就是对Selenium封装而成的,可以和selenium混合使用,比如脚本内容用Helium,截图用selenium。Helium会相对简单一些,而且界面发生变更的话修改起来会更容易,且定位成功率相对高一些(部分元素除外),配合Unittest、pytest、pageObject等与Selenium混合使用能够完成较好的自动化测试脚本。
————————————————
版权声明:本文为CSDN博主「Tao.....」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiuxiu_1111/article/details/122057527

相关文章