PO模式在Selenium中简单实践

初识PO模式

PO(PageObject)是一种设计模式。简单来说就是把一些繁琐的定位方法、元素操作方式等封装到类中,通过类与类之间的调用完成特定操作。

PO被认为是自动化测试项目开发实践的最佳设计模式之一。

在学习PO模式前,可以先复习一下面向对象的编程思想。我觉得两者很像。

优点

PO模式把页面元素定位和业务操作流程分开,界面元素的变化则不需要修改业务逻辑代码
PO能提高代码的可读性,高复用性,可维护性
设计准则
1.使用公共方法来代表页面提供的服务

2.不要暴露页面的内部细节(比如元素、元素的定位方法等),隔离测试用例和业务和页面对象

3.PO本身通常不应进行断言或判断。判断和断言是测试的一部分,而不是在PO中。

4.PO不一定需要代表整个界面,而是在测试中‘用到什么写什么’

5.相同的操作,但是数据不同,带来的不同结果可以封装成不同的方法。

6.方法可以返回其他的页面对象,进行页面的关联。

以上是比较官方的PO设计准则,我们需要根据具体业务的实际情况决定是完全遵循还是部分遵循。

selenium中的分层模型

表现层:页面中可见的元素,都属于表现层。(元素定位器的编写)
操作层:对页面可见元素的操作。(点击、输入文本等)
业务层:上面2层的组合,联合到一起形成某个业务动作。
测试用例:组合了一个或多个页面的方法,操作对应的元素,完成的测试。
PO模式实战
接下来就用PO模式完成一个简单的‘百度登录模块’的测试

思路:

1.创建一个elements.py存放登录界面所有的元素定位方式(用到哪个写哪个)

2.创建一个common_driver.py存放一些共用的浏览器相关方法

3.创建一个common_basepage.py存放共用的元素操作方法

4.创建一个test_cases.py文件存放测试用例

以下为部分代码:

找到我们测试登录模块需要操作到的元素,将其定位方法写到elements.py中

  1. #elements.py

  2. class Elements():

  3. '''存放用到的所有元素定位器'''

  4. #登录前的界面元素

  5. LOGIN_BUTTON_OUT = ('id','s-top-loginbtn')#百度首页的‘登录’按钮

  6. LOGIN_WIN = ('id','TANGRAM__PSP_4__content')#登录窗口

  7. USERNAME_INPUT = ('id','TANGRAM__PSP_11__userName')#输入账号栏

  8. PASSWORD_INPUT = ('id','TANGRAM__PSP_11__password')#输入密码栏

  9. LOGIN_BUTTON_IN = ('id','TANGRAM__PSP_11__submit')#登录界面的‘登录’按钮

  10. #登录后的界面元素

  11. USER_INFO = ('css selector','#s-top-username > span.user-name.c-font-normal.c-color-t')#右上角的用户信息

  12. QUIT_BOTTON = ('css selector','#s-user-name-menu>.quit')#退出登录按钮

浏览器相关操作放到common_driver.py中

  1. # common_driver.py

  2. from selenium import webdriver

  3. from environment_config import Env

  4. class Single(object):

  5. '''

  6. 设计单例模式

  7. '''

  8. _instance = None #实例

  9. def __new__(cls, *args, **kwargs):

  10. if cls._instance is None: #此处是可以用__instance

  11. cls._instance = super().__new__(cls)

  12. return cls._instance

  13. class Open_Driver(Single):

  14. '''

  15. 打开一个浏览器

  16. '''

  17. driver = None

  18. def get_driver(self,browser_type=Env.BROWSER_TYPE,headless_flag=Env.HEADLESS_FLAG):

  19. '''

  20. 根据参数打开想要的浏览器

  21. :param browser_type: 浏览器类型,读取Env文件中的值作为默认值

  22. :param headless_flag: 是否有头,读取Env文件中的值作为默认值,True/False

  23. :return: 返回一个浏览器对象

  24. '''

  25. if self.driver is None:

  26. if not headless_flag:#如果是有头模式

  27. if browser_type == 'chrome':

  28. self.driver = webdriver.Chrome()

  29. elif headless_flag == 'firefox':

  30. self.driver = webdriver.Firefox()

  31. else:

  32. raise Exception(f'暂不支持{browser_type}浏览器')

  33. else:#如果是无头模式

  34. _option = webdriver.ChromeOptions()

  35. _option.add_argument('--headless')#添加无头模式参数'--headless'

  36. if browser_type == 'chrome':

  37. self.driver = webdriver.Chrome(options=_option)

  38. elif headless_flag == 'firefox':

  39. self.driver = webdriver.Firefox(options=_option)

  40. else:

  41. raise Exception(f'暂不支持{browser_type}浏览器')

  42. self.driver.maximize_window()#窗口最大化

  43. self.driver.implicitly_wait(Env.IMPLICITLY_WAIT_TIME)#隐式等待,读取Env文件中IMPLICITLY_WAIT_TIME的值

  44. return self.driver #返回浏览器对象

