项目目录:
1.先在手工测试用例中写好测试步骤,然后复制测试步骤到注释中,方便编写代码步骤
2.测试数据分离
3.浏览器驱动分离
4.封装可复用的代码
什么是PO模式?
PO:page object,页面对象模型,page代表我们需要操作的页面,把页面中的操作封装到一个类里,需要用到的url放到类的属性里;
每个方法对应每个页面的操作,需要用到时再去调用类里面的方法;
本质上就是封装代码,复用代码的一种思路。
作用:
1、提高代码可读性, 2、提高代码复用性 3、简化代码 4、页面操作和测试用例隔离 5、扩展和可维护
import pytest from selenium import webdriver from selenium.webdriver.common.by import By from pages.login_page import LoginPage from data.login_data import login_fail # po模式好处 # 1、 测试函数中的代码变得更加精简。 # 2、 可读性变强 # 3、 页面操作封装完成,隔离管理;前端发生变化,只需要维护po操作, 如果修改用例数据,只需要维护数据 # 4、 po 页面的操作是可以重复使用的。 # PO, page object, page object model, POM # PO模式, 页面对象模型 class TestSignIn: def test_sign_in(self, login_page): """测试登录功能 步骤: 1、输入登录url: https://v4.ketangpai.com/User/login.html 2、输入用户名: aaa, name=account 3、输入密码 123, name=pass 4、点击登录按钮, css=.btn-btn :return: """ # 1、隔离测试数据,当需要添加,修改数据时可以在单独的模块中修改。 username = login_fail["username"] password = login_fail["password"] expected = login_fail["expected"] # 2、浏览器管理应该可以重复使用,单独封装 # 3、需要把驱动进行隔离管理,1,可以存储多个浏览器驱动, 2、想用哪个用哪个 # 4、base url 域名,ip # 访问url login_page.load() # 5、登录操作可以重复使用:可以重复使用到什么地步?是该项目通用,还是所有的 # 项目通过 # 6、登录操作:记住状态, token, session, cookie 优化 # po 模式 # 其实就是将下面复杂的代码封装成一个函数,提高代码可读性 # # 输入用户名 # username_el = browser.find_element(By.NAME, 'account') # username_el.clear() # username_el.send_keys(username) # # 输入密码 # browser.find_element(By.NAME, 'pass').send_keys(password) # # 点击登录 # browser.find_element(By.CSS_SELECTOR, '.btn-btn').click() login_page.login(username, password) # 获取文本 actual = login_page.get_error_tips() # actual = browser.find_element(By.CSS_SELECTOR, '.error-tips').get_attribute('name') assert actual == expected
数据分离:
在data.login_data.py
# 单条用例数据 login_fail = {"username": "aaa", "password": "123", "expected": "密码有效长度是6到30个字符"}
存储夹具:
在conftest中存储,好处是在测试用例中不需要再导入
""" 存储所有的夹具, 好处:在测试用例中使用夹具时不需要导入 """ import pytest import os from selenium import webdriver from setting import config from pages.login_page import LoginPage driver = os.path.join(config.driver_dir, 'chromedriver') def get_browser(): """获取浏览器""" browser = webdriver.Chrome(executable_path=driver) browser.implicitly_wait(5) browser.maximize_window() return browser @pytest.fixture() def browser():
"""打开浏览器,执行用例,关闭浏览器""" driver = get_browser() yield driver driver.quit() @pytest.fixture() def login_page(browser):
"""初始化对象""" return LoginPage(browser)
封装路径:
"""配置选项""" import os # 获取 config.py当前文件的路径 current_path = os.path.abspath(__file__) # 配置文件目录的路径 setting/ 的路径 config_dir = os.path.dirname(current_path) # 项目的根目录 root_dir = os.path.dirname(config_dir) # 测试数据的目录路径 data/ data_dir = os.path.join(root_dir, 'data') # 测试用例文件路径 case_file = os.path.join(data_dir, 'cases.xlsx') # host 域名 host = 'https://v4.ketangpai.com' # 驱动目录 driver_dir = os.path.join(root_dir, 'drivers')
在pages目录下存储所有的页面操作
from selenium.webdriver.common.by import By class LoginPage: url = 'https://v4.ketangpai.com/User/login.html' # title = '登录' def __init__(self, browser): self.browser = browser def load(self): """加载页面""" self.browser.get(self.url) def login(self, username, password): """登录""" username_el = self.browser.find_element(By.NAME, 'account') username_el.clear() username_el.send_keys(username) # 输入密码 self.browser.find_element(By.NAME, 'pass').send_keys(password) # 点击登录 self.browser.find_element(By.CSS_SELECTOR, '.btn-btn').click() def get_error_tips(self): """获取错误信息""" return self.browser.find_element(By.CSS_SELECTOR, '.error-tips').text
用例优化结果:
import pytest from selenium import webdriver from selenium.webdriver.common.by import By from pages.login_page import LoginPage from data.login_data import login_fail # 好处 # 1、 测试函数中的代码变得更加精简。 # 2、 可读性变强 # 3、 页面操作封装完成,隔离管理;前端发生变化,只需要维护po操作, 如果修改用例数据,只需要维护数据 # 4、 po 页面的操作是可以重复使用的。 # PO, page object, page object model, POM # PO模式, 页面对象模型 class TestSignIn: def test_sign_in(self, login_page): """测试登录功能 步骤: 1、输入登录url: https://v4.ketangpai.com/User/login.html 2、输入用户名: aaa, name=account 3、输入密码 123, name=pass 4、点击登录按钮, css=.btn-btn :return: """ # 1、数据 username = login_fail["username"] password = login_fail["password"] expected = login_fail["expected"] # 2、获取实际结果 login_page.load() login_page.login(username, password) actual = login_page.get_error_tips() # 3、断言 assert actual == expected