赞
踩
在自动化测试领域,元素定位的准确性对于测试的成功至关重要。当使用Playwright结合pytest进行测试时,我们可以通过一些策略来增强测试的鲁棒性,特别是在元素定位失败时能够自动进行修复。本文将详细介绍如何实现这一过程。
首先,确保你的环境中安装了playwright
和pytest
。可以通过以下命令安装:
pip install pytest
pip install playwright
在测试过程中捕获失败并尝试自动修复问题。我们将使用 Playwright 的 Locator 来定位元素,并在失败时重新定位更新元素。
BasePage
类封装了页面操作和自动修复的逻辑。
base.py
# -*- coding: utf-8 -*-
# @Author : blues_C
# @File : base.py
# @Desc:
import re
from utils.logger import log
from playwright.sync_api import Page, expect, Locator
class BasePage:
def __init__(self, page: Page):
self.page = page
def locator(self, selector: str) -> Locator:
"""查找并返回元素"""
element = self.page.locator(selector)
if not element.is_visible():
self.auto_repair()
return element
def click(self, selector: str):
self.locator(selector).click()
def fill(self, selector: str, input_value: str):
self.locator(selector).fill(input_value)
def auto_repair(self, scope_selector: str = "body",
selector: str = "input, button, a, select, textarea, div, span, img, iframe, label, svg",
filename="login_element.py"):
### 自动修复逻辑:尝试重新定位页面上的所有相关元素,并更新我们的元素定位文件。###
page_title = self.page.title()
scope = self.page.locator(scope_selector)
elements = scope.locator(selector).all()
log.info(f"自愈元素: {selector} (共 {len(elements)} 个)")
# 检查文件是否存在
if os.path.exists(filename):
# 读取现有文件内容,以便检查变量名
with open(filename, "r") as file:
lines = file.readlines()
existing_variables = set()
# 获取现有的变量名
for line in lines:
if "=" in line:
variable_name = line.split("=")[0].strip()
existing_variables.add(variable_name)
# 打开文件,准备写入新内容
with open(filename, "w") as file:
file.write(f"# Existing variables from {page_title}\n\n")
for element in elements:
element_info = f"element='{element}', "
start_index = element_info.find("selector=")
if start_index != -1:
selector_str = element_info[start_index + len("selector='"):]
end_index = selector_str.find("'")
if end_index != -1:
selector_content = selector_str[:end_index]
# 获取各个属性
text = element.inner_text()
value = element.get_attribute('value')
element_id = element.get_attribute('id')
element_class = element.get_attribute('class')
element_name = element.get_attribute('name')
element_type = element.get_attribute('type')
element_placeholder = element.get_attribute('placeholder')
# 检查属性是否为 None,并记录非 None 的属性
log_info = f"element='{selector_content}', "
if text != '':
log_info += f"text='{text}' "
if value != '' and value is not None:
log_info += f"[value='{value}'] "
if element_id is not None:
log_info += f"#{element_id} "
if element_class is not None:
log_info += f"[class='{element_class}'] "
if element_name is not None:
log_info += f"[name='{element_name}'] "
if element_type is not None:
log_info += f"[type='{element_type}'] "
if element_placeholder is not None:
log_info += f"[placeholder='{element_placeholder}']"
# 打印日志信息
log.info(log_info)
# 如果变量名已存在,替换现有的定义行
if variable_name in existing_variables:
file.write(f"# {log_info} (replaced)\n")
if element.get_attribute('name') is not None:
variable_name = element.get_attribute('name')
variable_type = selector_content
file.write(f"{variable_name} = '{variable_type}'\n\n")
existing_variables.add(variable_name)
elif element.get_attribute('type') is not None:
variable_name = element.get_attribute('type')
variable_type = selector_content
file.write(f"{variable_name} = '{variable_type}'\n\n")
existing_variables.add(variable_name)
else:
variable_type = selector_content
file.write(f"'{variable_type}'\n\n")
existing_variables.add(variable_name)
else:
# 如果文件不存在,则创建新文件并写入内容
with open(filename, "w") as file:
file.write(f"# {page_title}\n")
for element in elements:
element_info = f"element='{element}', "
start_index = element_info.find("selector=")
if start_index != -1:
selector_str = element_info[start_index + len("selector='"):]
end_index = selector_str.find("'")
if end_index != -1:
selector_content = selector_str[:end_index]
text = element.inner_text()
value = element.get_attribute('value')
element_id = element.get_attribute('id')
element_class = element.get_attribute('class')
element_name = element.get_attribute('name')
element_type = element.get_attribute('type')
element_placeholder = element.get_attribute('placeholder')
info = f"element='{selector_content}', "
if text != '':
info += f"text='{text}' "
if value != '' and value is not None:
info += f"[value='{value}'] "
if element_id is not None:
info += f"#{element_id} "
if element_class is not None:
info += f"[class='{element_class}'] "
if element_name is not None:
info += f"[name='{element_name}'] "
if element_type is not None:
info += f"[type='{element_type}'] "
if element_placeholder is not None:
info += f"[placeholder='{element_placeholder}']"
log.info(info)
file.write(f"# {info}\n")
if element.get_attribute('name') is not None:
variable_name = element.get_attribute('name')
variable_type = selector_content
file.write(f"{variable_name} = '{variable_type}'\n\n")
elif element.get_attribute('type') is not None:
variable_name = element.get_attribute('type')
variable_type = selector_content
file.write(f"{variable_name} = '{variable_type}'\n\n")
else:
variable_type = selector_content
file.write(f"'{variable_type}'\n\n")
conftest.py
import pytest
from playwright.sync_api import sync_playwright
@pytest.fixture(scope='session')
def browser():
with sync_playwright() as p:
browser = p.chromium.launch()
yield browser
browser.close()
test_cases.py
import pytest
from common.base import BasePage
from playwright.sync_api import sync_playwright
def test_auto_repair(browser):
page = browser.new_page()
page.goto('https://example.com')
try:
# 运行测试步骤
BasePage(page).fill(login_element.username, 'username')
BasePage(page).fill(login_element.password, 'password')
BasePage(page).click(login_element.login)
except Exception as e:
pytest.fail(f'Test failed: {e}')
BasePage(page).fill(login_element.username, 'username')
BasePage(page).fill(login_element.password, 'password')
BasePage(page).click(login_element.login)
login_element.py 示例:
# 登录到 standard
# element='form >> input,button >> nth=0', #username [class='form-control'] [name='username'] [type='text']
username = 'form >> input,button >> nth=0'
# element='form >> input,button >> nth=1', #password [class='form-control'] [name='password'] [type='password']
password = 'form >> input,button >> nth=1'
# element='form >> input,button >> nth=2', #id-hidden-input [name='credentialId'] [type='hidden']
credentialId = 'form >> input,button >> nth=2'
# element='form >> input,button >> nth=3', [value='登录'] #kc-login [class='btn btn-primary btn-block btn-lg'] [name='login'] [type='submit']
login = 'form >> input,button >> nth=3'
本文展示了如何使用Playwright的Locator结合pytest的自动化测试框架来实现元素的自动定位和修复。通过封装页面操作和自动修复逻辑到BasePage
类中,我们可以提高测试的稳定性和可维护性。同时,使用pytest的fixture来管理浏览器的生命周期,使得测试更加简洁。
通过上述方法,我们能够确保即使在面对复杂的页面元素变化时,我们的自动化测试也能够适应并成功执行,从而提高测试的覆盖率和准确性。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。