在上一节中,我们了解了PO设计模式,并通过具体的案例实现的测试用例和测试对象的分离。
但是这种分离还不够彻底,在本节中,我们将对上一节的案例进行进一步的改进,实现:
(1)将测试数据从测试用例中分离出来;
(2)将页面元素的定位总页面对象中分离出来。
场景描述:使用用户名和密码登录课堂派,要求使用PO设计模式(使用python文件来存放测试数据)
操作流程:
(1)先梳理业务,根据业务需求使用excel编写测试用例;
(2)明确测试用例中需要使用的页面和测试数据以及断言; -- 此时需要熟悉测试用例中每一步的操作流程,代码可以先不用实现
(3)实现具体的页面对象和页面元素定位;
(4)准备测试数据 -- 使用python代码来存放测试数据
(5)页面对象和测试数据准备就绪后,对测试用例进行填充。
代码实现:
(1)代码组织结构:
(2)各部分代码实现
pageLocators:
login_page_locs
1 """ 2 登录页面元素定位 3 """ 4 5 from selenium.webdriver.common.by import By 6 7 class LoginPageLocs: 8 # 用户名输入框 9 user_loc = (By.XPATH, '//input[@placeholder="请输入邮箱/手机号/账号"]') 10 # 密码输入框 11 pwd_loc = (By.XPATH, '//input[@placeholder="请输入密码"]') 12 # 登录按钮 13 btn_loc = (By.XPATH, '//button[contains(@class,"primary")]') 14 # 登录区域错误提示框 15 error_tips_from_login_erea = (By.XPATH,'//div[@class="el-message el-message--error"]//p')
home_page_locs
1 """ 2 主页面元素定位 3 """ 4 5 from selenium.webdriver.common.by import By 6 7 class HomePageLocs: 8 # 任务管理定位 9 assign_loc = (By.XPATH, '//span[@title="任务管理"]')
pageObjects:
login_page
1 """ 2 登录页面 3 """ 4 from selenium.webdriver.remote.webdriver import WebDriver 5 from selenium.webdriver.support.wait import WebDriverWait 6 from selenium.webdriver.support import expected_conditions as EC 7 8 from pageLocators.login_page_locs import LoginPageLocs as loc 9 10 class LoginPage: 11 # 属性-元素定位:直接从元素定位类中获取 12 13 def __init__(self,driver:WebDriver): 14 self.driver = driver 15 self.wait = WebDriverWait(driver,20) 16 17 # 用户名、密码登录 18 def login(self,username,password): 19 self.wait.until(EC.visibility_of_element_located(loc.btn_loc)) 20 self.driver.find_element(*loc.user_loc).send_keys(username) 21 self.driver.find_element(*loc.pwd_loc).send_keys(password) 22 btn_ele = self.driver.find_element(*loc.btn_loc) 23 js_code = "arguments[0].click()" 24 self.driver.execute_script(js_code,btn_ele) 25 26 def get_error_msg_from_login_area(self): 27 """ 28 登录失败时,获取登录区域的错误提示信息 29 :return: 错误提示信息 30 """ 31 self.wait.until(EC.visibility_of_element_located(loc.error_tips_from_login_erea)) 32 return self.driver.find_element(*loc.error_tips_from_login_erea).text
home_page
1 """ 2 首页 3 """ 4 from selenium.webdriver.remote.webdriver import WebDriver 5 from selenium.webdriver.support.wait import WebDriverWait 6 from selenium.webdriver.support import expected_conditions as EC 7 8 from pageLocators.home_page_locs import HomePageLocs as loc 9 10 class HomePage: 11 12 def __init__(self,driver:WebDriver): 13 self.driver = driver 14 self.wait = WebDriverWait(driver,20) 15 16 def is_assign_exist(self): 17 """ 18 如果存在则返回True,如果不存在,则返回false 19 :return: 20 """ 21 try: 22 self.wait.until(EC.visibility_of_element_located(loc.assign_loc)) 23 except: 24 return False 25 else: 26 return True
testDatas:
global_datas
1 # 登录url 2 login_url = "https://www.ketangpai.com/#/login"
login_datas
1 # 测试数据存放模块 2 3 # 登录成功的测试数据 4 valid_user = ("1522317xxxx","jyfxxxxxx") 5 6 # 登录失败的测试数据 7 """ 8 用户名为空/用户名不存在 9 """ 10 invalid_datas = [ 11 {"username":"15223179492","password":"jyfxxxxxx","check":"用户不存在"}, 12 {"username":"","password":"jyfxxxxxx","check":"用户名不能为空"} 13 ]
testCases:
test_login
1 """ 2 登录页面测试 3 """ 4 import pytest 5 6 from pageObjects.login_page import LoginPage 7 from pageObjects.home_page import HomePage 8 from testDatas import login_datas as td 9 10 @pytest.mark.usefixtures("back_login") 11 class TestLogin: 12 13 """ 14 逆向场景--登录失败(输入数据格式有误) 15 """ 16 @pytest.mark.parametrize("case",td.invalid_datas) 17 def test_login_failed_invalid_datas(self,case,back_login): 18 LoginPage(back_login).login(case["username"],case["password"]) 19 assert LoginPage(back_login).get_error_msg_from_login_area() == case["check"] 20 21 def test_login_success(self,back_login): 22 LoginPage(back_login).login(*td.valid_user) 23 assert HomePage(back_login).is_assign_exist()
conftest.py -- 前置后置
1 from selenium import webdriver 2 from testDatas import global_datas as gd 3 from time import sleep 4 import pytest 5 6 # 前置后置--作用域和返回值 7 # 作用域是类级别的,因此在进行自动化测试的过程中,浏览器只打开一次,可以节省测试时间 8 @pytest.fixture(scope="class") 9 def init(): 10 # 实例化driver,并访问课堂派登录页面 11 driver = webdriver.Chrome() 12 driver.get(gd.login_url) # 从全局变量中获取登录url 13 yield driver 14 driver.quit() 15 16 @pytest.fixture() 17 def back_login(init): 18 # 每次进行登录测试时,会重新返回登录页面进行登录,如果不重新返回登录页面, 19 # 此时数据会有原有输入框的基础上进行追加,而不是我们期待的测试数据 20 init.get(gd.login_url) 21 yield init
(3)测试结果