Selenium 常用操作汇总

Selenium 操作 form 表单

form 表单是常用的测试用例对象,大多数 web 应用程序都有这方面的功能。例如:用户登录、注册都会用到 form 表单。

form 表单的流程:

  1. 定位表单元素
  2. 输入测试值
  3. 判断表单元素属性
  4. 获取表单元素属性
  5. 提交表单进行验证

实例:在本地使用了 file 协议加载本地文件,自定义一个 form 表单,使用 selenium 实现了表单的数据输入、提交。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="javascript:alert('hello')">
username: <input type="text" name="username" id="username"><br>
password: <input type="password" name="password" id="password"><br>
submit<input type="submit" value="submit" id="submit">
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import os
from time import sleep
from selenium import webdriver
from Selenium.utils.util import PROJECT_PATH # 自定义的Selenium目录


class TestCase(object):
def __init__(self):
self.path = os.path.join(PROJECT_PATH, 'static')
self.forms_file = 'file:///' + self.path + '/demo2_3_forms.html'
self.driver = webdriver.Chrome()

def quit(self):
self.driver.quit()

def get_forms_file(self):
self.driver.get(self.forms_file)

def test_login(self):
self.get_forms_file()
username = self.driver.find_element_by_id('username')
username.send_keys('admin')
password = self.driver.find_element_by_id('password')
password.send_keys('123456')
print(username.get_attribute('value'))
print(password.get_attribute('value'))
sleep(2)
self.driver.find_element_by_id('submit').click()
sleep(1)
self.driver.switch_to.alert.accept()
sleep(1)
username.clear()
password.clear()
sleep(1)
self.quit()


if __name__ == '__main__':
case = TestCase()
# print(case.get_forms_file())
case.test_login()

Selenium 操作 checkbox 和 radiobutton

  • form 表单里常用 checkbox 和 radiobutton, checkbox 是多选框,radiobutton 是单选框;
  • 例如,一个注册表单收集用户爱好可以用 checkbox,输入性别可以用 radiobutton;

关于 checkbox

  • 如果 checkbox 有 id 属性,可以直接通过 id 定位;若没有则通过 input 标签名称定位,然后通过 type 属性过滤;
  • 选择或反选 checkbox,使用 click() 方法;

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="javascript:alert('test')">
swimming: <input type="checkbox" name="swimming" value="swimming"><br>
reading: <input type="checkbox" name="reading" value="reading"><br>
<hr>
gender: <input type="radio" name="gender" value="male">male &nbsp
<input type="radio" name="gender" value="female">female <br>
login: <input type="submit" name="submit">
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import os
from time import sleep
from selenium import webdriver

from Selenium.utils.util import PROJECT_PATH


class TestCase(object):
def __init__(self):
self.path = os.path.join(PROJECT_PATH, 'static')
self.file = 'file:///' + self.path + '/demo2_4_checkbox_radiobutton.html'
self.driver = webdriver.Chrome()

def get_path(self):
self.driver.get(self.file)

def quit(self):
self.driver.quit()

def test_checkbox(self):
self.get_path()
sleep(2)
checkbox1 = self.driver.find_element_by_name('swimming')
checkbox2 = self.driver.find_element_by_name('reading')
for ele in [checkbox1, checkbox2]:
if not ele.is_selected():
ele.click()
sleep(1)
self.quit()

def test_radiobutton(self):
self.get_path()
radios = self.driver.find_elements_by_name('gender')
for radio in radios:
radio.click()
sleep(1)
self.quit()


if __name__ == '__main__':
case = TestCase()
# case.test_checkbox()
case.test_radiobutton()

Selenium 操作下拉列表

处理下拉列表,需要用到工具栏 Select 。

