selenium 学习

启动

firefox

安装foxmail driver

https://github.com/mozilla/geckodriver/releases

image-20221026164825695

这里写了当前driver满足的版本问题

image-20221026164845470

image-20221026164917410

这里用的虚拟环境 非虚拟环境直接放到使用的python的scripts目录下即可 保持与使用的python同级目录

image-20221026165058775

pip3 install selenium

image-20221026165620385

开个firefox

from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.baidu.com/")

image-20221026165948462

他说找不到moz:firefoxOptions.binary 也就是找不到firefox的二进制文件

那么我们就添加上

image-20221026183102091

Chrome

image-20221026184326544

image-20221026183443311

image-20221026183518779

image-20221026184431499

一键搭建

pip3 install webdriver-helper==1.0.1

image-20230217180248303

import time

from webdriver_helper import *
driver = get_webdriver()
# 默认chrome
driver.get("http://baidu.com")
# 访问百度
time.sleep(3)
driver.quit()

image-20230217180405829

import time

from webdriver_helper import *

with get_webdriver() as driver:
#类似文件操作
driver.get("http://baidu.com")

元素定位

根据文本定位

import time

from selenium.webdriver.common.by import By
from webdriver_helper import *

with get_webdriver() as driver:
#类似文件操作
driver.get("http://101.34.221.219:8010/")
time.sleep(3)
el = driver.find_element(By.LINK_TEXT,"登录")
print(el)
# 通过文本定位一个元素
el2 = driver.find_element(By.PARTIAL_LINK_TEXT,"登")
print(el2)

image-20230217200714695

属性定位

<input id="search-input" name="wd" type="text" placeholder="其实搜索很简单^_^ !" value="" autocomplete="off">
el = driver.find_element(By.ID,"search-input")
el = driver.find_element(By.NAME,"wd")
el = driver.find_element(By.CLASS_NAME,"search-group")
el = driver.find_element(By.TAG_NAME,"search-group")

通用定位

driver.find_element(By.CSS_SELECTOR,"#search-input")
driver.find_element(By.XPATH,"/html/body/div[6]/div/div[1]/div[2]/a[1]")

XPATH选择器

语法

  • / (开头) 根路径 /html/body/div
  • // 任意层级(包括下级 下级的下级) //div
  • @属性 //a[@target=”_top”]
  • /(中间) 下一级 //p/input
  • . 本级
  • .. 上一级

函数

  • text 获取元素内的文本

    $x("//a[text()='vivo X5MAX L 移动4G 八核超薄大屏5.5吋双卡手机vivoX5max']")
  • contains 任意位置包含

    $x("//a[contains(text(),'vivo')]")
  • starts-with 开头

    $x("//a[starts-with(text(),'vivo')]")

实践

登录一闪而过

image-20230218112012329

使用debugger 进行停止

先在控制台输入debugger 点击登录之后立即按回车

image-20230218112101323

image-20230218112141406

import pdb
import time

from selenium.webdriver.common.by import By
from webdriver_helper import *

