1. 项目概述:为什么选择Airtest-Selenium与Firefox?
如果你刚接触自动化测试,面对一堆工具和浏览器可能会有点懵。Selenium名气大,但纯代码上手门槛不低;Airtest的图像识别很酷,但主要针对移动端。那有没有一种方法,能让我们这些“零基础”选手,快速上手对桌面浏览器,特别是像Firefox这样普及度高的浏览器进行自动化操作呢?答案是肯定的,Airtest-Selenium这个组合就是为你准备的。
简单来说,Airtest-Selenium是Airtest项目的一个扩展,它把Airtest那套简单直观的操作API(比如点击、输入、断言)嫁接到了Selenium WebDriver之上。这意味着,你既可以利用Selenium强大的浏览器操控能力,又能享受到Airtest带来的、更接近自然语言的脚本编写体验。你不用再死记硬背复杂的find_element_by_xpath,而是可以用touch、text这样的关键词来完成大部分操作,学习曲线平缓得多。
为什么选择Firefox?首先,它的市场份额和开发者友好度毋庸置疑。其次,Firefox的GeckoDriver(Selenium用于控制Firefox的驱动)非常稳定,社区支持也好。更重要的是,在日常测试中,Firefox的页面渲染、插件生态以及对新Web标准的支持,都让它成为一个必须覆盖的测试目标。从那些热搜词也能看出,大家在使用Firefox进行自动化时,会遇到各种实际问题,比如“无法加载您的firefox配置文件”、“驱动安装”等,这正是我们需要系统学习和规避的坑。
本篇文章,我就以一个从零开始的视角,带你走通整个流程:从环境搭建、驱动配置,到编写第一个自动化脚本,再到处理那些令人头疼的常见问题。我的目标是,即使你之前一行Python或测试代码都没写过,跟着做下来,也能让Firefox浏览器在你的指令下“自动”跑起来。
2. 环境搭建与核心组件解析
2.1 Python与pip:一切的起点
自动化测试脚本通常用Python来写,因为它语法简洁、库丰富。所以第一步是安装Python。去Python官网下载最新稳定版(比如3.8以上版本)的安装包,安装时务必勾选“Add Python to PATH”,这样就能在命令行里直接使用python和pip命令了。
安装完成后,打开命令行(Windows上是CMD或PowerShell,Mac/Linux是Terminal),输入python --version和pip --version。如果都能正确显示版本号,说明基础环境OK。
注意:国内网络使用pip安装库可能会很慢。建议配置清华源或阿里云等国内镜像源来加速。方法是在用户目录下(如
C:\Users\你的用户名\)新建一个pip文件夹,里面新建一个pip.ini文件,写入:[global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple [install] trusted-host = pypi.tuna.tsinghua.edu.cn
2.2 安装Airtest-Selenium与Selenium
环境准备好后,安装核心库就一行命令。在命令行中输入:
pip install airtest-selenium这条命令会自动安装airtest-selenium以及它所依赖的selenium库。airtest-selenium是我们要用的主要工具,而selenium是底层驱动浏览器的核心。
验证安装是否成功,可以打开Python交互环境(命令行输入python),然后尝试导入:
from airtest_selenium.proxy import WebChrome如果没有报错,说明安装成功。这里导入的是WebChrome,它是Airtest-Selenium对Selenium WebDriver的一个代理封装,同样适用于Firefox,我们后续会用到它的兄弟WebFirefox。
2.3 Firefox浏览器与GeckoDriver驱动配置
这是最关键也最容易出错的一步。Selenium控制Firefox需要一个名为geckodriver的桥梁。
第一步:安装Firefox浏览器。如果你没有安装,去Mozilla Firefox官网下载并安装最新稳定版。记住你的Firefox安装路径(尤其是Windows系统,默认可能在C:\Program Files\Mozilla Firefox\)。确保你能正常打开Firefox浏览器。
第二步:下载匹配的GeckoDriver。前往GeckoDriver的GitHub发布页。这里有个重要原则:驱动版本最好与你的Firefox浏览器大版本号匹配。比如你用的是Firefox 115,就去找标注支持Firefox 115的GeckoDriver版本。下载对应你操作系统的文件(Windows是.zip,Mac是.tar.gz,Linux也是.tar.gz)。
第三步:配置GeckoDriver到系统路径。这是为了让Selenium能够找到它。
- Windows:将下载的
geckodriver.exe解压出来,放到一个你喜欢的目录,比如D:\WebDrivers\。然后,将这个目录路径(D:\WebDrivers)添加到系统的PATH环境变量中。具体操作:右键“此电脑”->“属性”->“高级系统设置”->“环境变量”,在“系统变量”里找到Path,编辑,新建一条,填入你的路径。 - Mac/Linux:解压后,通常将
geckodriver文件移动到/usr/local/bin/目录下,这个目录默认就在PATH里。在终端执行:sudo mv /path/to/geckodriver /usr/local/bin/
第四步:验证配置。打开命令行,输入geckodriver --version。如果能看到版本信息输出,恭喜你,配置成功了。如果提示“不是内部或外部命令”,说明PATH配置有误或需要重启命令行终端。
实操心得:驱动问题占了新手问题的80%。务必确保浏览器版本和驱动版本基本对应。另一个常见错误是,将
geckodriver.exe放在了有中文或空格的路径里,这也可能导致Selenium找不到它,尽量使用纯英文路径。
3. 第一个自动化脚本:从打开浏览器到搜索
理论说再多不如动手试一下。我们来创建一个最简单的脚本,实现“打开Firefox,访问百度,搜索关键词,然后关闭浏览器”的全流程。
3.1 脚本编写与逐行解读
创建一个新的Python文件,比如命名为first_firefox_test.py,用任何文本编辑器(推荐VS Code、PyCharm)打开,写入以下代码:
# 导入Airtest-Selenium为Firefox封装的类 from airtest_selenium.proxy import WebFirefox from selenium.webdriver.common.keys import Keys import time # 1. 启动Firefox浏览器 # 这里没有指定geckodriver路径,因为我们已经将其加入PATH。 # 如果没加PATH,可以指定:driver = WebFirefox(executable_path=r‘D:\WebDrivers\geckodriver.exe’) driver = WebFirefox() # 2. 设置浏览器窗口最大化(非必须,但看着舒服) driver.maximize_window() # 等待2秒,让页面稳定加载。在实际脚本中,应使用更智能的等待(后面会讲) time.sleep(2) # 3. 打开百度首页 driver.get(“https://www.baidu.com“) print(“已打开百度首页”) time.sleep(2) # 等待页面加载 # 4. 定位搜索框并输入关键词 # Airtest-Selenium的`text`方法可以直接向目标元素输入文本 # 这里通过CSS选择器`#kw`定位百度的搜索输入框(‘#‘代表id) driver.text(“#kw”, “Airtest-Selenium Firefox自动化测试”) print(“已在搜索框输入关键词”) time.sleep(1) # 5. 模拟键盘回车键进行搜索 # 这里我们使用Selenium原生的`send_keys`方法发送回车键 # 先通过Selenium方式找到元素,再执行操作 search_box = driver.find_element_by_css_selector(“#kw”) search_box.send_keys(Keys.RETURN) print(“已触发搜索”) time.sleep(3) # 等待搜索结果加载 # 6. 进行一个简单的断言(验证) # 检查页面标题是否包含我们搜索的关键词 assert “Airtest-Selenium” in driver.title print(“页面标题验证通过!”) # 7. 关闭浏览器 driver.quit() print(“浏览器已关闭,测试完成!”)3.2 脚本运行与结果观察
保存文件后,在命令行中,切换到该文件所在目录,运行:
python first_firefox_test.py你会看到Firefox浏览器自动启动,窗口最大化,然后跳转到百度,在搜索框里自动输入文字并搜索,最后控制台输出一系列提示信息后浏览器关闭。
逐行解读与注意事项:
WebFirefox():这是Airtest-Selenium的启动入口。它会自动调用系统PATH里的geckodriver来启动一个全新的Firefox实例。这个实例是干净的,通常不加载你本地的插件和配置文件,这避免了“无法加载您的firefox配置文件”这类问题,保证了测试环境的一致性。driver.text(“#kw”, ...):这是Airtest-Selenium的特色API,非常直观。第一个参数是CSS选择器,第二个是要输入的文本。它底层帮我们完成了“查找元素”和“输入文本”两个动作。time.sleep():这是“强制等待”,简单但低效。在实际项目中,我们应尽量避免,改用“智能等待”。这里为了首次演示清晰才使用。assert ... in driver.title:这是一个简单的断言。自动化测试的核心之一就是“验证”。这里我们验证搜索后页面的标题是否包含特定字符串。如果断言失败,程序会抛出异常,测试不通过。driver.quit():关闭浏览器并释放驱动资源。务必用quit()而不是close(),close()只关闭当前标签页。
踩坑提醒:第一次运行可能会看到一个Firefox提示“此浏览器正在被自动化测试软件控制”。这是正常的安全提示,Selenium会自动处理,无需担心,也不要手动去点它。如果脚本卡住,检查是否是杀毒软件或防火墙阻止了
geckodriver.exe的运行。
4. Airtest-Selenium核心API实战解析
掌握了基本流程后,我们来深入看看Airtest-Selenium提供了哪些好用的“武器”。它最大的优势是将复杂的Selenium操作封装成了更易懂的指令。
4.1 元素定位:多种方式精准“找到”它
要对页面元素进行操作,第一步是定位它。Airtest-Selenium支持多种定位器,与Selenium一脉相承但写法更集成。
from airtest_selenium.proxy import WebFirefox driver = WebFirefox() driver.get(“your_test_page.html“) # 1. 通过ID定位 - 最快速,唯一 driver.text(“id=username”, “myName”) # 等同于CSS选择器 `#username` # 2. 通过CSS选择器定位 - 最灵活强大 driver.click(“css=.submit-btn”) # 点击class为submit-btn的元素 driver.click(“css=div#content > a:first-child”) # 复杂的CSS选择器 # 3. 通过XPath定位 - 功能强大,但可能慢且脆弱 driver.click(“xpath=//button[@id=‘submit’]“) driver.click(“xpath=//div[contains(@class, ‘list’)]/li[2]“) # 4. 通过链接文本定位 - 专门针对<a>标签 driver.click(“link=登录”) # 点击文字为“登录”的链接 # 5. Airtest的图像识别定位(辅助) - 当元素无法用常规方式定位时 # 需要先对元素截图,保存为.png文件 # driver.click(Template(“button_image.png”)) # 点击与图片匹配的区域定位策略建议:
- 优先级:ID > CSS Selector > XPath。ID最快最准,应首选。
- CSS选择器性能好,语法简洁,是大部分情况下的最佳选择。
- 尽量避免使用绝对XPath(如
/html/body/div[3]/div[2]/button),因为页面结构微调就会导致定位失败。使用相对XPath或属性结合的方式。 - 图像识别是Airtest的强项,但在Web自动化中应作为最后手段,因为受分辨率、缩放、字体渲染影响较大,且执行速度慢。
4.2 常用操作API:模拟用户行为
定位到元素后,就可以对其进行操作了。
# 点击操作 driver.click(“css=#loginBtn”) # 简单点击 driver.double_click(“css=.item”) # 双击 driver.right_click(“css=#contextMenu”) # 右键点击 # 文本输入与清除 driver.text(“css=#searchInput”, “关键字”) # 输入文本,会先清空原内容 # 如果只想追加,而不清空,可以用Selenium原生方式: elem = driver.find_element_by_css_selector(“#searchInput”) elem.send_keys(“追加的文字”) driver.clear(“css=#searchInput”) # 清空输入框 # 获取元素属性与文本 element_text = driver.get_text(“css=.title”) # 获取元素的可见文本 attr_value = driver.get_attribute(“css=#link”, “href”) # 获取元素属性,如href inner_html = driver.get_attribute(“css=#div1”, “innerHTML”) # 获取内部HTML # 鼠标悬停 driver.hover(“css=.dropdown-toggle”) # 鼠标移动到元素上,常用于触发下拉菜单 # 拖拽操作 (Airtest-Selenium封装) # 将元素A拖拽到元素B的位置 driver.drag_and_drop(“css=#itemA”, “css=#areaB”) # 执行JavaScript driver.execute_script(“window.scrollTo(0, document.body.scrollHeight);”) # 滚动到页面底部 driver.execute_script(“arguments[0].click();”, element) # 用JS点击元素,可绕过某些前端限制4.3 等待机制:告别time.sleep,让脚本更智能
强制等待 (time.sleep) 是脚本稳定性和效率的杀手。我们必须使用“智能等待”。
1. 隐式等待 (Implicit Wait):设置一个全局的超时时间,在查找任何元素时,如果元素没有立即出现,WebDriver会轮询查找直到超时。
driver = WebFirefox() driver.implicitly_wait(10) # 单位:秒。后续所有find_element操作最多等10秒注意:隐式等待只对
find_element...这类查找操作有效,对元素状态(如可点击、可见)无效。且设置一次,对整个driver生命周期有效。
2. 显式等待 (Explicit Wait):针对某个特定条件进行等待,更灵活精准。这是推荐的主要等待方式。我们需要导入相关模块。
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 等待某个元素出现在DOM中并可见,最多等10秒,每0.5秒检查一次 wait = WebDriverWait(driver, 10, poll_frequency=0.5) element = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, “#successMsg”))) # 现在可以安全地对element进行操作了 # 其他常用条件: # EC.presence_of_element_located - 元素存在于DOM(不一定可见) # EC.element_to_be_clickable - 元素可点击 # EC.text_to_be_present_in_element - 元素文本包含特定文字 # EC.title_contains - 页面标题包含特定文字3. Airtest-Selenium的assert_template(图像断言等待):这是Airtest的特色,等待屏幕上出现某个特定图像。
# 假设我们有一个‘成功提示.png’的截图 driver.assert_template(“成功提示.png”) # 会等待直到该图片出现在屏幕上,或者超时失败最佳实践:
- 在脚本开头设置一个较短的隐式等待(如5秒),作为查找元素的保底策略。
- 在关键交互点(如点击按钮后等待新页面加载、等待弹窗出现)使用显式等待,条件具体,超时时间根据网络和应用性能合理设置。
- 尽量避免隐式等待和显式等待混用,可能导致总等待时间不可控。
5. 实战进阶:构建一个简单的测试用例框架
单个脚本跑通了,但我们通常需要测试多个场景。这就需要一点简单的框架思维,让脚本更可维护、可复用。
5.1 封装基础操作与页面对象模型(PO)雏形
我们不搞复杂的框架,但可以做一个简单的封装。例如,把对百度首页的操作封装成一个类。
创建一个文件baidu_page.py:
from airtest_selenium.proxy import WebFirefox from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By class BaiduPage: def __init__(self, driver: WebFirefox): self.driver = driver self.wait = WebDriverWait(driver, 10) # 页面元素定位器(Locators),集中管理,方便维护 SEARCH_INPUT = (By.CSS_SELECTOR, “#kw”) SEARCH_BUTTON = (By.CSS_SELECTOR, “#su”) FIRST_RESULT = (By.CSS_SELECTOR, “#content_left .result-op h3 a”) def open(self): “”“打开百度首页”“” self.driver.get(“https://www.baidu.com“) # 等待搜索框加载出来,作为页面加载完成的标志 self.wait.until(EC.presence_of_element_located(self.SEARCH_INPUT)) return self def search(self, keyword): “”“输入关键词并搜索”“” # 使用Airtest-Selenium的text方法输入 self.driver.text(self.SEARCH_INPUT[1], keyword) # 传入CSS选择器字符串 # 使用Selenium原生方式点击搜索按钮(也可以用driver.click) search_btn = self.wait.until(EC.element_to_be_clickable(self.SEARCH_BUTTON)) search_btn.click() # 等待搜索结果区域出现 self.wait.until(EC.presence_of_element_located((By.ID, “content_left”))) return self def get_first_result_title(self): “”“获取第一个搜索结果的标题文本”“” first_link = self.wait.until(EC.presence_of_element_located(self.FIRST_RESULT)) return first_link.text def click_first_result(self): “”“点击第一个搜索结果”“” first_link = self.wait.until(EC.element_to_be_clickable(self.FIRST_RESULT)) first_link.click() # 注意:点击后浏览器标签页可能切换,实际项目中需要处理多窗口 return self5.2 编写测试用例
再创建一个主测试文件test_baidu_search.py:
from airtest_selenium.proxy import WebFirefox import unittest from baidu_page import BaiduPage class TestBaiduSearch(unittest.TestCase): @classmethod def setUpClass(cls): “”“整个测试类开始前执行一次,启动浏览器”“” cls.driver = WebFirefox() cls.driver.maximize_window() cls.driver.implicitly_wait(5) @classmethod def tearDownClass(cls): “”“整个测试类结束后执行一次,关闭浏览器”“” cls.driver.quit() def setUp(self): “”“每个测试方法开始前执行,这里我们每次回到百度首页”“” self.baidu = BaiduPage(self.driver) self.baidu.open() def test_search_functionality(self): “”“测试基本搜索功能,验证结果页标题”“” keyword = “Python编程” self.baidu.search(keyword) # 验证页面标题包含关键词 self.assertIn(keyword, self.driver.title) print(f“测试通过:搜索‘{keyword}’,标题验证成功。”) def test_first_result_link(self): “”“测试搜索结果的第一个链接是否可以获取到文本”“” keyword = “Airtest” self.baidu.search(keyword) first_title = self.baidu.get_first_result_title() self.assertIsNotNone(first_title) self.assertGreater(len(first_title), 0) print(f“测试通过:第一个结果标题是‘{first_title}’。”) if __name__ == “__main__“: unittest.main()运行测试:在命令行执行python test_baidu_search.py。unittest框架会自动运行两个以test_开头的方法,并输出结果。你会看到浏览器打开,执行第一个测试(搜索Python),关闭,然后又重新打开(setUp作用),执行第二个测试。
这样做的好处:
- 可读性高:测试用例(
test_*.py)像自然语言一样描述测试步骤。 - 可维护:页面元素定位器集中在
BaiduPage类中,如果百度前端改版,只需要修改这个类里的选择器,不用到处找。 - 可复用:
BaiduPage类的方法可以在多个测试用例中被调用。 - 结构化:使用
unittest框架,有了标准的setup/teardown(初始化和清理)流程。
实操心得:对于中小型项目,这个程度的封装已经足够。不必一开始就追求像
PageFactory那样的复杂模式。先让脚本跑起来,结构清晰,随着测试用例增多,再逐步重构和抽象。记住,“能工作的简单方案”优于“复杂但难维护的完美方案”。
6. 常见问题排查与实战技巧实录
即使按照步骤操作,你也一定会遇到各种问题。下面是我在实战中总结的“坑”和解决方案。
6.1 驱动与浏览器版本问题
问题现象:WebDriverException: Message: ‘geckodriver’ executable needs to be in PATH.或者SessionNotCreatedException: Expected browser binary location, but unable to find binary in default location...
排查思路:
- 确认
geckodriver在PATH中:命令行运行geckodriver --version。如果失败,检查环境变量配置,并重启命令行或IDE。 - 确认Firefox安装路径:Selenium可能找不到Firefox。可以尝试在代码中指定二进制文件位置:
from selenium.webdriver.firefox.options import Options options = Options() options.binary_location = r“C:\Program Files\Mozilla Firefox\firefox.exe” # Windows示例 driver = WebFirefox(firefox_options=options) # 注意:新版Selenium参数名可能是 `options=options` - 版本兼容性:这是最常见的问题。访问GeckoDriver的GitHub发布页面,查看其Release Notes,确认支持的Firefox版本范围。将Firefox或GeckoDriver升级/降级到匹配的版本。
6.2 元素定位失败(NoSuchElementException)
问题现象:脚本报错,提示找不到元素。
排查与解决:
- 检查选择器是否正确:在浏览器的开发者工具(F12)Console里,用
document.querySelector(‘你的CSS选择器’)或$x(‘你的XPath’)测试一下,看能否找到元素。 - 等待时间不足:元素还没加载出来就去查找了。这是新手最常犯的错误。务必使用显式等待(
WebDriverWait)代替sleep。 - 页面存在iframe/Shadow DOM:如果元素在
<iframe>里,需要先切换进去才能操作。driver.switch_to.frame(“iframe_name_or_id”) # 通过name或id切换 # 或者通过索引 driver.switch_to.frame(0) # 操作iframe内的元素... driver.switch_to.default_content() # 操作完后切回主文档 - 元素属性是动态生成的:有些元素的id或class是每次刷新页面随机变化的。这时需要用更稳定的定位方式,比如通过部分文本、通过父元素的稳定属性结合XPath的
contains、starts-with函数,或者通过元素的其他不变属性。
6.3 浏览器弹窗与警报(Alert)处理
问题现象:页面弹出JavaScript的alert、confirm或prompt对话框,导致脚本卡住。
解决方法:Selenium提供了切换到Alert的接口。
from selenium.common.exceptions import NoAlertPresentException # 等待Alert出现并切换到它 WebDriverWait(driver, 5).until(EC.alert_is_present()) alert = driver.switch_to.alert # 获取弹窗文本 print(alert.text) # 接受(点击“确定”) alert.accept() # 或者取消(点击“取消”) # alert.dismiss() # 如果是prompt,还可以输入文字 # alert.send_keys(“输入的文字”) # alert.accept()6.4 处理新窗口/标签页
问题现象:点击一个链接后,在新标签页打开,但脚本还在操作老页面。
解决方法:需要获取所有窗口句柄并切换。
# 点击一个会打开新标签页的链接 driver.click(“css=#newTabLink”) # 获取当前所有窗口的句柄 all_handles = driver.window_handles # 切换到新打开的窗口(通常是最后一个) driver.switch_to.window(all_handles[-1]) # 在新窗口进行操作... print(“新窗口标题:”, driver.title) # 操作完后,如果想切回原窗口 driver.switch_to.window(all_handles[0])6.5 Firefox配置文件与插件管理
问题现象:想使用一个有特定插件或设置的Firefox配置文件进行测试。
解决方法:可以指定Firefox的profile目录。
from selenium.webdriver.firefox.options import Options from selenium.webdriver.firefox.firefox_profile import FirefoxProfile # 方式1:使用现有配置文件(先手动启动Firefox,在地址栏输入 about:profiles 查看路径) profile_path = r“C:\Users\YourName\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxxx.default-release” options = Options() options.profile = profile_path # 方式2:创建并配置一个新的配置文件 profile = FirefoxProfile() profile.set_preference(“browser.download.dir”, “D:\Downloads”) # 设置下载路径 profile.set_preference(“browser.helperApps.neverAsk.saveToDisk”, “application/pdf”) # 自动保存PDF options.profile = profile driver = WebFirefox(firefox_options=options)注意:使用自定义配置文件时,可能会遇到“无法加载您的firefox配置文件”的提示,这通常是因为该配置文件正在被其他Firefox进程使用。确保所有Firefox实例都已关闭。
6.6 性能与稳定性优化技巧
- 禁用图片加载:可以大幅加快页面加载速度,尤其对于数据驱动的测试。
profile = FirefoxProfile() profile.set_preference(“permissions.default.image”, 2) # 2代表禁用所有图片 options.profile = profile - 使用Headless模式(无头模式):不显示浏览器GUI,在后台运行,节省资源,适合在服务器或CI/CD管道中运行。
options = Options() options.add_argument(“-headless”) driver = WebFirefox(firefox_options=options) - 合理设置超时时间:
implicitly_wait不要设得太大(建议5-10秒),显式等待根据具体操作设置(如登录等复杂操作可设长些)。 - 及时清理:每个测试用例结束后,尽量清理Cookies和LocalStorage,避免测试间相互影响。
def tearDown(self): self.driver.delete_all_cookies() # 也可以执行JS清理 localStorage self.driver.execute_script(“window.localStorage.clear();”)
7. 与持续集成(CI)结合及报告生成
脚本能在自己电脑上跑还不够,我们希望能自动定时跑,或者代码一提交就自动跑,并生成测试报告。
7.1 使用pytest替代unittest(可选但推荐)
pytest是更强大、更流行的Python测试框架,插件生态丰富。 首先安装:pip install pytest。 将之前的测试文件稍作修改,去掉unittest相关的父类和方法:
test_with_pytest.py:
import pytest from airtest_selenium.proxy import WebFirefox from baidu_page import BaiduPage @pytest.fixture(scope=“module”) # 整个测试模块只启动一次浏览器 def driver(): d = WebFirefox() d.maximize_window() d.implicitly_wait(5) yield d # 测试函数使用这个driver d.quit() # 所有测试结束后退出 @pytest.fixture def baidu(driver): page = BaiduPage(driver) page.open() return page def test_search_title(baidu): baidu.search(“自动化测试”) assert “自动化测试” in baidu.driver.title def test_first_result(baidu): baidu.search(“pytest”) title = baidu.get_first_result_title() assert title is not None print(f“第一个结果是:{title}”)运行测试只需在命令行输入pytest test_with_pytest.py -v。
7.2 生成HTML测试报告
使用pytest-html插件可以生成漂亮的HTML报告。 安装:pip install pytest-html运行:pytest test_with_pytest.py -v --html=report.html --self-contained-html运行后会在当前目录生成一个report.html文件,用浏览器打开,可以看到详细的测试结果、通过率、甚至每个步骤的截图(需要配合其他插件)。
7.3 集成到CI/CD(以GitHub Actions为例)
可以在代码仓库中创建.github/workflows/run_test.yml文件,让每次代码推送都自动运行测试。
name: UI Automation Test on: [push, pull_request] # 在推送代码或提PR时触发 jobs: test: runs-on: ubuntu-latest # 使用Ubuntu系统作为运行环境 steps: - name: Checkout code uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: ‘3.9’ - name: Install dependencies run: | python -m pip install --upgrade pip pip install airtest-selenium pytest pytest-html # 安装Firefox和GeckoDriver sudo apt-get update sudo apt-get install -y firefox wget wget https://github.com/mozilla/geckodriver/releases/download/v0.33.0/geckodriver-v0.33.0-linux64.tar.gz tar -xzf geckodriver-v0.33.0-linux64.tar.gz sudo mv geckodriver /usr/local/bin/ - name: Run tests with pytest run: | # 在无头模式下运行测试并生成报告 python -m pytest test_with_pytest.py -v --html=report.html --self-contained-html - name: Upload test report uses: actions/upload-artifact@v2 if: always() # 即使测试失败也上传报告 with: name: ui-test-report path: report.html这样,每次提交代码后,在GitHub的Actions标签页就能看到测试运行状态和下载详细的HTML报告了。
走到这一步,你已经从一个零基础的自动化测试新手,成长为能够搭建环境、编写稳定脚本、处理常见问题、甚至将其集成到自动化流程中的实践者了。自动化测试的核心价值在于将重复、枯燥的手工操作转化为可重复、可验证的脚本,从而释放出更多时间去做更有价值的探索性测试和深度思考。Firefox只是起点,掌握了Airtest-Selenium这套方法,你完全可以将其应用到Chrome、Edge等其他浏览器上。记住,所有复杂的项目都是由一个个简单的driver.get()和driver.click()组成的,关键是开始动手,并持续迭代优化你的脚本。