蓝桥杯软件测试模拟赛实战复盘:Selenium自动化测试那些坑(附完整Python代码)
蓝桥杯软件测试模拟赛实战复盘:Selenium自动化测试那些坑(附完整Python代码)
参加蓝桥杯软件测试赛项的同学们,一定对自动化测试环节又爱又恨。爱的是它能让繁琐的测试工作变得高效,恨的是在实际编码过程中总会遇到各种意想不到的"坑"。本文将基于模拟赛实战经验,深入剖析Selenium自动化测试中最容易踩坑的几个关键点,并提供可复用的Python代码解决方案。
1. iframe切换:自动化测试的第一道坎
在Web自动化测试中,iframe就像是一个个嵌套的小房间,如果你不先"敲门"就直接想操作里面的元素,Selenium会毫不客气地抛出NoSuchElementException。模拟赛中的岗位管理系统就大量使用了iframe,很多同学在这里栽了跟头。
1.1 iframe的三种定位方式
实际操作中,我们主要通过以下三种方式定位iframe:
# 方式1:通过index定位(不推荐,易变) driver.switch_to.frame(0) # 切换到第一个iframe # 方式2:通过name或id定位(推荐) driver.switch_to.frame("iframe6") # 模拟赛中使用的方式 # 方式3:通过WebElement定位(最灵活) iframe = driver.find_element(By.XPATH, '//iframe[contains(@id,"layui-layer")]') driver.switch_to.frame(iframe)关键点:每次操作完iframe内的元素后,必须切换回默认内容,否则后续操作会继续在iframe上下文中执行:
driver.switch_to.default_content() # 这句一定要写!1.2 动态iframe的处理技巧
模拟赛中最坑的是那些动态生成的iframe,它们的id或name会变化。这时就需要使用XPath的contains函数进行模糊匹配:
# 处理动态iframe的黄金法则 dynamic_iframe = driver.find_element(By.XPATH, '//*[contains(@id,"layui-layer-iframe")]') driver.switch_to.frame(dynamic_iframe)2. 元素定位:XPath不是万能的
很多同学习惯用浏览器开发者工具直接复制XPath,这在简单页面上没问题,但在复杂的业务系统中,这种方式往往会导致脆弱的测试脚本。
2.1 相对定位与绝对定位的抉择
对比几种定位方式的优缺点:
| 定位方式 | 稳定性 | 可读性 | 性能 | 适用场景 |
|---|---|---|---|---|
| 绝对XPath | 低 | 差 | 差 | 不推荐使用 |
| 相对XPath | 中 | 中 | 中 | 复杂结构定位 |
| CSS选择器 | 高 | 好 | 优 | 简单元素定位首选 |
| ID/ClassName | 最高 | 最好 | 最优 | 有稳定标识时优先使用 |
模拟赛中的改进案例:
# 优化前(绝对路径,易碎) driver.find_element(By.XPATH, "/html/body/div/div/div[2]/div[1]/div[1]/div[1]/div/a[1]") # 优化后(相对路径+属性组合) driver.find_element(By.XPATH, "//a[contains(@class,'btn-add')]")2.2 智能等待策略
隐式等待(implicitly_wait)虽然方便,但在复杂场景下可能不够用。模拟赛中推荐组合使用:
# 设置基础等待(全局生效) driver.implicitly_wait(5) # 5秒隐式等待 # 关键操作添加显式等待 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "postName")) )3. Page Object模式:架构清晰的秘密武器
模拟赛要求使用Page Object模式,这是大型测试项目的标配。但很多同学对其理解不够深入,导致代码结构混乱。
3.1 经典PO模式实现
以新增岗位页面为例:
class AddPostPage: def __init__(self, driver): self.driver = driver self.post_name_input = (By.ID, "postName") self.post_code_input = (By.ID, "postCode") self.post_sort_input = (By.ID, "postSort") self.ok_button = (By.XPATH, "//a[text()='确定']") def input_post_name(self, name): element = self.driver.find_element(*self.post_name_input) element.clear() element.send_keys(name) def input_post_code(self, code): # 类似实现... def click_ok_button(self): self.driver.find_element(*self.ok_button).click()3.2 进阶:PO模式最佳实践
- 元素定位符统一管理:所有定位表达式集中在类开头
- 不要包含iframe切换:保持页面对象纯净
- 一个方法只做一件事:遵循单一职责原则
- 添加必要的等待:关键操作前确保元素可用
4. 比赛策略:时间管理的艺术
根据模拟赛经验,时间分配不合理是最大的失分点。建议采用以下策略:
3-3-3原则:
- 30%时间给功能测试(正交表+测试用例)
- 30%时间给自动化测试(优先完成基础场景)
- 30%时间给单元测试(分支覆盖法)
- 10%缓冲时间
自动化测试实施步骤:
- 先搭建框架(PO结构+基础配置)
- 实现核心业务流程(登录→新增岗位)
- 补充断言验证
- 最后处理边缘场景
单元测试拿分技巧:
# 分支覆盖法标准流程 def test_phone_number_validation(): # 路径1:空输入 assert is_valid_phone("") == False # 路径2:不足11位 assert is_valid_phone("123456") == False # 路径3:第二位不在3,5,6,7,8 assert is_valid_phone("22412345678") == False # 路径4:符合规则 assert is_valid_phone("13812345678") == True
实际比赛中,建议先完成单元测试这种"低投入高回报"的模块,再处理需要调试时间的自动化测试部分。功能测试虽然重要,但切忌陷入无止境的用例编写中。
