1、Selenium元素定位方式,优先级Selenium 8种定位方式(Selenium4推荐By类)fromselenium.webdriver.common.byimportByBy.IDid属性By.NAMEname属性By.CLASS_NAMEclass名称(单个class)By.TAG_NAME标签名 div/inputBy.LINK_TEXT完整链接文本By.PARTIAL_LINK_TEXT部分链接文本By.XPATHxpath路径By.CSS_SELECTORcss选择器优先级(优先稳定性、可维护性,从高到低)ID > NAME:最优,业务一般给稳定id;id理论页面唯一;CSS_SELECTOR:性能好,语法简洁,推荐优先于xpath;XPATH:能力最强,支持文本、父子轴;尽量避免绝对xpath,使用相对xpath;CLASS_NAME / LINK_TEXT / PARTIAL_LINK_TEXT / TAG_NAME:class容易动态变化;文本会随版本多语言改动,稳定性差,尽量少用。禁忌:不要复制浏览器复制出来的绝对xpath,页面结构轻微改动直接失效。2、Web自动化三种等待:强制、隐式、显式等待,区别1)强制等待 time.sleep(n)硬等待,固定休眠n秒,不管页面有没有加载完成。importtime time.sleep(2)缺点:浪费时间;设置短会报错;设置长执行慢;尽量少用,调试临时使用。2)隐式等待 implicitly_wait()全局设置一次,作用整个driver生命周期;查找元素时,如果找不到,在设定时间内不断轮询查找;超时抛异常。driver.implicitly_wait(10)⚠️局限:只针对找元素find_element生效,不等待元素可点击、可见;不能针对单个元素定制超时;Selenium4不建议混合隐式+显式等待,会产生不可预期等待行为。3)显式等待 WebDriverWait(项目最推荐)针对某个特定元素,等待某个条件(可见、可点击、存在),超时抛出异常。fromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasEC wait=WebDriverWait(driver,10)ele=wait.until(EC.element_to_be_clickable((By.ID,"btn")))常用条件:presence_of_element_located:DOM存在(不一定可见)visibility_of_element_located:元素可见element_to_be_clickable:元素可点击三者核心区别类型作用范围等待条件是否全局推荐度强制sleep代码行固定时间局部极低,仅调试隐式等待整个driver元素是否存在DOM全局慎用显式等待WebDriverWait单个元素自定义条件(可见、可点击)局部⭐生产首选最佳实践:以显式等待为主,禁止大量sleep,尽量不要混用隐式+显式。3、Appium底层原理;Android/iOS元素定位Appium底层原理Appium是C/S架构:Client:测试脚本(Python/Java Appium‑Python‑Client)发送http请求;Appium Server:接收http请求,转发给移动端驱动;Android:调用UiAutomator2;iOS调用XCUITest;驱动与设备通信,执行操作,结果返回Appium Server,再返回脚本。Appium不向App植入SDK,基于系统自带测试框架,支持原生、H5、混合应用。Android元素定位方式resource‑id(对应Selenium的id,优先用)accessibility_idxpathclassnameandroid‑uiautomator(Android独有)iOS元素定位方式accessibility_id(iOS最稳定优先)xpathclassnameiOS没有resource‑id;优先让开发给accessibility_id,稳定性最高。工具:uiautomatorviewer / Appium Inspector查看元素属性。4、pytest常用特性;fixture作用域pytest常用特性简单用例书写,不需要必须继承类;函数/类都可以作为用例;强大的fixture做前置后置,替代unittest的setUp/tearDown;丰富断言:直接assert,不用self.assertEqual,报错信息友好;参数化@pytest.mark.parametrize;mark标记:skip、xfail、自定义标签,分组执行用例;失败重试、并发、插件生态丰富;支持unittest用例兼容执行。fixture 5种作用域 scopefunction:默认,每个测试函数执行前后执行;class:每个测试类执行一次;module:每个py模块文件执行一次;session:整个测试会话,全部用例只执行一次,适合初始化数据库、登录token;package:包级别,pytest5.0+,每个包执行一次。fixture可以跨文件,放在conftest.py,不需要import,直接使用。5、unittest 和 pytest 区别,推荐哪个对比项unittestpytest用例写法必须继承unittest.TestCase;self.assertXXX普通函数/类,直接assert,简洁前置后置setUp/tearDown;setUpClassfixture,灵活,多粒度作用域参数化第三方库ddt原生@pytest.mark.parametrize标记过滤弱,需要自己封装原生mark,灵活分组执行报告原生简陋allure/pytest-html插件生态强兼容性只支持自身可运行unittest用例推荐pytest理由:代码简洁,降低维护成本;fixture粒度灵活,适合自动化框架;原生支持参数化、标记;插件生态完善(重试、并发、allure报告);兼容旧unittest脚本,迁移成本低;只有维护老项目时继续用unittest。6、数据驱动测试;pytest实现数据驱动数据驱动DDT:测试逻辑一套,测试数据多套;数据和脚本分离,通过不同输入数据驱动执行多条用例。数据可以写在代码、csv、json、yaml。方式1:原生 parametrize(最常用)importpytest test_data=[("admin","123456",True),("admin","wrong",False),("","123456",False)]@pytest.mark.parametrize("username,pwd,expect_result",test_data)deftest_login(username,pwd,expect_result):res=login(username,pwd)assertres==expect_result方式2:读取yaml/json外部文件做数据驱动把用例数据放到yaml,fixture读取文件加载数据,实现脚本与数据分离。yaml示例 login_data.yamlcases:-{"user":"admin","pwd":"123456","expect":true}-{"user":"admin","pwd":"err","expect":false}脚本读取yaml加载cases传入parametrize。区别关键字驱动:关键字驱动是把操作动作也抽象;数据驱动只分离输入输出数据。7、PO模式是什么?为什么使用POPO:Page Object 页面对象模式核心思想:页面与测试用例分离Page类:封装页面元素定位、页面操作方法;不写断言;Test测试用例:只调用page对象方法,写断言,不写元素定位、页面操作。使用PO的好处解耦:页面UI改动,只修改Page类,不需要修改大量测试用例;维护成本大幅下降;代码复用:多个用例复用页面操作;可读性高,测试用例业务语义清晰;降低重复代码。反模式:用例里面直接写大量xpath、click操作;页面逻辑散落在各个用例。POM = PO Model。8、接口自动化框架设计;requests封装、断言、报告接口自动化框架主要模块requests二次封装模块:统一请求头、公共url、异常捕获、日志打印;数据层:yaml/json存放用例数据;公共工具:token处理、数据提取、文件读取;测试用例层:pytest用例;断言模块:通用响应断言;报告:allure;日志模块log;配置文件:环境地址切换(测试、预发)。requests简单封装示例importrequestsclassHttpRequest:def__init__(self):self.session=requests.Session()defsend(self,method,url,**kwargs):# 统一处理base_url、headers、日志、异常捕获resp=self.session.request(method,url,**kwargs)returnresp使用session自动维护cookie。断言基础:状态码、响应字段、json字段;封装通用断言函数:校验响应码、关键字、数据库结果比对;报告主流:Allure报告,pytest‑allure插件;可以展示用例、步骤、请求响应、失败截图。9、token传递;接口关联、参数化Token传递登录接口获取token;存储到全局变量 / fixture返回;后续接口请求头headers带入Authorization: Bearer xxx;方案:session fixture,session级别只登录一次,返回token,所有用例直接使用。接口关联场景:A接口返回值,作为B接口入参。实现思路:执行A接口,提取返回字段;保存到变量;传给下一个接口;yaml数据驱动场景:使用变量池,保存提取值,用占位符替换后续请求参数。示例:登录拿到token,创建订单接口使用token;查询订单依赖上一步返回order_id。参数化pytest.mark.parametrize;读取yaml/json/csv批量用例;环境参数:通过配置文件区分测试/预发域名。10、自动化框架:失败重试、并发执行、定制报告1)失败重试插件:pytest‑rerunfailures--rerun 3失败重试3次;--reruns‑delay 2重试间隔;可以加标记指定哪些用例允许重试。注意:不要滥用重试,优先修复脚本不稳定,重试只是兜底。2)并发执行插件:pytest‑xdist-n auto根据CPU自动分配进程;‑n 44个进程并发。注意并发坑:fixture注意线程安全;测试数据不能互相冲突;不能共享内存变量;每个进程独立session。3)定制测试报告Allure:工业级,添加步骤、附件(请求响应、截图);pytest‑html简单html报告;二次开发:读取allure结果,自定义解析,对接钉钉/企业微信推送结果。11、Jenkins集成自动化;pipeline关键步骤Jenkins集成自动化步骤Jenkins机器准备python环境,安装项目依赖;拉取代码仓库(git);安装requirements.txt依赖;执行pytest自动化命令;生成allure结果;allure生成报告;结果钉钉/企业微信通知;构建失败标记。Pipeline关键stage示例pipeline{agent any stages{stage('拉取代码'){steps{git url:'xxx'}}stage('安装依赖'){steps{sh'pip install -r requirements.txt'}}stage('执行自动化用例'){steps{sh'pytest --allure-results=allure-results -n 2'}}stage('生成allure报告'){steps{allure generate...}}}post{always{//无论成功失败都推送报告dingTalk notification}}}触发方式:定时构建、代码提交触发、手动触发。12、自动化脚本不稳定(flaky case)原因与解决方案flaky:时而成功时而失败,没有改动代码就报错。常见原因等待问题:没有正确等待,元素没加载完成就操作;混用隐式显式;大量sleep;定位器不稳定:绝对xpath、依赖动态id、依赖页面文本;测试数据污染:用例之间没有隔离,前一个用例残留数据影响下一条;并发执行,共享测试数据;环境问题:网络波动、服务接口超时;弹窗、alert、广告弹窗没有处理;浏览器缓存、cookie残留;接口:token过期,没有重新登录。提升稳定性方案全部改用显式等待,按条件等待,杜绝sleep;优化元素定位,优先id/accessibility_id,写相对xpath/css;做好用例隔离:fixture做数据准备+数据清理;每条用例尽量独立;异常捕获:弹窗、alert做处理;网络超时设置;关键用例失败重试兜底;清理cookie,每个用例前后重置状态;增加详细日志,失败保存请求响应、截图,方便定位;测试数据工厂,每条用例生成全新数据,避免互相干扰。13、测试数据构造;自动化数据工厂设计测试数据构造:自动化执行前生成干净测试数据,执行后清理,避免线上/测试库脏数据,保证用例可重复执行。我做过的数据工厂设计思路封装数据工厂类,提供方法生成用户、订单等业务实体;两种模式:方式A:调用业务接口生成数据;方式B:直接操作测试数据库插入数据;fixture管理:scope=function,每条用例运行前生成数据,yield返回;用例结束后执行删除/还原;支持参数:可以传参数自定义字段,不传则生成默认随机数据;数据加标记,方便批量清理过期脏数据。示例伪代码@pytest.fixturedefcreate_test_user(db_factory):user=db_factory.create_user(username=random_str())yielduser db_factory.delete_user(user.id)#后置清理注意:不要在预发环境随意删除数据;可以做标记,定时脚本批量回收过期测试数据。14、从零搭建接口自动化框架,目录结构api_auto_test/ ├── conf/ #配置文件 │ └── config.yaml #环境地址、账号、超时配置 ├── data/ #测试用例数据 yaml/json │ ├── login_case.yaml │ └── order_case.yaml ├── lib/ #底层封装 │ ├── http_client.py #requests二次封装 │ ├── db_connect.py #数据库工具 │ └── data_factory.py #测试数据工厂 ├── common/ #公共工具 │ ├── assertion.py #通用断言封装 │ ├── token_manage.py #token管理 │ └── yaml_util.py #读取yaml工具 ├── testcases/ #pytest测试用例 │ ├── test_login.py │ └── test_order.py ├── conftest.py #全局fixture:登录token、初始化、数据工厂 ├── logs/ #运行日志 ├── allure-results/ #allure原始结果 ├── requirements.txt #依赖包 └── run.py #执行入口核心设计要点:配置与代码分离,切换环境只改config;请求封装统一处理header、日志、异常;fixture管理前置后置,token、测试数据;数据与脚本分离,yaml存放用例;内置断言、数据工厂;输出日志+allure报告,支持Jenkins CI接入。
1、Selenium元素定位方式,优先级Selenium 8种定位方式(Selenium4推荐By类)fromselenium.webdriver.common.byimportByBy.IDid属性By.NAMEname属性By.CLASS_NAMEclass名称(单个class)By.TAG_NAME标签名 div/inputBy.LINK_TEXT完整链接文本By.PARTIAL_LINK_TEXT部分链接文本By.XPATHxpath路径By.CSS_SELECTORcss选择器优先级(优先稳定性、可维护性,从高到低)ID > NAME:最优,业务一般给稳定id;id理论页面唯一;CSS_SELECTOR:性能好,语法简洁,推荐优先于xpath;XPATH:能力最强,支持文本、父子轴;尽量避免绝对xpath,使用相对xpath;CLASS_NAME / LINK_TEXT / PARTIAL_LINK_TEXT / TAG_NAME:class容易动态变化;文本会随版本多语言改动,稳定性差,尽量少用。禁忌:不要复制浏览器复制出来的绝对xpath,页面结构轻微改动直接失效。2、Web自动化三种等待:强制、隐式、显式等待,区别1)强制等待 time.sleep(n)硬等待,固定休眠n秒,不管页面有没有加载完成。importtime time.sleep(2)缺点:浪费时间;设置短会报错;设置长执行慢;尽量少用,调试临时使用。2)隐式等待 implicitly_wait()全局设置一次,作用整个driver生命周期;查找元素时,如果找不到,在设定时间内不断轮询查找;超时抛异常。driver.implicitly_wait(10)⚠️局限:只针对找元素find_element生效,不等待元素可点击、可见;不能针对单个元素定制超时;Selenium4不建议混合隐式+显式等待,会产生不可预期等待行为。3)显式等待 WebDriverWait(项目最推荐)针对某个特定元素,等待某个条件(可见、可点击、存在),超时抛出异常。fromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasEC wait=WebDriverWait(driver,10)ele=wait.until(EC.element_to_be_clickable((By.ID,"btn")))常用条件:presence_of_element_located:DOM存在(不一定可见)visibility_of_element_located:元素可见element_to_be_clickable:元素可点击三者核心区别类型作用范围等待条件是否全局推荐度强制sleep代码行固定时间局部极低,仅调试隐式等待整个driver元素是否存在DOM全局慎用显式等待WebDriverWait单个元素自定义条件(可见、可点击)局部⭐生产首选最佳实践:以显式等待为主,禁止大量sleep,尽量不要混用隐式+显式。3、Appium底层原理;Android/iOS元素定位Appium底层原理Appium是C/S架构:Client:测试脚本(Python/Java Appium‑Python‑Client)发送http请求;Appium Server:接收http请求,转发给移动端驱动;Android:调用UiAutomator2;iOS调用XCUITest;驱动与设备通信,执行操作,结果返回Appium Server,再返回脚本。Appium不向App植入SDK,基于系统自带测试框架,支持原生、H5、混合应用。Android元素定位方式resource‑id(对应Selenium的id,优先用)accessibility_idxpathclassnameandroid‑uiautomator(Android独有)iOS元素定位方式accessibility_id(iOS最稳定优先)xpathclassnameiOS没有resource‑id;优先让开发给accessibility_id,稳定性最高。工具:uiautomatorviewer / Appium Inspector查看元素属性。4、pytest常用特性;fixture作用域pytest常用特性简单用例书写,不需要必须继承类;函数/类都可以作为用例;强大的fixture做前置后置,替代unittest的setUp/tearDown;丰富断言:直接assert,不用self.assertEqual,报错信息友好;参数化@pytest.mark.parametrize;mark标记:skip、xfail、自定义标签,分组执行用例;失败重试、并发、插件生态丰富;支持unittest用例兼容执行。fixture 5种作用域 scopefunction:默认,每个测试函数执行前后执行;class:每个测试类执行一次;module:每个py模块文件执行一次;session:整个测试会话,全部用例只执行一次,适合初始化数据库、登录token;package:包级别,pytest5.0+,每个包执行一次。fixture可以跨文件,放在conftest.py,不需要import,直接使用。5、unittest 和 pytest 区别,推荐哪个对比项unittestpytest用例写法必须继承unittest.TestCase;self.assertXXX普通函数/类,直接assert,简洁前置后置setUp/tearDown;setUpClassfixture,灵活,多粒度作用域参数化第三方库ddt原生@pytest.mark.parametrize标记过滤弱,需要自己封装原生mark,灵活分组执行报告原生简陋allure/pytest-html插件生态强兼容性只支持自身可运行unittest用例推荐pytest理由:代码简洁,降低维护成本;fixture粒度灵活,适合自动化框架;原生支持参数化、标记;插件生态完善(重试、并发、allure报告);兼容旧unittest脚本,迁移成本低;只有维护老项目时继续用unittest。6、数据驱动测试;pytest实现数据驱动数据驱动DDT:测试逻辑一套,测试数据多套;数据和脚本分离,通过不同输入数据驱动执行多条用例。数据可以写在代码、csv、json、yaml。方式1:原生 parametrize(最常用)importpytest test_data=[("admin","123456",True),("admin","wrong",False),("","123456",False)]@pytest.mark.parametrize("username,pwd,expect_result",test_data)deftest_login(username,pwd,expect_result):res=login(username,pwd)assertres==expect_result方式2:读取yaml/json外部文件做数据驱动把用例数据放到yaml,fixture读取文件加载数据,实现脚本与数据分离。yaml示例 login_data.yamlcases:-{"user":"admin","pwd":"123456","expect":true}-{"user":"admin","pwd":"err","expect":false}脚本读取yaml加载cases传入parametrize。区别关键字驱动:关键字驱动是把操作动作也抽象;数据驱动只分离输入输出数据。7、PO模式是什么?为什么使用POPO:Page Object 页面对象模式核心思想:页面与测试用例分离Page类:封装页面元素定位、页面操作方法;不写断言;Test测试用例:只调用page对象方法,写断言,不写元素定位、页面操作。使用PO的好处解耦:页面UI改动,只修改Page类,不需要修改大量测试用例;维护成本大幅下降;代码复用:多个用例复用页面操作;可读性高,测试用例业务语义清晰;降低重复代码。反模式:用例里面直接写大量xpath、click操作;页面逻辑散落在各个用例。POM = PO Model。8、接口自动化框架设计;requests封装、断言、报告接口自动化框架主要模块requests二次封装模块:统一请求头、公共url、异常捕获、日志打印;数据层:yaml/json存放用例数据;公共工具:token处理、数据提取、文件读取;测试用例层:pytest用例;断言模块:通用响应断言;报告:allure;日志模块log;配置文件:环境地址切换(测试、预发)。requests简单封装示例importrequestsclassHttpRequest:def__init__(self):self.session=requests.Session()defsend(self,method,url,**kwargs):# 统一处理base_url、headers、日志、异常捕获resp=self.session.request(method,url,**kwargs)returnresp使用session自动维护cookie。断言基础:状态码、响应字段、json字段;封装通用断言函数:校验响应码、关键字、数据库结果比对;报告主流:Allure报告,pytest‑allure插件;可以展示用例、步骤、请求响应、失败截图。9、token传递;接口关联、参数化Token传递登录接口获取token;存储到全局变量 / fixture返回;后续接口请求头headers带入Authorization: Bearer xxx;方案:session fixture,session级别只登录一次,返回token,所有用例直接使用。接口关联场景:A接口返回值,作为B接口入参。实现思路:执行A接口,提取返回字段;保存到变量;传给下一个接口;yaml数据驱动场景:使用变量池,保存提取值,用占位符替换后续请求参数。示例:登录拿到token,创建订单接口使用token;查询订单依赖上一步返回order_id。参数化pytest.mark.parametrize;读取yaml/json/csv批量用例;环境参数:通过配置文件区分测试/预发域名。10、自动化框架:失败重试、并发执行、定制报告1)失败重试插件:pytest‑rerunfailures--rerun 3失败重试3次;--reruns‑delay 2重试间隔;可以加标记指定哪些用例允许重试。注意:不要滥用重试,优先修复脚本不稳定,重试只是兜底。2)并发执行插件:pytest‑xdist-n auto根据CPU自动分配进程;‑n 44个进程并发。注意并发坑:fixture注意线程安全;测试数据不能互相冲突;不能共享内存变量;每个进程独立session。3)定制测试报告Allure:工业级,添加步骤、附件(请求响应、截图);pytest‑html简单html报告;二次开发:读取allure结果,自定义解析,对接钉钉/企业微信推送结果。11、Jenkins集成自动化;pipeline关键步骤Jenkins集成自动化步骤Jenkins机器准备python环境,安装项目依赖;拉取代码仓库(git);安装requirements.txt依赖;执行pytest自动化命令;生成allure结果;allure生成报告;结果钉钉/企业微信通知;构建失败标记。Pipeline关键stage示例pipeline{agent any stages{stage('拉取代码'){steps{git url:'xxx'}}stage('安装依赖'){steps{sh'pip install -r requirements.txt'}}stage('执行自动化用例'){steps{sh'pytest --allure-results=allure-results -n 2'}}stage('生成allure报告'){steps{allure generate...}}}post{always{//无论成功失败都推送报告dingTalk notification}}}触发方式:定时构建、代码提交触发、手动触发。12、自动化脚本不稳定(flaky case)原因与解决方案flaky:时而成功时而失败,没有改动代码就报错。常见原因等待问题:没有正确等待,元素没加载完成就操作;混用隐式显式;大量sleep;定位器不稳定:绝对xpath、依赖动态id、依赖页面文本;测试数据污染:用例之间没有隔离,前一个用例残留数据影响下一条;并发执行,共享测试数据;环境问题:网络波动、服务接口超时;弹窗、alert、广告弹窗没有处理;浏览器缓存、cookie残留;接口:token过期,没有重新登录。提升稳定性方案全部改用显式等待,按条件等待,杜绝sleep;优化元素定位,优先id/accessibility_id,写相对xpath/css;做好用例隔离:fixture做数据准备+数据清理;每条用例尽量独立;异常捕获:弹窗、alert做处理;网络超时设置;关键用例失败重试兜底;清理cookie,每个用例前后重置状态;增加详细日志,失败保存请求响应、截图,方便定位;测试数据工厂,每条用例生成全新数据,避免互相干扰。13、测试数据构造;自动化数据工厂设计测试数据构造:自动化执行前生成干净测试数据,执行后清理,避免线上/测试库脏数据,保证用例可重复执行。我做过的数据工厂设计思路封装数据工厂类,提供方法生成用户、订单等业务实体;两种模式:方式A:调用业务接口生成数据;方式B:直接操作测试数据库插入数据;fixture管理:scope=function,每条用例运行前生成数据,yield返回;用例结束后执行删除/还原;支持参数:可以传参数自定义字段,不传则生成默认随机数据;数据加标记,方便批量清理过期脏数据。示例伪代码@pytest.fixturedefcreate_test_user(db_factory):user=db_factory.create_user(username=random_str())yielduser db_factory.delete_user(user.id)#后置清理注意:不要在预发环境随意删除数据;可以做标记,定时脚本批量回收过期测试数据。14、从零搭建接口自动化框架,目录结构api_auto_test/ ├── conf/ #配置文件 │ └── config.yaml #环境地址、账号、超时配置 ├── data/ #测试用例数据 yaml/json │ ├── login_case.yaml │ └── order_case.yaml ├── lib/ #底层封装 │ ├── http_client.py #requests二次封装 │ ├── db_connect.py #数据库工具 │ └── data_factory.py #测试数据工厂 ├── common/ #公共工具 │ ├── assertion.py #通用断言封装 │ ├── token_manage.py #token管理 │ └── yaml_util.py #读取yaml工具 ├── testcases/ #pytest测试用例 │ ├── test_login.py │ └── test_order.py ├── conftest.py #全局fixture:登录token、初始化、数据工厂 ├── logs/ #运行日志 ├── allure-results/ #allure原始结果 ├── requirements.txt #依赖包 └── run.py #执行入口核心设计要点:配置与代码分离,切换环境只改config;请求封装统一处理header、日志、异常;fixture管理前置后置,token、测试数据;数据与脚本分离,yaml存放用例;内置断言、数据工厂;输出日志+allure报告,支持Jenkins CI接入。