AI智能证件照制作工坊自动化测试:Selenium模拟点击验证
1. 为什么需要为证件照工具做自动化测试
你有没有遇到过这样的情况:刚部署好一个AI证件照工具,朋友急着要一张蓝底一寸照去办签证,你信心满满地打开网页,上传照片、点选参数、点击生成……结果页面卡住不动,或者下载的图片边缘全是白边?又或者换底色时选了“蓝底”,出来的却是灰蒙蒙的一片?
这不是个别现象。AI图像处理类Web应用看似简单——上传、点选、生成——但背后涉及文件读取、前端状态管理、后端异步处理、图片流返回、浏览器渲染等多个环节,任何一个环节出问题,用户就拿不到可用的证件照。
而人工点一遍再检查一遍,效率低、易遗漏、不可复现。尤其当你要频繁验证不同浏览器、不同分辨率、不同图片格式(JPG/PNG/WEBP)下的表现时,手动操作很快就会变成重复劳动。
这时候,用Selenium写一段脚本,让浏览器自动完成“上传→选择→点击→等待→保存”的全过程,就不是“炫技”,而是工程落地的刚需。它不代替人工体验,但能守住功能底线:只要流程能走通,生成结果可下载,基础可用性就有保障。
本文不讲高深的AI模型原理,也不堆砌Selenium API文档。我们聚焦一件事:用最简明的方式,验证这个离线证件照工坊是否真的“一键可用”。你会看到:
- 如何绕过本地文件上传的权限限制
- 怎样精准等待AI抠图完成(而不是盲目sleep)
- 如何判断生成的图片是否真正被浏览器接收
- 一次脚本能覆盖红/蓝/白底 + 1寸/2寸共6种组合
所有代码均可直接运行,无需额外配置,适配Chrome最新稳定版。
2. 工具链与环境准备
2.1 确认运行前提
在开始写测试脚本前,请确保你的AI证件照工坊已成功启动,并可通过浏览器正常访问。通常镜像启动后,平台会提供一个HTTP访问链接(如http://127.0.0.1:7860),点击即可打开WebUI界面。
注意:本文测试基于离线隐私安全版,所有处理均在本地完成,不依赖任何外部API或云服务。因此,Selenium测试也完全在本地闭环执行,无需网络代理或跨域配置。
2.2 安装核心依赖
打开终端,执行以下命令安装必需组件:
pip install selenium beautifulsoup4 pillowselenium:驱动浏览器的核心库beautifulsoup4:用于解析HTML结构,辅助定位元素(比纯XPath更容错)pillow:后续可用于校验生成图片的基本属性(尺寸、模式等),本文暂不展开,但留作扩展接口
2.3 下载并配置ChromeDriver
Selenium需要对应版本的ChromeDriver来控制Chrome浏览器。推荐使用chromedriver-py自动管理:
pip install chromedriver-py该包会在首次运行时自动下载匹配当前Chrome版本的驱动,省去手动下载和路径配置的麻烦。
2.4 准备一张标准测试图
测试必须用真实图片,不能用占位符。建议准备一张正面、清晰、背景杂乱的生活照(例如手机自拍),尺寸不限,格式为JPG或PNG。将其保存为test_photo.jpg,放在脚本同级目录下。
小贴士:避免使用纯白/纯黑背景图,这样才能真正验证Rembg抠图能力;也别用戴帽子、侧脸、严重反光的照片,否则会干扰对“基础功能是否可用”的判断。
3. Selenium测试脚本详解
3.1 核心逻辑拆解
整个测试流程遵循“用户视角”设计,共5个关键动作:
- 启动浏览器并访问WebUI地址
- 上传本地测试图片(需绕过input[type=file]的安全限制)
- 依次选择底色(红/蓝/白)和尺寸(1寸/2寸)
- 点击“一键生成”,等待生成完成并触发下载
- 验证下载行为是否发生(而非仅看按钮变灰)
其中第2步和第4步最具技术细节,我们重点展开。
3.2 绕过文件上传限制的实操方案
现代浏览器禁止脚本直接设置<input type="file">的value属性。常规做法是用send_keys()发送文件绝对路径,但该方法在Docker容器或某些沙箱环境中可能失效。
更稳定的做法是:通过JavaScript直接修改input元素的files列表。Selenium支持执行原生JS,且完全绕过浏览器安全策略:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import os driver = webdriver.Chrome() driver.get("http://127.0.0.1:7860") # 定位文件上传input(根据实际HTML结构调整,此处为典型Gradio结构) file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']") # 构造绝对路径 test_image_path = os.path.abspath("test_photo.jpg") # 执行JS,将文件注入input的files属性 driver.execute_script( "arguments[0].style.display = 'block'; arguments[0].setAttribute('accept', 'image/*');", file_input ) driver.execute_script( "const input = arguments[0];" "const file = new File([new Blob([''], {type: 'image/jpeg'})], arguments[1], {type: 'image/jpeg'});" "const dataTransfer = new DataTransfer();" "dataTransfer.items.add(file);" "input.files = dataTransfer.files;", file_input, "test_photo.jpg" ) # 触发change事件,通知前端文件已更新 driver.execute_script("arguments[0].dispatchEvent(new Event('change', {bubbles: true}));", file_input)这段代码的关键在于:
- 先用JS让隐藏的file input可见(部分WebUI会默认隐藏)
- 创建一个虚拟File对象,名称与真实文件一致(便于后续日志追踪)
- 用DataTransfer模拟用户拖拽行为,注入到input的files属性
- 最后主动触发
change事件,确保前端监听器能捕获到变化
3.3 智能等待生成完成,而非硬编码sleep
很多教程教人用time.sleep(10)等待AI处理,这既不可靠(处理时间随图而异),也不专业(无法区分“卡死”和“还在算”)。
本工坊WebUI在生成过程中,页面上通常会出现一个动态加载指示器(如旋转图标)或按钮文字变为“生成中…”。我们利用Selenium的显式等待机制,监听这些视觉信号:
# 等待“一键生成”按钮变为可点击状态(说明上传完成、参数已就绪) generate_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), '一键生成')]")) ) # 点击生成 generate_btn.click() # 等待加载指示器出现(假设其class包含'loading') WebDriverWait(driver, 30).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".loading, .progress-bar")) ) # 再等待加载指示器消失,且下载按钮/图片预览出现 WebDriverWait(driver, 60).until( EC.invisibility_of_element_located((By.CSS_SELECTOR, ".loading, .progress-bar")) ) WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, "img[alt='Generated ID Photo'], a[download]")) )这里设置了三层等待:
- 第一层:确认生成按钮就绪(防止未选参数就点击)
- 第二层:确认处理已启动(避免误判为“瞬间完成”)
- 第三层:确认处理结束且结果可用(下载链接或预览图出现)
超时时间按实际场景设定:30秒足够Rembg完成单张人像抠图,60秒覆盖复杂边缘处理。若超时,则说明流程中断,测试失败。
3.4 验证下载行为的真实性
很多WebUI只是把生成的图片塞进<img>标签,用户右键另存为才真正下载。但自动化测试无法模拟右键。更可靠的方式是:监听浏览器发起的下载请求。
Selenium本身不提供下载监听API,但我们可以通过一个轻量技巧实现:
- 启动Chrome时指定自定义下载目录
- 生成后,检查该目录下是否有新图片文件(以
.png或.jpg结尾) - 文件创建时间在点击生成之后,即视为下载成功
import tempfile import time # 创建临时下载目录 download_dir = tempfile.mkdtemp() chrome_options = webdriver.ChromeOptions() chrome_options.add_experimental_option("prefs", { "download.default_directory": download_dir, "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": False }) driver = webdriver.Chrome(options=chrome_options) driver.get("http://127.0.0.1:7860") # ...(上传、选择、点击等步骤)... # 记录点击时间 click_time = time.time() # 等待最多30秒,检查下载目录是否有新图片 for _ in range(30): time.sleep(1) files = [f for f in os.listdir(download_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))] if files: latest_file = max([os.path.join(download_dir, f) for f in files], key=os.path.getctime) if os.path.getctime(latest_file) > click_time: print(f" 下载成功:{latest_file}") break else: print("❌ 超时:未检测到生成的证件照文件")该方法不依赖前端是否提供download属性,也不要求图片必须是base64内联,只要浏览器发起了下载,就能捕获,真实反映用户最终能得到什么。
4. 六种组合全覆盖测试设计
4.1 参数组合矩阵
本工坊支持3种底色 × 2种尺寸 = 6种标准输出。自动化测试不应只跑一遍,而应穷举所有组合,确保任意参数下流程都健壮。
我们用嵌套循环实现:
backgrounds = ["红底", "蓝底", "白底"] sizes = ["1寸", "2寸"] for bg in backgrounds: for size in sizes: print(f"\n 正在测试:{bg} + {size}") # 1. 选择底色(假设为radio button组) bg_radio = driver.find_element(By.XPATH, f"//label[contains(text(), '{bg}')]/input[@type='radio']") bg_radio.click() # 2. 选择尺寸(假设为下拉选择框) size_select = driver.find_element(By.CSS_SELECTOR, "select#size-select") size_select.click() size_option = driver.find_element(By.XPATH, f"//option[text()='{size}']") size_option.click() # 3. 点击生成、等待、验证下载... # (此处插入3.2–3.4节中的核心逻辑) # 4. 重置表单,为下一轮测试准备(可选) reset_btn = driver.find_element(By.XPATH, "//button[contains(text(), '重置')]") reset_btn.click() WebDriverWait(driver, 5).until( EC.invisibility_of_element_located((By.CSS_SELECTOR, "img[alt='Generated ID Photo']")) )注意:实际XPath/CSS选择器需根据WebUI真实DOM结构调整。Gradio生成的界面通常有规律可循(如label文本含“红底”,对应input的id可能为
radio_0),建议先用浏览器开发者工具Inspect确认。
4.2 失败时的友好诊断信息
测试失败不可怕,可怕的是不知道哪里错了。我们在每个关键步骤后加入断言和日志:
try: # 尝试点击生成按钮 generate_btn.click() print(" 按钮点击成功") except Exception as e: print(f"❌ 按钮点击失败:{str(e)}") driver.save_screenshot(f"error_click_{bg}_{size}.png") raise try: # 等待结果出现 WebDriverWait(driver, 60).until( EC.presence_of_element_located((By.CSS_SELECTOR, "img[alt='Generated ID Photo']")) ) print(" 生成图片已显示") except TimeoutException: print("❌ 超时:未显示生成的证件照") driver.save_screenshot(f"error_no_result_{bg}_{size}.png") raise每次失败自动保存当前页面截图,文件名包含参数组合,方便快速定位是“红底1寸出错”还是“所有组合都挂”,大幅提升排查效率。
5. 运行效果与结果解读
5.1 一次完整执行示例
当你运行完整脚本后,终端将输出类似以下内容:
正在测试:红底 + 1寸 上传成功:test_photo.jpg 按钮点击成功 生成图片已显示 下载成功:/var/folders/xx/xxx/T/tmpabc123.png 正在测试:红底 + 2寸 上传成功:test_photo.jpg 按钮点击成功 生成图片已显示 下载成功:/var/folders/xx/xxx/T/tmpdef456.png 正在测试:蓝底 + 1寸 上传成功:test_photo.jpg 按钮点击成功 生成图片已显示 下载成功:/var/folders/xx/xxx/T/tmpghi789.png ...(其余组合) 全部6种组合测试通过!若某一项失败,脚本会抛出异常并终止,同时保存对应截图,例如error_no_result_蓝底_2寸.png,打开即可看到当时页面卡在哪个环节——是按钮没响应?还是生成区域一片空白?一目了然。
5.2 结果不只是“通过/失败”
真正的价值在于:测试过程本身成为一份可执行的验收文档。
- 它明确告诉你,这张生活照在“蓝底+2寸”模式下,从上传到下载耗时4.2秒(可在代码中加计时)
- 它记录下生成的图片分辨率为413x626,符合2寸标准(可用PIL校验)
- 它证明即使在Mac Safari(需换driver)下,文件上传也能通过JS注入方式绕过限制
这些不是主观描述,而是由机器逐帧验证的客观事实。当新版本上线,只需重新运行同一脚本,就能立刻回答:“这次更新,有没有破坏用户最常用的功能?”
6. 总结:自动化测试不是负担,而是交付确定性的锚点
AI证件照工坊的价值,在于它把一个原本需要专业设备、专业人员、半天时间的流程,压缩成一次鼠标点击。但这份“简单”,背后是Rembg模型的精度、WebUI交互的流畅、本地计算的稳定性共同支撑的。
而Selenium测试,就是那个默默站在后台的“质量守门员”。它不关心模型用了U2NET还是新的SegFormer,也不纠结CSS动画是否丝滑——它只问一个朴素问题:用户上传一张照片,点一下,能不能拿到一张能用的证件照?
本文提供的脚本,没有炫技式的高级用法,全部基于最基础、最稳定的Selenium原语。你可以把它放进CI流水线,每次镜像构建后自动执行;也可以作为新同事上手的第一份“可运行文档”;甚至稍作修改,就能迁移到其他AI图像工具(如证件照换装、老照片修复)的测试中。
技术的温度,不在于多酷炫的模型,而在于用户按下那个按钮时,心里有没有底。这份确定性,正是自动化测试赋予我们的底气。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。