一、下拉选择框
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
url = ""
driver.get(url)
"""
目标:默认北京A
暂停2秒
1、定位 上海A
2、暂停2秒
3、定位 广州A
"""
# 使用CSS定位
sleep(2)
driver.find_element(By.CSS_SELECTOR, "[value='sh']").click()
sleep(2)
driver.find_element(By.CSS_SELECTOR, "[value='gz']").click()
sleep(2)
driver.quit()
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
url = ""
driver.get(url)
"""
目标:使用Select类实现操作option选项
暂停2秒
1、定位 上海A
2、暂停2秒
3、定位 广州A
注意:
1、Select类是通过select标签来控制其下的option元素
2、element:只能是select标签
"""
element = driver.find_element(By.CSS_SELECTOR, "#selectA")
sleep(2)
# 通过下标访问
Select(element).select_by_index(1)
sleep(2)
Select(element).select_by_index(2)
# 通过value值形式访问
Select(element).select_by_value("sh")
# 通过显示文本切换
Select(element).select_by_visible_text("A上海")
driver.quit()
二、弹出框
网页中常见的弹出框有三种
1、alert 警告框
2、confirm 确认框
3、prompt 提示框
"""
需求:
1、点击alert按钮
2、输入用户名admin
"""
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
url = ""
driver.get(url)
driver.find_element(By.CSS_SELECTOR, "#alerta").click()
# 切换到alert,默认返回alert对话框对象
alert = driver.switch_to.alert
# 处理对话框
alert.accept()
# 定位用户名输入admin
driver.find_element(By.CSS_SELECTOR, "#userA").send_keys("admin")
sleep(2)
driver.quit()
三、滚动条操作
滚动条:一种可控制页面显示范围的组件
from selenium import webdriver
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
url = "https://www.bilibili.com/"
driver.get(url)
# 滚动条操作
# 设置js控制滚动条语句
js = "window.scrollTo(0,1000)"
# 调用执行js语句方法
driver.execute_script(js)
四、frame切换
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
url = " "
driver.get(url)
# 主用户
driver.find_element(By.CSS_SELECTOR, "user").send_keys("admin")
driver.find_element(By.CSS_SELECTOR, "password").send_keys("123456")
driver.find_element(By.CSS_SELECTOR, ".tel").send_keys("12344445555")
# 切换到注册A
driver.switch_to.frame("myframe1")
# 用户A
driver.find_element(By.CSS_SELECTOR, "userA").send_keys("admin")
driver.find_element(By.CSS_SELECTOR, "passwordA").send_keys("123456")
driver.find_element(By.CSS_SELECTOR, ".telA").send_keys("12344445555")
# 切换到默认目录
driver.switch_to.default_content()
# 切换到注册B
driver.switch_to.frame("myframe2")
# 用户B
driver.find_element(By.CSS_SELECTOR, "userB").send_keys("admin")
driver.find_element(By.CSS_SELECTOR, "passwordB").send_keys("123456")
driver.find_element(By.CSS_SELECTOR, ".telB").send_keys("12344445555")
五、多窗口切换
在HTML页面中,当点击超链接或者按钮时,有的会在新的窗口打开页面
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
url = " "
driver.get(url)
# 获取当前窗口句柄 判断只要不是当前主窗口句柄,就一定是新开的窗口句柄
cur = driver.current_window_handle
# 点击注册A网页
driver.find_element(By.CSS_SELECTOR, "A网页").click()
# 获取所有窗口句柄
handles = driver.window_handles
# 判断不是当前窗口句柄
for c in handles:
if c != cur:
driver.switch_to.window(c)
# 主用户
driver.find_element(By.CSS_SELECTOR, "user").send_keys("admin")
driver.find_element(By.CSS_SELECTOR, "password").send_keys("123456")
driver.find_element(By.CSS_SELECTOR, ".tel").send_keys("12344445555")
六、窗口截图
把当前操作的网页,截图保存到指定位置
from time import sleep
from selenium import webdriver
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
url = "https://www.bilibili.com/"
driver.get(url)
# 调用截图方法
driver.get_screenshot_as_file("./admin.png")
# 动态获取文件名称 使用时间戳
driver.get_screenshot_as_file("../image/%s.png"%(time.strftime("%Y_%m_%d %H_%M_%S")))
sleep(2)
driver.quit()
七、验证码处理-cookie
验证码:一种随机生成的信息,为了防止恶意的请求行为,增加应用的安全性
from time import sleep
from selenium import webdriver
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(30)
# 设置cookie
url = "https://www.baidu.com/"
driver.get(url)
driver.add_cookie({"name": "BDUSS", "value": "根据实际情况编写"})
# 获取所有的cookies信息
""""
cookies = driver.get_cookies()
print("cookies内容为:", cookies)
for co in cookies:
print(co)
"""
cookie = driver.get_cookie("BDUSS")
print("cookies内容为:", cookie)
# 暂停2秒
sleep(2)
# 必须进行刷新才能看出效果
driver.refresh()
driver.quit()
八、UnitTest框架
UnitTest是python自带的一个单元测试框架,用它来做单元测试
为什么使用UnitTest框架?
1、能够组织多个用例去执行
2、提供丰富的断言方法
3、能够生成测试报告UnitTest核心要素
1、TestCase:测试用例
2、TestSuite:测试套件
3、TextTestRunner:以文本的形式运行测试用例
4、TestLoader:批量执行测试用例-搜索指定文件夹内指定字母开头的模块
5、Fixture:固定装置(两个固定的函数,一个初始化时使用,一个结束时使用)
定义测试用例
执行测试用例
"""
unittest框架--TestCase使用
步骤:
1、导包import unittest
2、新建类并继承 unittest.TestCase
3、测试方法必须test字母开头
案例:
编写求和测试函数
"""
import unittest
def add(x, y):
return x + y
class Test01(unittest.TestCase):
def test_add1(self):
result = add(1, 1)
print("结果为:", result)
def test_add2(self):
result = add(1, 3)
print("结果为:", result)
def test_add3(self):
result = add(1, 5)
print("结果为:", result)
"""
unittest框架--TestSuite使用
操作:
1、导包
2、实例化获取TestSuite对象
3、调用addTest方法添加用例到指定套件中
"""
import unittest
from scripts.test01_testcase import Test02
suite = unittest.TestSuite()
# 调用添加方法
# 写法1 类名(“方法名”),方法名称使用双引号
suite.addTest(Test02("test_add1"))
# 扩展 添加测试类中所有test开头的方法
suite.addTest(unittest.makeSuite(Test02))
# 执行测试套件
runner = unittest.TextTestRunner()
runner.run(suite)
"""
目标:演示TestLoader()类的用法
作用:搜索指定目录下指定开头的py文件,在py文件中搜索test开头测试方法
并且将这些方法添加到测试套件中
需求:
运行cases目录下test01.py-test05.py文件
操作:
1、导包
2、调用
3、执行
"""
import unittest
# suite = unittest.TestLoader().discover("../cases")
# 扩展:指定开头的模块
#suite = unittest.TestLoader().discover("../cases", pattern="shop.py")
# 扩展 使用缺省
suite = unittest.defaultTestLoader.discover("../cases")
unittest.TextTestRunner().run(suite)
TestLoader与TestSuite区别
1、TestSuite需要手动添加测试用例
2、TestLoader搜索指定目录下指定开头py文件,并添加测试类中所有的测试方法,不能指定添加测试方法
import unittest
class Test01(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUpClass被执行")
@classmethod
def tearDownClass(cls):
print("tearDownClass被执行")
def setUp(self):
print("setUp被执行")
def tearDown(self):
print("tearDown被执行")
def test01(self):
print("test01被执行")
def test02(self):
print("test02被执行")
def test03(self):
print("test03被执行")
九、断言
让程序代替人为判断测试程序执行结果是否符合预期结果的过程
import unittest
"""
目标:unittest常用断言
"""
class Test01(unittest.TestCase):
def test01(self):
flag = True
self.assertTrue(flag)
# 判断两个字符串是否相等
#self.assertEqual("你好", "您好")
# 判断后边的字符串是否包含前边的字符串
self.assertIn("hello", "hello,world!")
"""
目标:断言练习
案例:
输入:正确用户名和密码 验证码为空
断言:提示信息是否为,验证码不能为空!
要求:如果断言出错,截屏保存
"""
# 导包
import unittest
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
# 定义测试类并继承unittest.TestCase
class TestLogin(unittest.TestCase):
# 定义初始化方法
def setUp(self):
# 获取浏览器驱动对象
self.driver = webdriver.Chrome()
# 打开url
url = ""
self.driver.get(url)
# 最大化浏览器
self.driver.maximize_window()
# 隐式等待
self.driver.implicitly_wait(30)
# 定义teardown
def tearDown(self):
# 关闭浏览器驱动
sleep(3)
self.driver.quit()
# 定义登录测试方法 验证码为空
def test_login_code_null(self):
driver = self.driver
# 点击登录连接
driver.find_element(By.PARTIAL_LINK_TEXT, "登录").click()
# 输入用户名
driver.find_element(By.CSS_SELECTOR, "#username").send_keys("12344445555")
# 输入密码
driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123456")
# 输入验证码
driver.find_element(By.CSS_SELECTOR, "#verify_code").send_keys("")
# 点击登录
driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()
# 获取登录后提示信息
result = driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
# 定义预期结果
expect_result = "验证码不能为空!"
try:
# 断言
self.assertEqual(result, expect_result)
except AssertionError:
# 截图
driver.get_screenshot_as_file("../error.png")
# 抛异常
raise
十、参数化
根据需求动态获取参数并引用的过程
应用场景:解决相同业务逻辑,不同测试数据问题
import unittest
from parameterized import parameterized
"""
目标:parameterized插件应用
步骤:
1、导包
2、修饰测试函数 @parameterized.expand(列表类型数据)
3、在测试函数中使用变量接收,传递过来的值
语法:
1、单个参数:值为列表
2、多个参数:值为列表嵌套元组 如:[(1,2,3),(2,3,4)]
"""
class Test01(unittest.TestCase):
@parameterized.expand(["1", "2", "3"])
def test_add(self, num):
print("num:", num)
@parameterized.expand([(1, 2, 3), (4, 5, 9), (7, 8, 15)])
def test_add_more(self, a, b, result):
print("{}+{}={}:".format(a, b, result))
十一、跳过
对于一些未完成的或者不满足测试条件的测试函数和测试类,可以跳过执行
使用方式
import unittest
version = 30
# @unittest.skip("Test01方法暂未实现")
class Test01(unittest.TestCase):
def test01(self):
print("test01")
@unittest.skipIf(version > 25, "版本大于25了,跳过此用例")
def test02(self):
print("test02")
十二、HTML报告生成
import time
import unittest
from Day5.tools.HTMLTestRunner import HTMLTestRunner
"""
目标:基于unittest框架执行生成html报告
操作:
1、复制HTMLTestRunner.py文件到指定目录
2、导包from HTMLTestRunner import HTMLTestRunner
3、获取报告存放文件流,并实例化HTMLTestRunner类,执行run方法
"""
# 定义测试套件
suite = unittest.defaultTestLoader.discover("../scripts", pattern="test*.py")
# 定义报告存放路径及文件名称
report_dir = "../report/{}.html".format(time.strftime("%Y_%m_%d %H_%M_%S"))
# 获取报告文件流 并执行
with open(report_dir, "wb") as f:
HTMLTestRunner(stream=f, verbosity=2, title="XX项目自动化测试报告", description="操作系统win10").run(suite)
open与with open区别:
1、共同点:打开文件
2、不同点:with open = 执行打开操作+关闭操作
十三、PO模式
1、V1
案例:用户名不存在
# 导包
from selenium import webdriver
from selenium.webdriver.common.by import By
# 获取driver对象
driver = webdriver.Chrome()
# 最大化浏览器
driver.maximize_window()
# 隐式等待
driver.implicitly_wait(30)
# 打开url
driver.get("url")
# 点击登录连接
driver.find_element(By.PARTIAL_LINK_TEXT, "登录").click()
# 输入用户名
driver.find_element(By.CSS_SELECTOR, "#username").send_keys("admin")
# 输入密码
driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123456")
# 输入验证码
driver.find_element(By.CSS_SELECTOR, "#verify_code").send_keys("1111")
# 点击登录按钮
driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()
# 获取错误提示信息
msg = driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
print("msg:", msg)
# 断言
assert msg == "用户名不存在!"
# 点击提示框确定按钮
driver.find_element(By.CSS_SELECTOR, ".layui-layer-btn0").click()
# 关闭
driver.quit()
案例:密码错误
# 导包
from selenium import webdriver
from selenium.webdriver.common.by import By
# 获取driver对象
driver = webdriver.Chrome()
# 最大化浏览器
driver.maximize_window()
# 隐式等待
driver.implicitly_wait(30)
# 打开url
driver.get("url")
# 点击登录连接
driver.find_element(By.PARTIAL_LINK_TEXT, "登录").click()
# 输入用户名
driver.find_element(By.CSS_SELECTOR, "#username").send_keys("admin")
# 输入密码
driver.find_element(By.CSS_SELECTOR, "#password").send_keys("123456789")
# 输入验证码
driver.find_element(By.CSS_SELECTOR, "#verify_code").send_keys("1111")
# 点击登录按钮
driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()
# 获取错误提示信息
msg = driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
print("msg:", msg)
# 断言
assert msg == "密码错误!"
# 点击提示框确定按钮
driver.find_element(By.CSS_SELECTOR, ".layui-layer-btn0").click()
# 关闭
driver.quit()
缺点:无法批量运行
2、V2
# 导包
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
# 新建测试类 并继承
class TestLogin(unittest.TestCase):
@classmethod
# 初始化 setUp
def setUpClass(cls):
# 获取driver对象
cls.driver = webdriver.Chrome()
# 最大化浏览器
cls.driver.maximize_window()
# 隐式等待
cls.driver.implicitly_wait(30)
# 打开url
cls.driver.get("url")
# 点击登录连接
cls.driver.find_element(By.PARTIAL_LINK_TEXT, "登录").click()
# 结束 tearDown
@classmethod
def tearDownClass(cls):
# 关闭浏览器
cls.driver.quit()
# 新建测试方法 用户名不存在
def test_login_username_not_exist(self):
# 输入用户名
username = self.driver.find_element(By.CSS_SELECTOR, "#username")
username.clear()
username.send_keys("admin")
# 输入密码
pwd = self.driver.find_element(By.CSS_SELECTOR, "#password")
pwd.clear()
pwd.send_keys("123456")
# 输入验证码
code = self.driver.find_element(By.CSS_SELECTOR, "#verify_code")
code.clear()
code.send_keys("1111")
# 点击登录按钮
self.driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()
# 获取错误提示信息
msg = self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
print("msg:", msg)
try:
# 断言
self.assertEqual(msg, "账号不存在!")
# 点击提示框确定按钮
self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-btn0").click()
except AssertionError:
# 截图
self.driver.get_screenshot_as_file("../report/fail.png")
# 新建测试方法 密码错误
def test_login_password_error(self):
# 输入用户名
username = self.driver.find_element(By.CSS_SELECTOR, "#username")
username.clear()
username.send_keys("admin")
# 输入密码
pwd = self.driver.find_element(By.CSS_SELECTOR, "#password")
pwd.clear()
pwd.send_keys("123456789")
# 输入验证码
code = self.driver.find_element(By.CSS_SELECTOR, "#verify_code")
code.clear()
code.send_keys("1111")
# 点击登录按钮
self.driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()
# 获取错误提示信息
msg = self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
print("msg:", msg)
try:
# 断言
self.assertEqual(msg, "密码错误!")
# 点击提示框确定按钮
self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-btn0").click()
except AssertionError:
# 截图
self.driver.get_screenshot_as_file("../report/fail.png")
缺点:业务脚本与页面对象没有分开
3、V3
"""
页面对象层
页面对象编写技巧:
类名:使用大驼峰将模块名称写进来,有下划线去掉
方法:根据业务需求每个操作步骤单独封装一个方法
方法名:page_XXX
"""
from selenium import webdriver
from selenium.webdriver.common.by import By
class PageLogin:
# 初始化
def __init__(self):
# 获取driver对象
self.driver = webdriver.Chrome()
# 最大化浏览器
self.driver.maximize_window()
# 隐式等待
self.driver.implicitly_wait(30)
# 打开url
self.driver.get("url")
# 点击登录连接
def page_click_login_link(self):
self.driver.find_element(By.PARTIAL_LINK_TEXT, "登录").click()
# 输入用户名
def page_input_username(self, username):
self.driver.find_element(By.CSS_SELECTOR, "#username").send_keys(username)
# 输入密码
def page_input_pwd(self, pwd):
self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys(pwd)
# 输入验证码
def page_input_verify_code(self, code):
self.driver.find_element(By.CSS_SELECTOR, "#verify_code").send_keys(code)
# 点击登录
def page_click_login_btn(self):
self.driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()
# 获取异常提示信息
def page_get_text(self):
return self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
# 点击提示框确定按钮
def page_click_err_btn_ok(self):
self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-btn0").click()
# 组装登录业务方法 给业务层调用
def page_login(self, username, pwd, code):
self.page_click_login_link()
self.page_input_username(username)
self.page_input_pwd(pwd)
self.page_input_verify_code(code)
self.page_click_login_btn()
# 业务层
# 导包
import unittest
from parameterized import parameterized
from Day6.v3.page.page_login import PageLogin
# 新建测试类
class TestLogin(unittest.TestCase):
# 初始化方法
def setUp(self):
# 获取登录页面对象
self.login = PageLogin()
# 结束方法
def tearDown(self):
# 关闭驱动对象
self.login.driver.quit()
# 新建测试方法
@parameterized.expand([("123444455555", "123", "1111", "账号不存在"), ("111444455555", "123345", "1111", "密码错误")])
def test_login(self, username, pwd, code, expect):
# 调用测试登录方法
self.login.page_login(username, pwd, code)
# 获取登录后的信息
msg = self.login.page_get_text()
try:
# 断言
self.assertEqual(msg, expect)
# 点击确定
self.login.page_click_err_btn_ok()
except AssertionError:
# 截图
pass
缺点: 代码冗余
4、V6
结构:
1、base(基类):page页面一些公共的方法
2、page(页面对象):一个页面封装成一个对象,继承base
3、scripts(业务层):导包调用page页面
"""base.py"""
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
class Base:
# 初始化
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("url")
pass
# 查找元素方法(提供:点击、输入、获取文本)使用
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_input(self, loc, value):
el = self.base_find_element(loc)
# 清空
el.clear()
# 输入
el.send_keys(value)
# 获取文本方法
def base_get_text(self, loc):
# 注意:一定要返回元素的文本信息
return self.base_find_element(loc).text
# 截图方法
def base_get_image(self):
self.driver.get_screenshot_as_file("../image/fail.png")
"""
__init__.py
以下为登录页面元素配置信息,临时存放地
"""
from selenium.webdriver.common.by import By
login_link = By.PARTIAL_LINK_TEXT, "登录"
login_username = By.ID, "username"
login_pwd = By.ID, "password"
login_verify_code = By.ID, "verify_code"
login_btn = By.CSS_SELECTOR, ".J-login-submit"
login_err_info = By.CSS_SELECTOR, ".layui-layer-content"
login_err_btn_ok = By.CSS_SELECTOR, ".layui-layer-btn0"
""" page_login.py """
from Day6.v6 import page
from Day6.v6.base.base import Base
class PageLogin(Base):
# 点击登录链接
def page_click_login_link(self):
self.base_click(page.login_link)
# 输入用户名
def page_input_username(self, username):
self.base_input(page.login_username, username)
# 输入密码
def page_input_pwd(self, pwd):
self.base_input(page.login_pwd, pwd)
# 输入验证
def page_input_verify_code(self, code):
self.base_input(page.login_verify_code, code)
# 点击登录按钮
def page_click_login_btn(self):
self.base_click(page.login_btn)
# 获取异常提示信息
def page_get_error_info(self):
return self.base_get_text(page.login_err_info)
# 点击异常信息框 确定
def page_click_err_btn_ok(self):
self.base_click(page.login_err_btn_ok)
# 截图
def page_get_screenshot(self):
self.base_get_image()
# 组合业务方法
def page_login(self, username, pwd, code):
self.page_input_username(username)
self.page_input_pwd(pwd)
self.page_input_verify_code(code)
self.page_click_login_btn()
# 导包
""" test_login.py """
import unittest
from Day6.v6.page.page_login import PageLogin
from parameterized import parameterized
def get_data():
return [("123444455555", "123", "1111", "账号不存在"),
("111444455555", "123345", "1111", "密码错误")]
# 新建测试类 并继承
class TestLogin(unittest.TestCase):
# setUp
def setUp(self):
# 实例化获取页面对象PageLogin
self.login = PageLogin()
# 点击登录链接
self.login.page_click_login_link()
# tearDown
def tearDown(self):
# 关闭driver驱动对象
self.login.driver.quit()
# 登录测试方法
@parameterized.expand(get_data())
def test_login(self, username, pwd, code, expect_result):
# 调用登录方法
self.login.page_login(username, pwd, code)
# 获取登录提示信息
msg = self.login.page_get_error_info()
try:
# 断言
self.assertEqual(msg, expect_result)
except AssertionError:
# 截图
self.login.page_get_screenshot()