主要是selenium+pytest+POM
一、selenium初始框架:
# 导入模块 from selenium import webdriver from time import sleep # 实例化浏览器对象 driver = webdriver.Chrome() # 打开网页 driver.get('***.html') # 展示效果 sleep(3)# 关闭页面 driver.quit()
元素定位
# 使用id定位element = driver.find_element_by_id('xx')# 使用name定位element = driver.find_element_by_name('xx')# class_name根据元素class属性定位元素element = driver.find_element_by_class_name('xx')# tag_name:标签名element = driver.find_element_by_tag_name('xx')# 使用link_text定位访问超链接l = driver.find_element_by_link_text('xx')# 只需要超链接的部分文本信息 pl = driver.find_element_by_partial_link_text('xx')
除了id唯一外,其他都有重复的可能,所以其他要保证唯一性
元素信息
element.size, element.text, element.get_attribute('class'), element.is_displayed(),element.is_enabled(), element.is_selected()
元素操作方法
element.send_keys('xx')、element.click()
driver操作
driver.back() driver.forward() driver.refresh() driver.close() driver.quit() driver.title driver.current_url
定位一组元素
usernames = driver.find_elements_by_name('xxx')
for username in usernames:
username.send_keys('xxx')
sleep(3)
XPath
# XPath # 路径:定位 # 利用元素属性:定位 # 属性与逻辑结合:定位 # 层级与属性结合:定位 # 方法名:find_element_by_xpath(xpath)# 绝对路径:从最外层元素到指定元素之间所有经过元素层级的路径,以/html开始 # 相对路径:匹配任意层级的元素,不限制元素的位置,以//开始# 利用元素属性策略 # 语法://标签名[@属性名='属性值'] # 语法: //*[@属性名='属性值' and @属性名='属性值']# 层级与属性结合 # //*[@id='p1']/input # 延伸://*[text()="xxx"] 文本内容是xxx的元素 # //*[contains(@attribute,'xxx')] 属性中含有xxx的元素 # //*[starts-with(@attribute, 'xxx')] 属性以xxx开头
CSS
# 推荐使用CSS比Xpath快 # CSS定位常用策略: # 1. id选择器 #id # 2. class选择器 .class # 3. 元素选择器 element(标签) # 4. 属性选择器 [属性=值] # 5. 层级选择器 # 方法:find_element_by_css_selector# 层级:父子:>,祖辈和后代:空格# CSS延伸 # input[type^='p'] 以p开头 # input[type$='d'] 以d结尾 # input[type*='w'] 包含w的
下拉框
select = Select(wb.find_element_by_id('selectA'))
select.select_by_index(2)
元素等待
# 在定位页面元素时如果未找到,会在指定时间内一直等待的过程 # 为什么设置?1. 网络速度慢 2. 电脑配置低 3. 服务器处理请求慢 # 隐式等待和显示等待 # 隐式等待:如果能找到元素就不等待,如果找不到就隔一段时间(默认值)定位,如果达到最大时间还没找到,就抛出异常 # driver.implicitly_wait(timeout) # timeout为等待最大时长,单位为s # 隐式等待为全局设置,设置一次作用于所有元素# 当隐式等待被激活时,虽然目标元素已经出现了,但是还是会因为页面内其他元素未加载完成而继续等待,进而增加代码执行时间 # 显示等待,如果能找到元素就不等待,如果找不到就隔一段时间(默认值)定位,如果达到最大时间还没找到,就抛出异常element = WebDriverWait(driver, 10, 1).until(lambda x: x.find_element_by_id("userA")) element.send_keys('admin') #显示
frame
# 当确定id却提示没有定位到元素的时候,可以考虑是不是有frame
# 如果有frame包含的要先获取frame
driver.switch_to_frame('idframe1')
多窗口
# 当点击超链接的时候,切换到另一个窗口的时候要切换handle,每次调用的时候每个窗口都会创建自己独立的handle hand = driver.current_window_handle driver.switch_to.window(hand)
截图
driver.get_screenshot_as_file('./1.png')
系统弹窗
# alert元素
element = driver.find_element_by_xpath('//*[@id="alerta"]').click()
#alert = driver.switch_to_alert()
# 切换到弹窗
alert = driver.switch_to.alert
print(alert.text)
sleep(3)
# 去除弹窗
alert.accept() # 同意
键盘操作
# 删除:BACK_SPACE, SPACE 空格, TAB 制表, ESCAPE 回退, ENTER 回车, CONTROL 'a' 全选, CONTROL 'c' 复制str = username.send_keys(Keys.CONTROL, 'c') password.send_keys(Keys.CONTROL, 'v')
鼠标操作
username = driver.find_element_by_id('userA') action.context_click(username)# 右键,鼠标右键只能展示菜单内容,菜单中的元素无法操作 action.perform() # 该方法必须调用 sleep(3)# 左键 action.click(username) action.perform() # 该方法必须调用 sleep(2) # 双击 username.send_keys("admin") action.double_click(username) action.perform() sleep(3) # 拖拽, 起点元素和终点, 主要用于滑块验证码(以前) ll = driver.find_element_by_link_text('访问 新浪 网站') action.drag_and_drop(ll, username) action.perform() sleep(3) # 悬停 element = driver.find_element_by_xpath('//*[@id="zc"]/fieldset/button') action.move_to_element(element) action.perform() sleep(3)
验证码
# 验证码处理方式 # 去掉,设置万能验证码,验证码识别技术,记录cookiecookie_value = {'name':'BDUSS', 'value':'cookie'} driver.add_cookie(cookie_value) driver.refresh()
滚动条
# selenium没有专门操作滚动条的,但是可以用js代码来实现 js = 'window.scrollTo(0, 1000)'driver.execute_script(js) sleep(3)js = 'window.scrollTo(0, 0)' driver.execute_script(js) sleep(3)
Pytest(python自动化测试框架)
# 函数形式 pytest -s 1.py -s表示输出打印信息
def test_func():
print('我是测试函数')
# 测试类 类名必须以Test开头
class Test_demo(object):
def test_method1(self):
print('测试方法1')
def test_method2(self):
print('测试方法2')
# 主函数方法执行
import pytest
if __name__ == "__main__":
pytest.main(['-s', './2.py'])
class Test_demo():
def setup_class(self):# 类级别
print('start')
def teardown_class(self):# 类级别
print('end')
def setup(self):# 方法级别
print('开始')
def test_1(self):
print('1')
def test_2(self):
print('2')
def teardown(self):# 方法级别
print('结束')
# 控制顺序
import pytest
class Test_demo():
def setup_class(self):# 类级别
print('start')
def teardown_class(self):
print('end')
def setup(self):
print('开始')
@pytest.mark.run(order=2)# 控制执行顺序
def test_1(self):
print('1')
@pytest.mark.run(order=1)
@pytest.mark.skip('noreason') #跳过操作
def test_2(self):
print('2')
assert 1==2
@pytest.mark.parametrize('password, username', [('123456', 'li'), ('4444', 'e')]) #参数
def test_canshu(self, password, username):
print(username, password)
def teardown(self):
print('结束')
pytest执行顺序就是定义的顺序,而unittest顺序是根据ASCII码来的
pytest.ini
[pytest]
test_path=./
addopts=-s
--html=./test.html # 测试报告
--reruns 2 # 重跑
python_files=*.py
python_classes=Test*
python_functions=test*
断言直接使用assert
PO设计模式
Base:base.py get_driver.py
# base.py
from selenium.webdriver.support.wait import WebDriverWait
import time
class Base:
def __init__(self, driver):
self.driver = driver
def base_find_element(self, loc, timeout=30, poll=0.5):
return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).until(lambda x:x.find_element(*loc))
def base_click(self, loc):
self.base_find_element(loc).click()
def base_get_value(self, loc):
return self.base_find_element(loc).get_attribute('value')
def base_get_img(self):
self.driver.get_screenshot_as_file('./{}.png'.format(time.strftime('%Y_%m_%d_%H_%M_%S')))
#get_driver.py
from selenium import webdriver
import PO设计模式.v4.page as page
class GetDriver:
driver = None
@classmethod
def get_driver(cls):
if cls.driver == None:
cls.driver = webdriver.Chrome()
cls.driver.maximize_window()
cls.driver.get(page.url)
return cls.driver
@classmethod
def quit_driver(cls):
if cls.driver:
cls.driver.quit()
cls.driver = None
data: 主要放json数据
test.json
page:__init__.py、以及各种对页面的操作
#__init__.pyfrom selenium.webdriver.common.by import By url='http://cal.apple886.com/'xx = By.CSS_SELECtOR,"xx"
page: xx.py
from time import sleep
from PO设计模式.v4 import page
from PO设计模式.v4.base.base import Base
from selenium.webdriver.common.by import By
class xx(Base):
def page_click_xx(self):
self.base_click(page.xx)
...
scripts:放各种test类
import pytest
from PO设计模式.v4.base.get_driver import GetDriver
from PO设计模式.v4.page.page_cal import xx
from PO设计模式.v4.tool.read_json import read_json
def get_data():
data = read_json("xx.json")
# print(data)
"""
期望数据格式:[(xx,xx), (xx,xx), (xx,xx)]
"""
list = []
for n in data.values():
list.append((n["a"], n["b"], n["expect_result"]))
return list
class Testxx():
# driver = None
@classmethod
def setup_class(cls):
cls.driver = GetDriver().get_driver()
cls.xx = Pagexx(cls.driver)
@classmethod
def teardown_class(cls):
GetDriver().quit_driver()
@pytest.mark.parametrize('a,expect_result', get_data())
def test_add_cla(self,a,expect_result):
self.xx.page_add_xx(a)
result = ...
try:
self.assertEqual(result,str(expect_result))
except:
raise
finally:
pass
if __name__ == '__main__':
pytest.main('-s', 'test_xx.py', "--html='./result.html'")
tool:read_json.py
import json
def read_json(filename):
filepath ="../data/"+ filename
with open(filepath,"r",encoding="utf8") as f:
return json.load(f)



