分层设计思想

    科技2024-12-21  9

    分层设计思想

    locator 元素定位分层测试用例分层

    接着上一篇文章 – PageObject 设计模式

    登录页面元素定位,都是放在 PageObjects 目录下的 login_page.py 文件下的 LoginPage 类下

    locator 元素定位分层

    这个登录页面要用到的元素定位还是比较少的,在真正的项目中,一个页面20~30个元素定位都是比较正常的。 现在除了 xpath 表达式没有其他的,如果我还要增加其他的表达式,都堆在这个 class 里,会塞得很满,而这个时候,我们在 LoginPage 类中写 操作元素的方法的时候,就会比较混乱

    所以,将元素定位和元素操作再进行细分。

    定位元素的操作,都有一个固定的方式,通过 By 的一个定位的策略,然后是对应元素的表达式

    新建1个包,命名为 PageLocators ,新建 home_page_locs.py 和 login_page_locs.py 文件,分别对应 PageObjects 文件下的 home_page.py 和 login_page.py 文件 (根据页面对象进行分类)

    login_page_locs.py

    from selenium.webdriver.common.by import By class LoginPageLocs: # 简化页面元素定位 # 用户名输入框 user_input = (By.XPATH, "//div[@class='u-input box']/input[@name='email']") # 密码输入框 psd_input = (By.XPATH, "//div[@class='u-input box']/input[@name='password']") # 登录按钮 login_btn = (By.XPATH, "//a[@id='dologin']") # 登录表单区域的提示信息 msg_login_form = (By.XPATH, "//div[@class='ferrorhead']")

    login_page.py

    from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from PO.PageLocators.login_page_locs import LoginPageLocs as locs class LoginPage: # 初始化操作 # driver:WebDriver 这里是声明 driver 是 WebDriver类的实例对象 def __init__(self,driver:WebDriver): # 初始化 dirver self.driver = driver # self.driver = webdriver.chrome() # 不采用这种 webdriver 的方式,是因为这个操作是打开了一个浏览器,创建了一个新的会话, # 而我们登录页面的元素操作,都是在同一个登录页面进行的 # # 定位到登录 iframe 并进行切换 driver.switch_to.frame(0) pass # 登录-元素操作 def login(self,username,password): # 设置元素可见等待 # 显性等待时间为20秒,等待元素为登录按钮 WebDriverWait(self.driver,20).until(EC.visibility_of_element_located(locs.login_btn)) # 找到用户名输入框输入用户名 self.driver.find_element(*locs.user_input).send_keys(username) # 找到密码输入框输入密码 self.driver.find_element(*locs.psd_input).send_keys(password) # 找到登录按钮进行点击 self.driver.find_element(*locs.login_btn).click() # 获取登录区域的提示信息 def get_error_msg(self): WebDriverWait(self.driver,20).until(EC.visibility_of_element_located(locs.msg_login_form)) # 返回文本值 eles = self.driver.find_elements(*locs.msg_login_form) if len(eles) == 1: # print(eles[0].text) return eles[0].text elif len(eles) > 1: text_list = [] for el in eles: text_list.append(el.text) print(text_list) return text_list

    测试用例分层

    自动化测试测试用例 = 测试对象行为 + 断言

    自动化测试测试用例三大要素:前置条件、操作步骤、断言

    测试用例的独立性: 用例之间没有必然业务联系,其他用例不能影响当前用例的运行。 若用例之间存在联系,不知道用例执行会在哪个页面失败,没办法保证接下来的用例一定是从自己想要的页面开始

    测试用例分层关键在于独立测试用例数据

    在测试过程中,对于我们的测试用例,需要做到独立测试数据: 比如账号和密码发生了修改,这时我们代码中的数据,也要发生修改; 或者是环境切换 / 多环境共用的时候,例如测试dev环境、测试UAT环境和生产环境,测试数据不一致。 还有一些全局共享的网址、数据,也可以独立出来。 所以,独立测试数据,可以减少测试的工作量,测试数据发生修改,就不需要在测试用例中逐个修改测试数据。

    测试数据的存储,可以用 csv / excel 表格的方式存储,可以用 python 文件方式存储,也可以用 yaml 文件存储。而 yaml 文件读取出来的内容,是 python 中 字典或者列表的形式的内容。 如果没有要求的话,可以直接用 python 文件方式存储,以列表或字典的方式存储测试数据,毕竟直接明了,没有那么多其他花里胡哨的操作。

    前面 PageLocators元素定位 是跟 PageObjects页面对象 绑定在一起,测试数据TestDatas 是跟 测试类(测试模块)TestCases 绑定在一起

    新建一个 TestDatas 包,用于放置测试数据

    对于全局共享的数据,比如 url ,可以创建一个 global_datas.py 文件进行存放测试数据文件的命名要和测试用例模块相对应,例如 登录测试用例模块的名称为 test_login.py,测试数据文件可命名为 login_datas.py

    global_datas.py

    # url base_url = "https://mail.163.com/"

    login_datas.py

    # 正常场景 success_case = ("z14737424527","输入你的密码") # 异常场景 fail_cases = [ {"user": "", "psd": "输入你的密码", "check": "请输入帐号"}, {"user": "z14737424527", "psd": "", "check": "请输入密码"}, {"user": "z1473", "psd": "输入你的密码", "check": "帐号或密码错误"} ]

    test_login.py

    import unittest from selenium import webdriver from PO.PageObjects.login_page import LoginPage from PO.PageObjects.home_page import HomePage import ddt from PO.TestDatas import global_datas as GD from PO.TestDatas import login_datas as lds @ddt.ddt() class TestLogin(unittest.TestCase): # 前置操作 def setUp(self) -> None: # 访问163邮箱登录页面 self.driver = webdriver.Chrome() self.driver.get(GD.base_url) self.driver.maximize_window() # 清理操作 def tearDown(self) -> None: self.driver.quit() def test_login_success(self): # 步骤: # 1、登录页面-登录操作 LoginPage(self.driver).login(*lds.success_case) # 输入账号密码 # 断言: # 1、首页-获取元素是否存在 (进行断言操作,元素可见返回True) self.assertTrue(HomePage(self.driver).get_element_exists()) @ddt.data(*lds.fail_cases) def test_login_failed(self,case): # 步骤: # 1、登录页面-登录操作 lp = LoginPage(self.driver) lp.login(case["user"], case["psd"]) # 输入 cases 数据中的 账号和密码 # print(case["user"], case["psd"], case["check"]) # 断言: # 1、登录页面-获取错误提示信息 进行对比 # print(lp.get_error_msg()) self.assertEqual(lp.get_error_msg(),case["check"])

    一般情况下,一个自动化测试框架,都会进行4层封装

    PO 页面对象层

    测试用例层

    测试数据层

    元素定位层

    一般情况下项目是比较庞大,存在比较多的模块,现在只是对登录这一模块的测试用例进行了讲解,可在这四层封装的基础上,在测试用例层和测试数据层再根据模块进行细分,将不同的模块放入不同的文件夹中,这样就不会那么混乱。就比如我们写测试用例的时候,会根据系统划分一级、二级模块。

    Processed: 0.026, SQL: 8