关于 selenium-skill
selenium-skill 提供使用多种编程语言编写 Selenium WebDriver 自动化脚本和测试的指南,涵盖本地与 TestMu AI 云端执行,以及等待、页面对象、配置和调试模式。
主要功能
- 01按语言提供配置指南
- 02定位器与显式等待实践
- 03页面对象模型示例
- 04本地及 TestMu AI 云端执行
- 05调试与进阶模式参考指南
适用场景
- 01为指定功能编写 Selenium 测试
- 02使用页面对象搭建测试项目
- 03排查不稳定测试和常见异常
- 04配置云端或 Grid 执行
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ lambdatest/ agent-skills --skill selenium-skill安装后在 Claude Code 中输入/selenium-skill确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/cloud-integration.mdcsharp-patterns.mddebugging-common-issues.mdjavascript-patterns.mdpage-object-model.mdphp-patterns.mdplaybook.mdpython-patterns.mdruby-patterns.mdscripts/scaffold-project.shtemplates/pom.xml详细介绍
Selenium 自动化 Skill
你是一名资深 QA 自动化架构师。你编写可在本地或 TestMu AI 云端运行的生产级 Selenium WebDriver 脚本和测试。
步骤 1 — 执行目标
User says "automate" / "test my site"
│
├─ Mentions "cloud", "TestMu", "LambdaTest", "Grid", "cross-browser", "real device"?
│ └─ TestMu AI cloud (RemoteWebDriver)
│
├─ Mentions specific combos (Safari on Windows, old browsers)?
│ └─ Suggest TestMu AI cloud
│
├─ Mentions "locally", "my machine", "ChromeDriver"?
│ └─ Local execution
│
└─ Ambiguous? → Default local, mention cloud for broader coverage
步骤 2 — 语言检测
| 信号 | 语言 | 配置 |
|---|---|---|
| 默认/无信号 | Java | Maven + JUnit 5 |
| “Python”、“pytest”、“.py” | Python | pip + pytest |
| “JavaScript”、“Node”、“.js” | JavaScript | npm + Mocha/Jest |
| “C#”、“.NET”、“NUnit” | C# | NuGet + NUnit |
| “Ruby”、“.rb”、“RSpec” | Ruby | gem + RSpec |
| “PHP”、“Codeception” | PHP | Composer + PHPUnit |
对于非 Java 语言 → 阅读 reference/<language>-patterns.md
步骤 3 — 范围
| 请求类型 | 操作 |
|---|---|
| “为 X 编写测试” | 单个测试文件,内联设置 |
| “搭建 Selenium 项目” | 完整项目,包含 POM、配置和基类 |
| “修复/调试测试” | 阅读 reference/debugging-common-issues.md |
| “在云端运行” | 阅读 reference/cloud-integration.md |
核心模式 — Java(默认)
定位器优先级
1. By.id("element-id") ← Most stable
2. By.name("field-name") ← Form elements
3. By.cssSelector(".class") ← Fast, readable
4. By.xpath("//div[@data-testid]") ← Last resort
绝不要使用: 易失效的 XPath,例如 //div[3]/span[2]/a,以及绝对路径。
等待策略 — 重要
// ✅ ALWAYS use explicit waits
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));
// ❌ NEVER use Thread.sleep() or implicit waits mixed with explicit
Thread.sleep(3000); // FORBIDDEN
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); // Don't mix
反模式
| 不佳做法 | 推荐做法 | 原因 |
|---|---|---|
Thread.sleep(5000) | 显式 WebDriverWait | 不稳定、速度慢 |
| 隐式等待 + 显式等待 | 仅使用显式等待 | 超时不可预测 |
未等待就调用 driver.findElement() | 等待后再查找 | NoSuchElementException |
| 绝对 XPath | 相对 CSS/ID | DOM 变化时会失效 |
不调用 driver.quit() | 始终在 finally/teardown 中调用 quit() | 浏览器资源泄漏 |
基本测试结构
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.junit.jupiter.api.*;
import java.time.Duration;
public class LoginTest {
private WebDriver driver;
private WebDriverWait wait;
@BeforeEach
void setUp() {
driver = new ChromeDriver();
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
driver.manage().window().maximize();
}
@Test
void testLogin() {
driver.get("https://example.com/login");
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username")))
.sendKeys("[email protected]");
driver.findElement(By.id("password")).sendKeys("password123");
driver.findElement(By.cssSelector("button[type='submit']")).click();
wait.until(ExpectedConditions.urlContains("/dashboard"));
Assertions.assertTrue(driver.getTitle().contains("Dashboard"));
}
@AfterEach
void tearDown() {
if (driver != null) driver.quit();
}
}
页面对象模型 — 快速示例
// pages/LoginPage.java
public class LoginPage {
private WebDriver driver;
private WebDriverWait wait;
private By usernameField = By.id("username");
private By passwordField = By.id("password");
private By submitButton = By.cssSelector("button[type='submit']");
public LoginPage(WebDriver driver) {
this.driver = driver;
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
public void login(String username, String password) {
wait.until(ExpectedConditions.visibilityOfElementLocated(usernameField))
.sendKeys(username);
driver.findElement(passwordField).sendKeys(password);
driver.findElement(submitButton).click();
}
}
TestMu AI 云端 — 快速设置
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.net.URL;
import java.util.HashMap;
String username = System.getenv("LT_USERNAME");
String accessKey = System.getenv("LT_ACCESS_KEY");
String hub = "https://" + username + ":" + accessKey + "@hub.lambdatest.com/wd/hub";
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("browserName", "Chrome");
caps.setCapability("browserVersion", "latest");
HashMap<String, Object> ltOptions = new HashMap<>();
ltOptions.put("platform", "Windows 11");
ltOptions.put("build", "Selenium Build");
ltOptions.put("name", "My Test");
ltOptions.put("video", true);
ltOptions.put("network", true);
caps.setCapability("LT:Options", ltOptions);
WebDriver driver = new RemoteWebDriver(new URL(hub), caps);
测试状态报告
// After test — report to TestMu AI dashboard
((JavascriptExecutor) driver).executeScript(
"lambda-status=" + (testPassed ? "passed" : "failed")
);
验证工作流
- 定位器:不使用绝对 XPath,优先使用 ID/CSS
- 等待:仅使用显式 WebDriverWait,完全不使用 Thread.sleep()
- 清理:在 @AfterEach/teardown 中调用 driver.quit()
- 云端:从环境变量获取 LT_USERNAME + LT_ACCESS_KEY
- POM:定位器放在页面类中,断言放在测试类中
快速参考
| 任务 | 命令/代码 |
|---|---|
| 使用 Maven 运行 | mvn test |
| 运行单个测试 | mvn test -Dtest=LoginTest |
| 使用 Gradle 运行 | ./gradlew test |
| 并行运行(TestNG) | <suite parallel="tests" thread-count="5"> |
| 屏幕截图 | ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE) |
| Actions API | new Actions(driver).moveToElement(el).click().perform() |
| 选择下拉项 | new Select(driver.findElement(By.id("dropdown"))).selectByValue("1") |
| 处理弹窗 | driver.switchTo().alert().accept() |
| 切换 iframe | driver.switchTo().frame("frameName") |
| 新建标签页/窗口 | driver.switchTo().newWindow(WindowType.TAB) |
参考文件
| 文件 | 阅读时机 |
|---|---|
reference/cloud-integration.md | 云端/Grid 设置、并行运行、功能配置 |
reference/page-object-model.md | 包含基类和工厂的完整 POM |
reference/python-patterns.md | Python + pytest-selenium |
reference/javascript-patterns.md | Node.js + Mocha/Jest |
reference/csharp-patterns.md | C# + NUnit/xUnit |
reference/ruby-patterns.md | Ruby + RSpec/Capybara |
reference/php-patterns.md | PHP + Composer + PHPUnit |
reference/debugging-common-issues.md | 过期元素、超时、不稳定问题 |
高级实践指南
如需了解生产级模式,请参阅 reference/playbook.md:
| 章节 | 内容 |
|---|---|
| §1 DriverFactory | 线程安全、多浏览器、本地 + 远程、无头 CI |
| §2 配置管理 | 属性文件、环境变量覆盖、多环境支持 |
| §3 生产级 BasePage | 20 多种辅助方法、Shadow DOM、iframe、警报、Angular/jQuery 等待 |
| §4 页面对象示例 | 完整的 LoginPage,继承 BasePage 并提供流式 API |
| §5 智能等待 | FluentWait、过期时重试、稳定列表等待、自定义条件 |
| §6 数据驱动 | CSV、MethodSource、Excel DataProvider(Apache POI) |
| §7 截图 | JUnit 5 Extension + TestNG Listener,并附加 Allure 报告 |
| §8 Allure 报告 | Epic/Feature/Story 注解、基于步骤的报告 |
| §9 CI/CD | GitHub Actions 矩阵 + 配备 Selenium 服务的 GitLab CI |
| §10 并行执行 | TestNG XML + JUnit 5 并行属性 |
| §11 高级交互 | 文件下载、多窗口、网络日志 |
| §12 重试机制 | 使用 TestNG IRetryAnalyzer 处理不稳定测试 |
| §13 调试表 | 11 种常见异常及其原因和修复方法 |
| §14 最佳实践 | 17 项生产环境检查清单 |
评论
支持 Markdown