# 方法/属性 方法/属性描述
1 select_by_value() 根据值选择
2 select_by_index() 根据索引选择
3 select_by_visible_text() 根据文本选择
4 deselect_by_value 根据值反选
5 deselect_by_index 根据索引反选
6 deselect_by_visible_text 根据文本反选
7 deselect_all 反选所有
8 options 所有选项
9 all_selected_options 所有选中选项
10 first_selected_option 第一个选择选项

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="javascript:alert('test select')">
<label for="provise">provide:</label>
<select name="provise" id="provise" multiple>
<option value="bj">beijing</option>
<option value="hz">hangzhou</option>
<option value="nj">nanjing</option>
</select>
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import os
from time import sleep

from selenium import webdriver
from selenium.webdriver.support.select import Select

from Selenium.utils.util import PROJECT_PATH


class TestCase(object):
def __init__(self):
self.path = os.path.join(PROJECT_PATH, 'static')
self.file = 'file:///' + self.path + '/demo2_5_select.html'
self.driver = webdriver.Chrome()

def get_path(self):
self.driver.get(self.file)
sleep(2)

def quit(self):
self.driver.quit()

def test_select_by_value(self):
ele = self.driver.find_element_by_id('provise')
select_obj = Select(ele)
select_obj.select_by_value('nj')
sleep(1.5)
select_obj.select_by_value('hz')
sleep(1.5)

def test_select_by_index(self):
ele = self.driver.find_element_by_id('provise')
select_obj = Select(ele)
select_obj.select_by_index(2)
sleep(1.5)
select_obj.select_by_index(1)
sleep(1.5)
select_obj.select_by_index(0)
sleep(1.5)

def test_select_by_visible_text(self):
ele = self.driver.find_element_by_id('provise')
select_obj = Select(ele)
select_obj.select_by_visible_text('beijing')
sleep(1.5)
select_obj.select_by_visible_text('nanjing')
sleep(1.5)

def test_select_multiple(self):
ele = self.driver.find_element_by_id('provise')
select_obj = Select(ele)
for i in range(3):
select_obj.select_by_index(i)
sleep(1)
select_obj.deselect_all()
sleep(1)

def test_options(self):
ele = self.driver.find_element_by_id('provise')
select_obj = Select(ele)
for option in select_obj.options:
print(option)
print(option.text)


if __name__ == '__main__':
case = TestCase()
case.get_path()
# case.test_select_by_value()
# case.test_select_by_index()
# case.test_select_by_visible_text()
# case.test_select_multiple()
case.test_options()
case.quit()

Selenium 处理弹框

页面上的弹框有三种:

  • alert:用来提示
  • confirm:用来确认
  • prompt:输入内容
# 方法/属性 方法/属性描述
1 accept() 接受
2 dismiss() 取消
3 text 显示的文本
4 send_keys 输入内容

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="javascript:alert('提示框')" id="alert"><br>
Alert
</a>
<a href="javascript:confirm('确认框')" id="confirm"><br>
Confirm
</a>
<a href="javascript:var inputvar = prompt('请输入');document.write(inputvar)" id="prompt"><br>
Prompt
</a>
<!--<a href="javascript:prompt('请输入')" id="prompt"><br>-->
<!-- Prompt-->
<!--</a>-->
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import os
from selenium import webdriver
from time import sleep
from Selenium.utils.util import PROJECT_PATH

class TestCase(object):
def __init__(self):
self.path = os.path.join(PROJECT_PATH, 'static')
self.file = 'file:///' + self.path + '/demo2_6_alert.html'
self.driver = webdriver.Chrome()

def get_path(self):
self.driver.get(self.file)
sleep(2)

def quit(self):
self.driver.quit()

def test_alert(self):
self.get_path()
ele = self.driver.find_element_by_id('alert')
ele.click()
alert_obj = self.driver.switch_to.alert # 切换到alert
print(alert_obj.text)
sleep(1)
alert_obj.accept()
sleep(1)
self.quit()

def test_confirm(self):
self.get_path()
for i in range(2):
ele = self.driver.find_element_by_id('confirm')
ele.click()
alert_obj = self.driver.switch_to.alert
sleep(1)
if i == 0:
alert_obj.accept() # 确认
else:
alert_obj.dismiss() # 取消
sleep(1)
self.quit()

