测试学习记录,仅供参考!
一、 PO(POM)设计模式代码实现
管理页面类和页面元素
1、在项目根目录下新建名称为 pageObject(用来管理页面类) 的软件包,在 pageObject 软件包下新建名称为 login_page(登录页面) 的目录文件,在 login_page 目录下新建名称为 login_page.py 的 Python 文件;
定义一个测试类,因为 class LoginPage 是一个页面类,所以不需要以 test 开头;这个页面类里面去维护一些元素定位和操作,首先得先导入定位元素 By 类 ,这里写一个类变量,使用类属性,不需要 __init__ 初始化为实例属性,一般正常写法是“self.driver.find_element(By.NAME, 'username')”,但是每一个都这么写的话很不方便,此时需要引入前面介绍过的二次封装(找到元素方法)方法,导入 BasePage 类,然后使用页面类去继承 BasePage 类(这样页面类就可以用到已经封装好的公共方法了)
把被测试页面的 url 地址、用户名、密码、登录按钮等都放到页面类里面管理,先完成“元素”,再继续“操作”,例如:第一个 登录操作,定义一个 def login(): 函数,登录里面带两个参数(self, user_name, pass_word):就是要输入的操作,输入的用户名(user_name)和密码(pass_word),使用 self.open_url()(因为页面类已经继承了公共的webdriver 二次封装方法,所以可以使用 BasePage 类里面的任何属性和方法) 打开页面,里面把 url 传过来,还是通过 self.url 调用这个 LoginPage 类 url 变量(self.url 中的 self 是表示类本身的意思),下一步跟着输入操作(输入操作亦已经封装了,同样的通过 self. 点调用,注意二次封装方法的参数若有默认值的可以不填)
为什么要对 webdriver 里面的方法进行二次封装,为了页面类使用的时候更方便,不用每一个都去写一个“去查找、去定位 driver.find_element(By.NAME, 'username')”,简化了代码量,这就是二次封装的一个好处;
from selenium.webdriver.common.by import By
from util_tools.basePage import BasePage
class LoginPage(BasePage):
url = 'http://localhost:8088/ecshop/user.php'
# 用户名
username = (By.NAME, 'username')
# 密码
password = (By.NAME, 'password')
# 登录按钮
submit = (By.NAME, 'submit')
# 登录操作
def login(self, user_name, pass_word):
# 打开网址
self.open_url(self.url)
# 输入用户名
self.send_keys(self.username, user_name)
# 输入密码
self.send_keys(self.password, pass_word)
# 点击登录按钮
self.click(self.submit)
至此,登录页面的第一个操作“登录操作”就已经封装完成了;
管理测试类
2、改造 testcase 软件包 login 目录下 test_login.py 文件;
先导包引入 LoginPage 类,登录成功里面的‘打开浏览器’、‘定位信息’、已经在上一步的页面类中维护了(元素),所以不需要了;一些输入的操作也是在页面类(操作)中维护,亦不需要了;这时候需要直接用到页面类,把导进来的 LoginPage 类直接用就行了;
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep
from pageObject.login_page.login_page import LoginPage
class TestLogin:
# 前置操作
def setup(self):
# 前面加上 self. 把它变成全局的,就可以在其他测试用例中调用这个对象了
self.driver = webdriver.Edge()
# 登录成功
def test_login_success(self):
# 传浏览器对象--再把结果返回
login_page = LoginPage(self.driver)
# 直接调用页面类中的 login 操作--里面需要输入两个参数(后续参数化)
login_page.login('admin123', '123456')
# 断言结果
success_ele = self.driver.find_element(By.XPATH, '//*[@id="ECS_MEMBERZONE"]/font/font')
assert success_ele != ''
sleep(2)
# 登录失败
def test_login_failed(self):
login_page = LoginPage(self.driver)
login_page.login('admin123', '123456789')
# 断言结果
assert '系统提示' in self.driver.title
sleep(2)
# 后置操作
def teardown(self):
# 关闭浏览器
self.driver.quit()
现在,测试类里面的一些操作就不用关心 ‘元素定位信息和操作了’,只需要去调用页面类里面的操作就行了;
写这个的好处就是 后续某个页面发生变更时,只需维护某个页面相关的定位即可;这就是 POM 的设计模式,简单理解就是“页面、对象、分离”;
3、后面使用参数化通过一个测试用例实现多种场景;
4、这是第一个页面‘登录页面(login_page)’,后续其他页面可以继续编写,例如第二个页面‘注册页面(register_page)’等等;
其他
在 pageObject 软件包下新建名称为 register_page(注册 页面) 的目录文件,在 register_page 目录下新建名称为 register_page.py 的 Python 文件;
与之相对应的,在 testcase 软件包下新建 register 目录文件,在 register 目录下 test_register.py 文件,用于编写注册页面的测试脚本;达到‘页面元素定位’、‘操作’和‘测试脚本’分离,这是一个稍微双耦合的效果;
二、使用Pytest设置全局的浏览器驱动对象
class TestCase:
# 前置操作
def setup(self):
self.driver = webdriver.Edge()
# 后置操作
def teardown(self):
self.driver.quit()
1、若在每一个测试用例里面均写上前后置操作,如果测试用例有很多个,几百上千个等等,要是每一个都写上前后置操作就会比较麻烦,所以对前后置部分做一个改造;优化前后置操作,使用 conftest.py 和 fixture 装饰器相结合实现全局的前后置应用;
2、找到 testcase 软件包下的 conftest.py 文件(若无此文件则新建一个),开始优化;
写一个前置操作 def get_driver(): 获取浏览器对象
import pytest
from selenium import webdriver
from util_tools.logs_util.recordlog import logs
@pytest.fixture(autouse=True)
def log_outputs():
logs.info('------测试用例开始执行testcase------')
yield
logs.info('------测试用例执行完毕testcase------')
@pytest.fixture()
def get_driver():
# 初始化浏览器对象
driver = webdriver.Chrome()
# 设置一个全局的隐式等待时间
driver.implicitly_wait(10)
# 最大化浏览器窗口
driver.maximize_window()
yield driver
# 后置操作--关闭浏览器
driver.quit()
3、在 test_login.py 调用前后置 def get_driver(): 操作;进一步优化;
from selenium.webdriver.common.by import By
from time import sleep
from pageObject.login_page.login_page import LoginPage
class TestLogin:
# 登录成功
def test_login_success(self, get_driver):
# 传浏览器对象--再把结果返回
login_page = LoginPage(get_driver)
# 直接调用页面类中的 login 操作--里面需要输入两个参数(后续参数化)
login_page.login('admin123', '123456')
# 断言结果
success_ele = get_driver.find_element(By.XPATH, '//*[@id="ECS_MEMBERZONE"]/font/font')
assert success_ele != ''
sleep(2)
# 登录失败
def test_login_failed(self, get_driver):
login_page = LoginPage(get_driver)
login_page.login('admin123', '123456789')
# 断言结果
assert '系统提示' in get_driver.title
sleep(2)
优化之后,测试类中就比较简洁了,就写了两个测试用例;把其他操作都放到 conftest.py 文件中的前后置操作中;
4、运行主函数 run.py 文件可以查看到刚刚添加的浏览器最大化;
5、把初始化浏览器做到配置文件中;
6、更改项目根目录 config 软件包下 setting.py 文件;
# 导包
import os
import sys
DIR_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(DIR_PATH)
# 显示等待时间设置,默认为10秒
WAIT_TIME = 10
# 设置浏览器
browser_type = 'chrome'
# 文件路径
FILE_PATH = {
'log': os.path.join(DIR_PATH, 'log'),
'screenshot': os.path.join(DIR_PATH, 'screenshot')
}
7、再优化一下 conftest.py 文件;
导入刚刚定义的 browser_type 变量,在初始化浏览器对象时做个 if 判断 browser_type 这个变量 .点 调用 capitalize() 函数(首字母转成大写) == 等于 'Chrome'、'Edge'、'Firefox' 成立的话,就初始化相对应的 'Chrome'、'Edge'、'Firefox' 浏览器对象;后续需要用到哪个浏览器做测试,就更改 setting.py 文件中的 browser_type 变量即可;
import pytest
from selenium import webdriver
from util_tools.logs_util.recordlog import logs
from config.setting import browser_type
@pytest.fixture(autouse=True)
def log_outputs():
logs.info('------测试用例开始执行testcase------')
yield
logs.info('------测试用例执行完毕testcase------')
@pytest.fixture()
def get_driver():
# 初始化浏览器对象
if browser_type.capitalize() == 'Chrome':
driver = webdriver.Chrome()
elif browser_type.capitalize() == 'Edge':
driver = webdriver.Edge()
elif browser_type.capitalize() == 'Firefox':
driver = webdriver.Firefox()
# 设置一个全局的隐式等待时间
driver.implicitly_wait(10)
# 最大化浏览器窗口
driver.maximize_window()
yield driver
driver.quit()
8、还可以继续优化 conftest.py 文件;把代码写的稍微好看一点,不需要很多 if else elif 的;使用字典的方式去替代 if else 嵌套;
import pytest
from selenium import webdriver
from util_tools.logs_util.recordlog import logs
from config.setting import browser_type
@pytest.fixture(autouse=True)
def log_outputs():
logs.info('------测试用例开始执行testcase------')
yield
logs.info('------测试用例执行完毕testcase------')
@pytest.fixture()
def get_driver():
# 初始化浏览器对象--字典
browser_mapping = {
'Chrome': webdriver.Chrome,
'Edge': webdriver.Edge,
'Firefox': webdriver.Firefox
}
# 判断配置文件 browser_type 变量值包含在 browser_mapping 字典里面
if browser_type.capitalize() in browser_mapping:
driver = browser_mapping.get(browser_type.capitalize())()
# 设置一个全局的隐式等待时间
driver.implicitly_wait(10)
# 最大化浏览器窗口
driver.maximize_window()
yield driver
driver.quit()
判断配置文件 browser_type 变量值包含在 browser_mapping 字典里面,就可以使用 browser_mapping 字典去调用 .get() 方法,把 browser_type.capitalize() 放到 .get(browser_type.capitalize()) 方法里面;注意后面再带上一个 () 小括号,因为定义字典时没写括号,所以这里带括号并且引用它,把结果返回出去;
@pytest.fixture()
def get_driver():
# 初始化浏览器对象--if判断
if browser_type.capitalize() == 'Chrome':
driver = webdriver.Chrome()
elif browser_type.capitalize() == 'Edge':
driver = webdriver.Edge()
elif browser_type.capitalize() == 'Firefox':
driver = webdriver.Firefox()
# 字典
browser_mapping = {
'Chrome': webdriver.Chrome,
'Edge': webdriver.Edge,
'Firefox': webdriver.Firefox
}
# 判断配置文件 browser_type 变量值包含在 browser_mapping 字典里面
if browser_type.capitalize() in browser_mapping:
driver = browser_mapping.get(browser_type.capitalize())()
# 设置一个全局的隐式等待时间
driver.implicitly_wait(10)
# 最大化浏览器窗口
driver.maximize_window()
yield driver
driver.quit()
9、通过配置文件读取等待时间,不写固定,导入引用;
import pytest
from selenium import webdriver
from util_tools.logs_util.recordlog import logs
from config.setting import browser_type, WAIT_TIME
@pytest.fixture(autouse=True)
def log_outputs():
logs.info('------测试用例开始执行testcase------')
yield
logs.info('------测试用例执行完毕testcase------')
@pytest.fixture()
def get_driver():
# 初始化浏览器对象--字典
browser_mapping = {
'Chrome': webdriver.Chrome,
'Edge': webdriver.Edge,
'Firefox': webdriver.Firefox
}
# 判断配置文件 browser_type 变量值包含在 browser_mapping 字典里面
if browser_type.capitalize() in browser_mapping:
driver = browser_mapping.get(browser_type.capitalize())()
# 设置一个全局的隐式等待时间
driver.implicitly_wait(WAIT_TIME)
# 最大化浏览器窗口
driver.maximize_window()
yield driver
driver.quit()
10、黄色警告,作用域问题

11、设置全局变量;

import pytest
from selenium import webdriver
from util_tools.logs_util.recordlog import logs
from config.setting import browser_type, WAIT_TIME
@pytest.fixture(autouse=True)
def log_outputs():
logs.info('------测试用例开始执行testcase------')
yield
logs.info('------测试用例执行完毕testcase------')
@pytest.fixture()
def get_driver():
# 将driver设置为全局变量
global driver
# 初始化浏览器对象--字典
browser_mapping = {
'Chrome': webdriver.Chrome,
'Edge': webdriver.Edge,
'Firefox': webdriver.Firefox
}
# 判断配置文件 browser_type 变量值包含在 browser_mapping 字典里面
if browser_type.capitalize() in browser_mapping:
driver = browser_mapping.get(browser_type.capitalize())()
# 设置一个全局的隐式等待时间
driver.implicitly_wait(WAIT_TIME)
# 最大化浏览器窗口
driver.maximize_window()
yield driver
driver.quit()
未完待续。。。
 设计模式代码实现和全局浏览器驱动设置&spm=1001.2101.3001.5002&articleId=153828774&d=1&t=3&u=615333575ce44ddb921ae755393ce7a9)
6463

被折叠的 条评论
为什么被折叠?



