所需环境
- 浏览器 Chrome
- Python 3.9
- Selenium
- Pytest
配置驱动
在项目根目录下创建 conftest.py
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.webdriver import WebDriver
import os
import time
# 配置driver 在所有的用例执行之前开始
@pytest.fixture(scope="session",autouse=True)
def driver():
driverpath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'drivers/chromedriver.exe')
driver = webdriver.Chrome(executable_path=driverpath)
driver.implicitly_wait(5)
driver.maximize_window()
yield driver
# 运行结束
# driver.quit()
@pytest.fixture(scope='function',autouse=True)
def handler_case(driver:WebDriver):
yield
# 每个用例执行完成之后进行截图
screenshots = os.path.join(os.path.dirname(os.path.abspath(__file__)),"screenshots")
if not os.path.exists(screenshots):
os.mkdir(screenshots)
filename = time.strftime('%Y-%m-%d_%H_%M_%S')
file = os.path.join(screenshots,filename+".png")
driver.save_screenshot(file)
创建测试用例
testcases/test_login.py
from selenium.webdriver.chrome.webdriver import WebDriver
def test_login(driver:WebDriver):
"""
用户登录
:param driver:
:return:
"""
driver.get("http://1.117.45.85/zentao/my/")
driver.find_element_by_id('account').send_keys("abtester")
driver.find_element_by_css_selector('[name="password"]').send_keys('Abtester123')
driver.find_element_by_id("submit").click()
def test_create_topic(driver:WebDriver):
driver.find_element_by_css_selector('li[title="测试"]').click()
# 切换iframe
qa = driver.find_element_by_id('appIframe-qa')
driver.switch_to.frame(qa)
driver.find_element_by_css_selector('li[data-id="testcase"]').click()
driver.find_element_by_css_selector('a.btn.btn-primary[data-app="qa"]').click()
driver.find_element_by_id('title').send_keys('用户登录测试成功登录')
driver.find_element_by_id('precondition').send_keys('网络正常:存在用户 abtester 密码:Abtester123')
# step1
driver.find_element_by_xpath('//tbody[@id="steps"]/tr[1]/td[2]//textarea').send_keys('打开登录页面')
driver.find_element_by_xpath('//tbody[@id="steps"]/tr[1]/td[3]//textarea').send_keys('能够正常打开')
# step2
driver.find_element_by_xpath('//tbody[@id="steps"]/tr[2]/td[2]//textarea').send_keys("输入用户名 abtester")
driver.find_element_by_xpath('//tbody[@id="steps"]/tr[2]/td[3]//textarea').send_keys('输入成功')
# step3
driver.find_element_by_xpath('//tbody[@id="steps"]/tr[3]/td[2]//textarea').send_keys('输入密码:Abtester123')
driver.find_element_by_xpath('//tbody[@id="steps"]/tr[3]/td[3]//textarea').send_keys('输入成功')
# submit
driver.find_element_by_id('submit').click()
封装POM
将自动化脚本直接写在代码中不是好的方案,如果后期页面进行了更改,那么维护起来很麻烦,一种业界通用的做法就是配置页面模型 POM
POM是将每个页面封装到一个类中,类中定义相关的操作,将上面的自动化创建测试用例的操作封装一下
pom/mainnav.py
"""
页面导航
"""
from selenium.webdriver.chrome.webdriver import WebDriver
from pom.testcasepage import TestCasePage
class MainNavgation:
def __init__(self,driver:WebDriver):
self.driver = driver
def nav_qa(self):
"""
导航到测试页面
:return:
"""
self.driver.find_element_by_xpath('//li[@title="测试"]').click()
qa = self.driver.find_element_by_id('appIframe-qa')
self.driver.switch_to.frame(qa)
return TestCasePage(self.driver)
pom/testcasepage.py
from selenium.webdriver.chrome.webdriver import WebDriver
class TestCasePage:
"""
测试用例相关的页面
"""
def __init__(self,driver:WebDriver):
self.driver = driver
self.driver.find_element_by_xpath('//li[@data-id="testcase"]').click()
def create_testcase(self,title,*steps,precondition=''):
"""
创建测试用例
:param title: 标题
:param precondition: 前置条件
:param steps: 测试步骤
:return:
"""
self.driver.find_element_by_id('title').send_keys(title)
self.driver.find_element_by_id('precondition').send_keys(precondition)
# 约定测试数据 steps=[{step:"打开登录页面",expect:""},{step:"打开登录页面",expect:""}]
for i in range(len(steps)):
self.driver.find_element_by_xpath(f'//tbody[@id="steps"]/tr[{i+1}]/td[2]//textarea').send_keys(steps[i].get("step"))
self.driver.find_element_by_xpath(f'//tbody[@id="steps"]/tr[{i+1}]/td[3]//textarea').send_keys(steps[i].get("expect"))
# submit
self.driver.find_element_by_id('submit').click()
def click_add_testcase(self):
"""
点击添加测试用例
:return:
"""
self.driver.find_element_by_css_selector('a.btn.btn-primary[data-app="qa"]').click()
将页面封装为独立的类,在测试用例中调用测试方法
testcases\test_login.py
from selenium.webdriver.chrome.webdriver import WebDriver
from pom.mainnav import MainNavgation
def test_login(driver:WebDriver):
"""
用户登录
:param driver:
:return:
"""
driver.get("http://1.117.45.85/zentao/my/")
driver.find_element_by_id('account').send_keys("abtester")
driver.find_element_by_css_selector('[name="password"]').send_keys('Abtester123')
driver.find_element_by_id("submit").click()
def test_create_topic(driver:WebDriver):
mainnav = MainNavgation(driver)
# 导航到测试页面
qa = mainnav.nav_qa()
# 点击添加测试用例
qa.click_add_testcase()
step1 = {'step':"输入用户名zhangsan","expect":"输入成功"}
step2 = {'step': "输入密码zhangsan", "expect": "输入成功"}
step3 = {'step': "输入确认密码zhangsan", "expect": "输入成功"}
step4 = {'step': "输入确认密码zhangsan", "expect": "输入成功"}
step5 = {'step': "输入确认密码zhangsan", "expect": "输入成功"}
qa.create_testcase("用户注册",step1,step2,step3,step4,step5,precondition='网络正常')
yaml配置页面元素定位
当创建的页面越来越多的时候,单纯的pom模型在维护元素定位时也会变得不方便,这时可以将页面上的元素放到yaml配置文件中;
安装 pyyaml 可以解析yaml文件
pip install pyyaml
配置页面的定位
pageconf/testcase.yaml
testcase:
xpath: //li[@data-id="testcase"] #测试
createbtn:
css: a.btn.btn-primary[data-app="qa"] # 创建用例
title:
id: title # 用例的标题
precondition:
id: precondition # 前置条件
submit:
id: submit # 提交
在pom文件中定义解析yaml文件的基类
pom\basepage.py
from selenium.webdriver.chrome.webdriver import WebDriver
import os
import yaml
class BasePage:
def __init__(self,driver:WebDriver,yamlfile):
self.driver = driver
self.__yamlpath = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),'pageconf')
self.__yamlfile = yamlfile
self.config = self.__load_yaml()
def __load_yaml(self):
"""加载yaml文件"""
with open(os.path.join(self.__yamlpath,self.__yamlfile),encoding="utf8") as file:
return yaml.load(file,Loader=yaml.SafeLoader)
def find_element_by_yaml_config(self,name):
"""
自定义从yaml文件中获取元素定位
:param name:
:return:
"""
selector:dict = self.config.get(name)
for key,value in selector.items():
if key == "xpath":
return self.driver.find_element_by_xpath(value)
elif key=="css":
return self.driver.find_element_by_css_selector(value)
elif key=="id":
return self.driver.find_element_by_id(value)
elif key=="name":
return self.driver.find_element_by_name(value)
elif key=="class":
return self.driver.find_element_by_class_name(value)
定义所有页面的基类,在基类中设置从yaml文件中读取配置的方法,后续所有的页面类都继承basepage 父类;
pom/testcasepage.py
from selenium.webdriver.chrome.webdriver import WebDriver
from pom.basepage import BasePage
class TestCasePage(BasePage):
"""
测试用例相关的页面
"""
def __init__(self,driver:WebDriver):
# 调用父类的构造器 'testcase.yaml' 传入页面的配置文件路径
super(TestCasePage, self).__init__(driver,'testcase.yaml')
self.find_element_by_yaml_config("testcase").click()
def create_testcase(self,title,*steps,precondition=''):
"""
创建测试用例
:param title: 标题
:param precondition: 前置条件
:param steps: 测试步骤
:return:
"""
self.find_element_by_yaml_config('title').send_keys(title)
# self.driver.find_element_by_id('title').send_keys(title)
self.find_element_by_yaml_config('precondition').send_keys(precondition)
# self.driver.find_element_by_id('precondition').send_keys(precondition)
# 约定测试数据 steps=[{step:"打开登录页面",expect:""},{step:"打开登录页面",expect:""}]
for i in range(len(steps)):
self.driver.find_element_by_xpath(f'//tbody[@id="steps"]/tr[{i+1}]/td[2]//textarea').send_keys(steps[i].get("step"))
self.driver.find_element_by_xpath(f'//tbody[@id="steps"]/tr[{i+1}]/td[3]//textarea').send_keys(steps[i].get("expect"))
# submit
self.find_element_by_yaml_config('submit').click()
def click_add_testcase(self):
"""
点击添加测试用例
:return:
"""
self.find_element_by_yaml_config('createbtn').click()
至此,实现了自动化测试框架中的最常用的操作
POM页面配置
Yaml元素定位配置
Pytest 配置单独driver
整个代码架构
附录-所涉及到的知识点
- Selenium基本用法
- yaml文件处理
- pytest的使用
测试人必看
感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接免费拿走:
① 2000多本软件测试电子书(主流和经典的书籍应该都有了)
② 软件测试/自动化测试标准库资料(最全中文版)
③ 项目源码(四五十个有趣且经典的练手项目及源码)
④ Python编程语言、API接口自动化测试、web自动化测试、App自动化测试(适合小白学习)
⑤ Python学习路线图(告别不入流的学习)
上图的资料 在我的QQ技术交流群里(技术交流和资源共享,广告进来腿给你打断)
可以自助拿走,群号953306497(备注“csdn111”)群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。