def test_prompt(self):
self.get_path()
ele = self.driver.find_element_by_id('prompt')
ele.click()
prompt_obj = self.driver.switch_to.alert
print(prompt_obj.text)
sleep(3)
# prompt_obj.send_keys('100')
prompt_obj.accept()
sleep(3)
self.quit()


if __name__ == '__main__':
case = TestCase()
# case.test_alert()
# case.test_confirm()
case.test_prompt()

Selenium 三种等待方式

在 UI 自动化测试中,必然会遇到测试环境不稳定的情况,网络延迟等,如果不做任何处理,代码会由于没有找到元素而报错。除此,有的页面会使用 ajax 异步加载机制,需要用到等待。

常用的等待有三种:

  • time.sleep 固定等待

    在开发自动化测试框架过程中,忌讳使用Python自带模块time的sleep方法进行等待,虽然可以自定义时间,当时当网络条件好时,依旧会等待,导致整个项目的测试时间没有必要的延长。只是在脚本调试是推荐使用。

  • implicitly_wait 隐式等待

    设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直会等待时间结束,然后执行下一步。这样的隐式等待会有问题,页面上的元素加载完毕后再加载 body 后面的 JavaScript,导致一直在等待页面加载结束。

    隐式等待对整个 driver 周期都起作用,在最开始设置一次就可以。不要当做笃定等待使用、到哪都使用。

  • WebDriverWait 显式等待

    WebDriverWait 是 selenium 提供得到显示等待的模块,引入路径:

    1
    from selenium.webdriver.support.wait import WebDriverWait

    WebDriverWait 参数:

    # 参数 参数说明
    1 driver 传入 WebDriver 实例
    2 timeout 超时时间,等待的最长时间
    3 poll_frequency 调用until或until_not中的方法的间隔时间,默认是0.5秒
    4 ignored_exceptions 忽略的异常

    该模块中一共只要两种方法:until 和 until_not

    # 参数 参数说明
    1 method 在等待时间,每隔一段时间调用这个传入的方法,直到返回值不是False
    2 message 如果超时,抛出TimeoutException异常,将message传入异常

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get('https://www.baidu.com')

def test_sleep(self):
self.driver.find_element_by_id('kw').send_keys('selenium')
sleep(3) # 线程阻塞 blocking wait
self.driver.find_element_by_id('su').click()
sleep(3)
self.driver.quit()

def test_implicitly(self):
self.driver.implicitly_wait(10)
self.driver.find_element_by_id('kw').send_keys('selenium')
self.driver.find_element_by_id('su').click()
self.driver.quit()

def test_wait(self):
# self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None
wait = WebDriverWait(self.driver, 5, 0.5)
wait.until(EC.title_is('百度一下,你就知道'))
self.driver.find_element_by_id('kw').send_keys('selenium')
self.driver.find_element_by_id('su').click()
self.driver.quit()


if __name__ == '__main__':
case = TestCase()
# case.test_sleep()
# case.test_implicitly()
case.test_wait()

Selenium 等待条件

# 条件 判断 返回值
1 title_is title,是否出现 布尔
2 title_contains title,是否包含某些子字符串 布尔
3 presence_of_element_located 某个元素是否被在dom树里,并不代表该元素一定可见 WebElement
4 url_contains 当前url中包含子字符串 布尔
5 url_matches 当前url匹配某表达式 布尔
6 url_to_be url是否相同 布尔
7 url_changes url不能准确匹配 布尔
8 visibility_of_element_located 某个元素是否被在dom里并且可见,宽和高都大于0 WebElement
9 visibility_of 元素是否可见,若可见就返回这个元素 WebElement
10 presence_of_all_elements_located 是否至少有1个元素存在dom树中 列表
11 visibility_of_any_elements_located 至少有1个元素在页面中可见 列表
12 text_to_be_present_in_element 指定元素中是否包含了预期的文本 布尔
13 text_to_be_present_in_element_value 指定元素的属性值中是否包含了预期的文本 布尔
14 frame_to_be_available_and_switch_to_it 该frame是否可以switch进去,若是则切进去 布尔
15 invisibility_of_element_located 某个元素是否存在于dom或不可见 布尔
16 element_to_be_clickable 某个元素是否可见并且是enabled的,代表可点击 布尔
17 staleness_of 等待某个元素从dom树中移除 布尔
18 element_to_be_selected 某个元素是否被选中了,一般用在下拉列表 布尔
19 element_located_to_be_selected 某个定位元素是否被选中了 布尔
20 element_selection_state_to_be 某个元素的选中状态是否符合预期 布尔
21 element_located_selection_state_to_be 某个元素的选中状态是否符合预期 布尔
22 alert_is_present 页面上是否存在alert alert