把要用到的元素操作方法写入到common_basepage.py中

  1. # common_basepage.py

  2. from common_driver import Open_Driver

  3. class BasePage():

  4. '''

  5. 存放所有界面元素操作方法

  6. '''

  7. def __init__(self):

  8. self.driver = Open_Driver().get_driver()

  9. def open_url(self,url):

  10. '''打开网址'''

  11. self.driver.get(url)

  12. def get_element(self,locator):

  13. '''

  14. 定位元素

  15. :param locator:元素定位器,从elements中取

  16. :return: 元素对象

  17. '''

  18. return self.driver.find_element(*locator)

  19. def input_text(self,locator,text,append=False):

  20. '''

  21. 在元素上输入文本

  22. :param locator: 元素定位器

  23. :param text: 要输入的文本

  24. :param append: 是否先清空,默认清空

  25. '''

  26. if append:#不需要清空内容,追加写入

  27. self.driver.find_element(*locator).send_keys(text)

  28. else:#先清空,再写入

  29. self.driver.find_element(*locator).clear()

  30. self.driver.find_element(*locator).send_keys(text)

  31. def click_element(self,locator):

  32. '''

  33. 点击元素

  34. :param locator: 元素定位器

  35. '''

  36. self.driver.find_element(*locator).click()

  37. def ele_find_ele_input(self,locator1,locator2,text):

  38. '''

  39. 在元素1上找元素2

  40. :param ele1: 元素1

  41. :param ele2: 元素2

  42. :return: 元素2

  43. '''

  44. return self.driver.find_element(*locator1).find_element(*locator2).send_keys(text)

  45. def get_element_text(self,locator):

  46. return self.driver.find_element(*locator).text

页面对象loginpage.py

  1. from common_basepage import BasePage

  2. from datas import Datas

  3. from elements import Elements

  4. from logsuccesspage import LogSuccessPage

  5. class LoginPage(BasePage):

  6. def open_loginpage(self,url):

  7. '''

  8. 打开登录页

  9. :param url:登录页url

  10. :return: LoginPage实例对象

  11. '''

  12. self.open_url(url)

  13. return self

  14. def login_baidu(self,username,password):

  15. '''

  16. 登录百度账号

  17. :param username: 用户名

  18. :param password: 密码

  19. :return: 登录成功后的页面对象

  20. '''

  21. self.click_element(Elements.LOGIN_BUTTON_OUT)#点击右上角登录

  22. self.ele_find_ele_input(Elements.LOGIN_WIN,Elements.USERNAME_INPUT,Datas.USERNAME)#输入账号

  23. self.ele_find_ele_input(Elements.LOGIN_WIN,Elements.PASSWORD_INPUT,Datas.PASSWORD)#输入密码

  24. self.click_element(Elements.LOGIN_BUTTON_IN)

  25. return LogSuccessPage()

测试用例test_cases.py

  1. from time import sleep

  2. import pytest

  3. from datas import Datas

  4. from elements import Elements

  5. from environment_config import Env

  6. from loginpage import LoginPage

  7. class Test_login():

  8. def test_login01(self):

  9. '''

  10. 登录成功的测试

  11. :return:

  12. '''

  13. test_page = LoginPage()#创建实例

  14. test_page.open_loginpage(Env.TEST_URL)#打开测试url

  15. new_page=test_page.login_baidu(Datas.USERNAME,Datas.PASSWORD)#登录百度账号

  16. sleep(2)

  17. text = new_page.get_element_text(Elements.USER_INFO)#登录成功界面

  18. assert text == 'yvvgfffvbh'#断言用户名称是否正确

  19. if __name__ == '__main__':

  20. pytest.main(['-vs'])

运行结果
在这里插入图片描述
写完花了4个小时,感受就是:

1.要理解透彻Python中的面向对象思想。

2.写完整体结构后要继续优化。

可以看到,我们所有数据都放在配置文件中,代码中不会暴露任何的界面元素或账号数据。 最后用pytest执行测试用例即可。

以上只是一个最简版的PO模型项目。只是遵循了po设计准则,并不完整。

一个完整的selenium测试项目大体上应该包括:

1.tools 工具类,格式转换、路径操作等

2.commom 基类,一些公用的方法

3.pageobjects 页面对象类

4.testcases 测试用例

5.test_datas 测试数据,yaml/Excel文件等

6.outfiles 输出文件,log和截图等

7.testreport 测试报告

项目结构并没有具体标准,分类清晰即可。重要的是在设计过程中遵循上文说到的’设计准则‘。

 

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Selenium PO(Page Object)设计模式是一种自动化测试的最佳实践,它将页面对象封装在一个类,使测试代码更加模块化、可读性更高、易于维护。下面是一个简单Selenium PO设计模式的例子: ```python from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class LoginPage: def __init__(self, driver): self.driver = driver self.username_input = (By.ID, 'username') self.password_input = (By.ID, 'password') self.login_button = (By.ID, 'login-button') self.error_message = (By.ID, 'error-message') def enter_username(self, username): WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(self.username_input)) self.driver.find_element(*self.username_input).send_keys(username) def enter_password(self, password): WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(self.password_input)) self.driver.find_element(*self.password_input).send_keys(password) def click_login_button(self): WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable(self.login_button)) self.driver.find_element(*self.login_button).click() def get_error_message(self): WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(self.error_message)) return self.driver.find_element(*self.error_message).text ``` 在这个例子,我们定义了一个名为LoginPage的类,它包含了登录页面的所有元素和操作。在类的构造函数,我们使用了Selenium的By类来定义了页面元素的定位方式,例如ID、CSS选择器等。然后,我们定义了一些方法来操作这些元素,例如输入用户名、输入密码、点击登录按钮等。在每个方法,我们使用了Selenium的WebDriverWait类来等待元素的出现或可点击,以确保测试的稳定性和可靠性。 使用Selenium PO设计模式,我们可以将测试代码和页面元素分离开来,使测试代码更加清晰、易于维护。同时,我们还可以将页面元素的定位方式封装在类,以便于修改和维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值