# <input id="search-input" name="wd" type="text" placeholder="其实搜索很简单^_^ !" value="" autocomplete="off">
with get_webdriver() as driver:
#类似文件操作
driver.get("http://101.34.221.219:8010/")
driver.maximize_window()
# 窗口最大化
driver.find_element(By.XPATH,'//a[text()="登录"]').click()
time.sleep(0.5)
driver.find_element(By.XPATH,'//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH,'//input[@placeholder="请输入登录密码"]').send_keys("123123")
driver.find_element(By.XPATH,'//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH,'//p[@class="prompt-msg"]').text
assert msg=="登录成功"
time.sleep(3)
driver.find_element(By.XPATH,'//a[text()="vivo X5MAX L 移动4G 八核超薄大屏5.5吋双卡手机vivoX5max"]').click()
# print(driver.current_window_handle)
# 打印当前的窗口 id
# print(driver.window_handles[1])
# 打印所有的窗口 id 中的第2个
driver.switch_to.window(driver.window_handles[1])
print(driver.current_url)
# 打印当前窗口的url

driver.find_element(By.ID,"text_box").send_keys("2")
driver.find_element(By.XPATH,'//button[@title="点此按钮到下一步确认购买信息"]').click()
driver.switch_to.alert.accept()
# 接受弹框
driver.find_element(By.XPATH,'//span[text()="货到付款"]').click()
driver.switch_to.alert.accept()
driver.find_element(By.XPATH,'//button[@title="点击此按钮,提交订单"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH,'//p[@class="prompt-msg"]').text
assert msg=="操作成功"

pytest

pip3 install pytest

image-20230218124108318

import time

from selenium.webdriver.common.by import By
from webdriver_helper import get_webdriver



def test_login_ok():
with get_webdriver() as driver:
# 类似文件操作
driver.get("http://101.34.221.219:8010/")
driver.maximize_window()
# 窗口最大化
driver.find_element(By.XPATH, '//a[text()="登录"]').click()
time.sleep(0.5)
driver.find_element(By.XPATH, '//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH, '//input[@placeholder="请输入登录密码"]').send_keys("123123")
driver.find_element(By.XPATH, '//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "登录成功"
def test_login_fail():
with get_webdriver() as driver:
# 类似文件操作
driver.get("http://101.34.221.219:8010/")
driver.maximize_window()
# 窗口最大化
driver.find_element(By.XPATH, '//a[text()="登录"]').click()
time.sleep(0.5)
driver.find_element(By.XPATH, '//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH, '//input[@placeholder="请输入登录密码"]').send_keys("123123123123")
driver.find_element(By.XPATH, '//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "密码错误"

image-20230218124348450

def test_order_ok():
with get_webdriver() as driver:
driver.get("http://101.34.221.219:8010/")
driver.maximize_window()
driver.find_element(By.XPATH, '//a[text()="vivo X5MAX L 移动4G 八核超薄大屏5.5吋双卡手机vivoX5max"]').click()
# print(driver.current_window_handle)
# 打印当前的窗口 id
# print(driver.window_handles[1])
# 打印所有的窗口 id 中的第2个
driver.switch_to.window(driver.window_handles[1])
print(driver.current_url)
# 打印当前窗口的url

driver.find_element(By.ID, "text_box").send_keys("2")
driver.find_element(By.XPATH, '//button[@title="点此按钮到下一步确认购买信息"]').click()
driver.switch_to.alert.accept()
# 接受弹框
driver.find_element(By.XPATH, '//span[text()="货到付款"]').click()
driver.switch_to.alert.accept()
driver.find_element(By.XPATH, '//button[@title="点击此按钮,提交订单"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "操作成功"

由于这里没有登录 因此这里未通过

image-20230218124816797

夹具

import time

import pytest
from selenium.webdriver.common.by import By
from webdriver_helper import get_webdriver

@pytest.fixture()
# 添加装饰器
def driver():
driver = get_webdriver()
# 添加一个函数
return driver

def test_login_ok(driver):
#在测试中添加 夹具函数名字
driver.get("http://101.34.221.219:8010/")
driver.maximize_window()
# 窗口最大化
driver.find_element(By.XPATH, '//a[text()="登录"]').click()
time.sleep(0.5)
driver.find_element(By.XPATH, '//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH, '//input[@placeholder="请输入登录密码"]').send_keys("123123")
driver.find_element(By.XPATH, '//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "登录成功"

夹具的范围

这种写法会启动两次

@pytest.fixture()
def driver():
driver = get_webdriver()
driver.maximize_window()
driver.get("http://101.34.221.219:8010/")

# 前置部分,在测试用例之前执行
yield driver
# 后置部分,在测试用例之后执行
print("测试用例执行完成")
driver.quit()

scope

  • function 默认 每个用例执行一次
  • class 每个类执行一次
  • module 每个文件执行一次
  • package 每个包只执行一次
  • session 整个测试过程执行一次
@pytest.fixture(scope="session")
def driver():

注意修改的代码

import time

import pytest
from selenium.webdriver.common.by import By
from webdriver_helper import get_webdriver

@pytest.fixture(scope="session")
def driver():
driver = get_webdriver()
driver.maximize_window()
driver.get("http://101.34.221.219:8010/")

# 前置部分,在测试用例之前执行

yield driver
# 后置部分,在测试用例之后执行
print("测试用例执行完成")
driver.quit()

@pytest.fixture(scope="session")
def user_driver():
driver = get_webdriver()
driver.maximize_window()
# 前置部分,在测试用例之前执行
# 登录页面
driver.get("http://101.34.221.219:8010/?s=user/logininfo.html")
driver.find_element(By.XPATH, '//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH, '//input[@placeholder="请输入登录密码"]').send_keys("123123")
driver.find_element(By.XPATH, '//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "登录成功"

yield driver
# 后置部分,在测试用例之后执行
print("测试用例执行完成")
driver.quit()
def test_login_ok(driver):

driver.get("http://101.34.221.219:8010/")

# 窗口最大化
driver.find_element(By.XPATH, '//a[text()="登录"]').click()
time.sleep(0.5)
driver.find_element(By.XPATH, '//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH, '//input[@placeholder="请输入登录密码"]').send_keys("123123")
driver.find_element(By.XPATH, '//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "登录成功"
def test_login_fail(driver):
driver.delete_all_cookies()
# 删除所有cookies
driver.get("http://101.34.221.219:8010/")
driver.maximize_window()
# 窗口最大化
driver.find_element(By.XPATH, '//a[text()="登录"]').click()
time.sleep(0.5)
driver.find_element(By.XPATH, '//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH, '//input[@placeholder="请输入登录密码"]').send_keys("123123123123")
driver.find_element(By.XPATH, '//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "密码错误"

def test_order_ok(user_driver):
# 注意这里需要修改成 user_driver
user_driver.get("http://101.34.221.219:8010/")
user_driver.find_element(By.XPATH, '//a[text()="vivo X5MAX L 移动4G 八核超薄大屏5.5吋双卡手机vivoX5max"]').click()
# print(driver.current_window_handle)
# 打印当前的窗口 id
# print(driver.window_handles[1])
# 打印所有的窗口 id 中的第2个
user_driver.switch_to.window(user_driver.window_handles[1])
print(user_driver.current_url)
# 打印当前窗口的url

user_driver.find_element(By.ID, "text_box").send_keys("2")
user_driver.find_element(By.XPATH, '//button[@title="点此按钮到下一步确认购买信息"]').click()
user_driver.switch_to.alert.accept()
# 接受弹框
user_driver.find_element(By.XPATH, '//span[text()="货到付款"]').click()
user_driver.switch_to.alert.accept()
user_driver.find_element(By.XPATH, '//button[@title="点击此按钮,提交订单"]').click()
time.sleep(0.5)
msg = user_driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "操作成功"

image-20230218131629489

pages.py

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.expected_conditions import *

class BasePage:
_loc_msg ='//p[@class="prompt-msg"]'
def __init__(self,driver: webdriver.Chrome):
# 在实例化是创建的
self._driver = driver
self._wait = WebDriverWait(driver,10)
# 用来处理浏览器的等待时间 最长时间为10秒
def __getattr__(self, item):
key = f"_loc_"+item
xpath = getattr(self,key)
if xpath:
return self.get_element(xpath)
raise AttributeError("属性不存在异常")
def get_element(self,xpath):
"""
元素定位会自动等待
:param xpath:
:return:
"""
el = self._wait.until(
visibility_of_element_located((By.XPATH,xpath))
# 直到找到xpath结束 否则执行 10秒
)
return el
def alert_ok(self):
alert = self._wait.until(alert_is_present())
# 等待弹窗出现
alert.accept()
# 点击接受
class LoginPage(BasePage):
_loc_username = '//input[@data-validation-message="请填写登录账号"]'
_loc_password = '//input[@placeholder="请输入登录密码"]'
_loc_btn = '//button[text()="登录"]'
def login(self,username,password):
self.username.send_keys(username)
self.password.send_keys(password)
self.btn.click()
import time

import pytest
from selenium.webdriver.common.by import By
from webdriver_helper import get_webdriver
from pages import *
@pytest.fixture(scope="session")
def driver():
driver = get_webdriver()
driver.maximize_window()
driver.get("http://101.34.221.219:8010/")

# 前置部分,在测试用例之前执行

yield driver
# 后置部分,在测试用例之后执行
print("测试用例执行完成")
driver.quit()

@pytest.fixture(scope="session")
def user_driver():
driver = get_webdriver()
driver.maximize_window()
# 前置部分,在测试用例之前执行
# 登录页面
driver.get("http://101.34.221.219:8010/?s=user/logininfo.html")
driver.find_element(By.XPATH, '//input[@data-validation-message="请填写登录账号"]').send_keys("wanan")
driver.find_element(By.XPATH, '//input[@placeholder="请输入登录密码"]').send_keys("123123")
driver.find_element(By.XPATH, '//button[text()="登录"]').click()
time.sleep(0.5)
msg = driver.find_element(By.XPATH, '//p[@class="prompt-msg"]').text
assert msg == "登录成功"

yield driver
# 后置部分,在测试用例之后执行
print("测试用例执行完成")
driver.quit()
def test_login_ok(driver):

driver.get("http://101.34.221.219:8010/?s=user/logininfo.html")
page = LoginPage(driver)
page.login("wanan","123123")
assert page.msg.text == "登录成功"

image-20230218142011079

不同参数测试

import pytest


def test_a():
print("这是个测试用例")
@pytest.mark.parametrize('i',range(5))
def test_b(i):
print(f"这是第{i}个测试用例")

image-20230218163520168

多组测试用例 测试添加地址

pages.py

import pdb
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.expected_conditions import *

class BasePage:
_loc_msg ='//p[@class="prompt-msg"]'
def __init__(self,driver: webdriver.Chrome):
# 在实例化是创建的
self._driver = driver
self._wait = WebDriverWait(driver,10)
# 用来处理浏览器的等待时间 最长时间为10秒
def __getattr__(self, item):
key = f"_loc_"+item
xpath = getattr(self,key)
if xpath:
return self.get_element(xpath)
raise AttributeError("属性不存在异常")
def get_element(self,xpath):
"""
元素定位会自动等待
:param xpath:
:return:
"""
el = self._wait.until(
visibility_of_element_located((By.XPATH,xpath))
# 直到找到xpath结束 否则执行 10秒
)
return el
def alert_ok(self):
alert = self._wait.until(alert_is_present())
# 等待弹窗出现
alert.accept()
# 点击接受
class LoginPage(BasePage):
_loc_username = '//input[@data-validation-message="请填写登录账号"]'
_loc_password = '//input[@placeholder="请输入登录密码"]'
_loc_btn = '//button[text()="登录"]'
def login(self,username,password):
self.username.send_keys(username)
self.password.send_keys(password)
self.btn.click()
class AddressPage(BasePage):
_loc_new = '//button[@data-popup-title="新增地址"]'
_loc_name = '/html/body/div[1]/form/div[2]/input'
_loc_tel = '/html/body/div[1]/form/div[3]/input'
_loc_sheng = '/html/body/div[1]/form/div[4]/div[1]'
_loc_shi = '/html/body/div[1]/form/div[4]/div[2]'
_loc_qu = '/html/body/div[1]/form/div[4]/div[3]'
_loc_addr = '//*[@id="form-address"]'
_loc_btn = "/html/body/div[1]/form/div[7]/button"
def click_new(self):
self.new.click()
self.alert_ok()
iframe = self.get_element('//iframe[@src="http://101.34.221.219:8010/?s=useraddress/saveinfo.html"]')
self._driver.switch_to.frame(iframe)
# 这里是切换到iframe
def input_info(self,name,tel,sheng,shi,qu,addr):
self.name.send_keys(name)
self.tel.send_keys(tel)
self.div_select(self.sheng,sheng)
self.div_select(self.shi,shi)
self.div_select(self.qu,qu)
self.addr.send_keys(addr)

def div_select(self,el,value):
el.click()
el.find_element(By.XPATH,"./div/div/input").send_keys(value)
el.find_element(By.XPATH,'./div/ul/li').click()
def click_save(self):
self.btn.click()

p1.py

import pytest
from webdriver_helper import get_webdriver

from pages import *


@pytest.fixture(scope="session")
def user_driver():
driver = get_webdriver()
driver.maximize_window()
driver.get("http://101.34.221.219:8010/?s=user/logininfo.html")
login_page = LoginPage(driver)
login_page.login("wanan","123123")
assert login_page.msg.text == "登录成功"
driver.get("http://101.34.221.219:8010/?s=useraddress/index.html")

yield driver
driver.quit()
@pytest.mark.parametrize("name,tel,sheng,shi,qu,addr,msg",
[
["wanan","123456","北京市","东城区","东华门街道","一号楼","操作成功"],
["","","","","","","姓名格式 2~16 个字符之间"],
]
)
def test_new_address(user_driver,name,tel,sheng,shi,qu,addr,msg):
page = AddressPage(user_driver)
page.click_new()
page.input_info(name,tel, sheng, shi, qu, addr)
page.click_save()
assert page.msg.text == msg

image-20230219104520885