Selenium 鼠标和键盘操作

Selenium 中的鼠标和键盘时间被封装在 ActionChains 类中,正确的使用方法是:ActionChains(driver).click(btn).perform() ,下面是常用方法。

# 方法 描述
1 perform 执行链中的所有动作
2 reset_actions 清空链中已经存储的所有动作
3 click 点击一个元素
4 click_and_hold 在一个元素上单击并保持
5 context_click 在一个元素上右击
6 double_click 双击一个元素
7 drag_and_drop 在一个元素上单击并拖动到另一个元素上再释放(拖拽)
8 drag_and_drop_by_offset 在一个元素上单击并拖动固定距离到另一个坐标点
9 key_down 键盘上按下某个键
10 key_up 键盘上释放某个键
11 move_by_offset 鼠标从当前位置移动到某个坐标
12 move_to_element 鼠标移动到某个元素
13 move_to_element_with_offset 移动到距某个元素(左上角坐标)多少距离的位置
14 pause 在一定时间内,暂停所有的输入
15 release 在一个元素上释放鼠标左键
16 send_keys 发送数据到当前焦点的元素
17 send_keys_to_element 发送某个键到指定元素

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys


class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()

def test_mouse(self):
self.driver.get('http://sahitest.com/demo/clicks.htm')

# actionchains = ActionChains(self.driver)
# 不能使用一个实例化的ActionChains去执行多个操作,否则会下一次会执行前面累积的操作,需要reset
doubleclick_ele = self.driver.find_element_by_xpath('/html/body/form/input[2]')
ActionChains(self.driver).double_click(doubleclick_ele).perform()

click_ele = self.driver.find_element_by_xpath('/html/body/form/input[3]')
ActionChains(self.driver).click(click_ele).perform()

rightclick_ele = self.driver.find_element_by_xpath('/html/body/form/input[4]')
ActionChains(self.driver).context_click(rightclick_ele).perform()

def test_mouse_reset(self):
self.driver.get('http://sahitest.com/demo/clicks.htm')
actionchains = ActionChains(self.driver)

doubleclick_ele = self.driver.find_element_by_xpath('/html/body/form/input[2]')
actionchains.double_click(doubleclick_ele).perform()
actionchains.reset_actions()

click_ele = self.driver.find_element_by_xpath('/html/body/form/input[3]')
actionchains.click(click_ele).perform()
actionchains.reset_actions()

rightclick_ele = self.driver.find_element_by_xpath('/html/body/form/input[4]')
actionchains.context_click(rightclick_ele).perform()

def test_keys(self):
self.driver.get('http://www.baidu.com')
kw_ele = self.driver.find_element_by_id('kw')
kw_ele.send_keys('selenium')
kw_ele.send_keys(Keys.CONTROL, 'a')
sleep(1)
kw_ele.send_keys(Keys.CONTROL, 'x')
sleep(1)
kw_ele.send_keys(Keys.CONTROL, 'v')

config_ele = self.driver.find_element_by_name('tj_settingicon')
ActionChains(self.driver).move_to_element(config_ele).perform()
forcast_ele = self.driver.find_element_by_link_text('关闭预测')
ActionChains(self.driver).click(forcast_ele).perform()

if __name__ == '__main__':
case = TestCase()
# case.test_mouse()
# case.test_mouse_reset()
case.test_keys()

Selenium 执行 JavaScript 脚本

WebDriver 有两个方法来执行 JavaScript,分别是:

  • execute_script 同步执行
  • execute_async_script 异步执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from time import sleep
from selenium import webdriver


class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get("http://www.baidu.com")
self.driver.maximize_window()

def test_js1(self):
# 通过js创建alert弹框
self.driver.execute_script('alert("test_javascript")')
sleep(1)
self.driver.switch_to.alert.accept()

def test_js2(self):
# 通过js获取页面标题
js_sentence = 'return document.title'
title = self.driver.execute_script(js_sentence)
return title

def test_js3(self):
# 通过js修改样式
js_sentencce = "var q = document.getElementById('kw'); q.style.border='2px solid red'"
self.driver.execute_script(js_sentencce)

def test_js4(self):
# 通过js来拖动滚动条
self.driver.implicitly_wait(5)
self.driver.find_element_by_id('kw').send_keys('python')
self.driver.find_element_by_id('su').click()
sleep(1)
js_sentence = "window.scrollTo(0, document.body.scrollHeight)"
self.driver.execute_script(js_sentence)


if __name__ == '__main__':
case = TestCase()
# case.test_js1()
# print(case.test_js2())
# case.test_js3()
case.test_js4()

Selenium 屏幕截图

WebDriver 内置了一些在测试中捕获并保存的方法:

# 方法 描述
1 save_screenshot(filename) 获取当前屏幕截图并保存为文件,filename为指定保存的路径或图片的文件名
2 get_screenshot_as_base64() 获取当前屏幕截图base64编码字符串
3 get_screenshot_as_file(filename) 获取当前的屏幕截图,使用完整的路径
4 get_screenshot_as_png() 获取当前屏幕截图的二进制文件数据

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import os
from time import sleep, strftime, localtime, time
from selenium import webdriver

from utils.util import PROJECT_PATH


class TestCase(object):
def __init__(self):
self.path = PROJECT_PATH
self.driver = webdriver.Chrome()
self.driver.get("http://www.baidu.com")
self.driver.maximize_window()

def test1(self):
self.driver.find_element_by_id('kw').send_keys('截屏')
self.driver.find_element_by_id('su').click()
sleep(1)
# self.driver.save_screenshot('screenshot_baidu')

str_time = strftime("%Y-%m-%d-%H-%M-%S", localtime(time()))
# file_name = str_time + '.png'
# self.driver.save_screenshot(file_name)

screenshot_dir = os.path.join(self.path, 'screenshot')
if not os.path.exists(screenshot_dir):
os.mkdir(screenshot_dir)
file_name = os.path.join(screenshot_dir, str_time + '.png')
self.driver.save_screenshot(file_name)


if __name__ == '__main__':
case = TestCase()
case.test1()

Selenium 定位 frame iframe

frame 标签有 framesetframeiframe 三种,frameset 跟其他普通标签没有区别,不会影响到正常的定位,而 frame 与 iframe 对 Selenium 定位而言是一样的,Selenium 有一组方法对 frame 进行操作。

# 方法 描述
1 switch_to.frame(reference) 切换frame,reference是传入的参数,用来定位frame,可以传入id,name,index以及selenium的WebElement对象
2 switch_to.default_content() 返回主文档
3 switch_to.parent_frame() 返回父文档

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from time import sleep
from selenium import webdriver


class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get("http://sahitest.com/demo/framesTest.htm")

def test_frame(self):
self.driver.implicitly_wait(10)
frame1_ele = self.driver.find_element_by_name('top')
self.driver.switch_to.frame(frame1_ele)
Link_Test = self.driver.find_element_by_xpath("/html/body/table/tbody/tr/td[1]/a[1]")
Link_Test.click()
self.driver.switch_to.default_content()

sleep(3)
frame2_ele = self.driver.find_element_by_xpath("/html/frameset/frame[2]")
self.driver.switch_to.frame(frame2_ele)
Link_Test2 = self.driver.find_element_by_xpath("/html/body/table/tbody/tr/td[1]/a[1]")
Link_Test2.click()


if __name__ == '__main__':
case = TestCase()
case.test_frame()