恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

SpringBoot+Selenium+TestNG+Allure框架搭建实战

  • 首页
  • 资讯中心
  • /
  • SpringBoot+Selenium+TestNG+Allure框架搭建实战

相关资讯

边缘部署深度学习硬件选型指南:从算力评估到模型优化的实战路径 2026/10/21 18:04:13
串口通讯参数配置全解析:从波特率到校验位,解决乱码与通信故障 2026/10/21 18:04:13
Adapter发包优先级设计与调试:多级队列调度实战 2026/10/21 17:59:13

最新资讯

4.3.5 CPU 访问:vmap、mmap 与缺页处理
dns命令排查解析nslookup ,关闭加密dns
yuzu Switch 模拟器 30 分钟上手指南:从源码构建到图形性能调优
为什么3D设计师都在收藏3D Resources:3500+免费3D资源一站式导航完整介绍
三款Steam挂刀工具实测横评:SteamTradingSiteTracker的24小时比价凭什么能跑赢?
AF Media Bar 架构详解:WPF + MVVM + Win32 构建任务栏媒体控制器的分层设计

今日推荐

电商智能运营体系从0到1:架构设计、落地步骤与避坑指南
压缩空气储能与热网热惯性联合优化调度:热电联产系统建模与求解
若依框架AI代码生成不稳定?用Agent Skill三层结构+五步法搞定

本周热门

基于GMM的语音识别系统原理与MATLAB实现详解
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

SpringBoot+Selenium+TestNG+Allure框架搭建实战

发布时间:2026/10/21 18:04:13
SpringBoot+Selenium+TestNG+Allure框架搭建实战 做Java后端的人想转自动化测试或者测试团队想统一提升技术栈基本绕不开这个组合SpringBoot Selenium TestNG Allure。我最早是从JUnit加裸Selenium脚本起步的写了几十个散落的测试类痛点非常明显——没有统一的地方管理测试数据没人管浏览器生命周期测试报告只有一行行通过/失败的平铺列表出了问题都不知道是哪一步崩的。后来花了一周把这条链路完整搭起来测试代码总量没怎么变维护成本却实打实降了一个量级。这篇文章不聊虚的直接把从零到跑通一条完整Web自动化链路的思路和关键代码拆开讲。你会看到一个用SpringBoot管理依赖注入、Selenium操作浏览器、TestNG调度执行、Allure输出可视化报告的最小可用框架以及我在实际搭建过程中踩进去的坑。适合有Java基础、想入门前端UI自动化的同学也适合团队里想从脚本脚本模式升级到框架模式的测试开发。1. 四条技术线各解决什么问题先想清楚为什么这么配很多初学者容易把自动化框架理解成把几个工具加进pom.xml就能跑结果装完依赖照样一脸懵。我在搭这套东西之前先花时间搞清楚了一个问题这四条线配合到底谁在干什么。1.1 SpringBoot不是给测试写的但它是天然的对象管理容器SpringBoot的核心能力是依赖注入和自动配置。放到自动化测试场景里它的价值体现在三个地方第一测试代码里所有需要被共享的组件——配置文件读取、数据库访问、接口调用、测试数据构造——都能统一交给Spring管不需要在每个测试类里手动new来new去第二被测项目本身往往就是SpringBoot应用测试工程和业务代码用同一套配置语义降低理解成本第三Spring的profile机制可以让你在本地、测试环境、预发布环境之间切换配置不需要改代码。这里有个常见的认知误区以为自动化测试框架引入SpringBoot是大炮打蚊子。实际上当你的测试需要连数据库准备数据、调用业务服务校验结果、或者对接消息队列的时候Spring容器带来的便利远超它启动占用的那几秒时间。1.2 Selenium的核心是模拟人在浏览器里操作Selenium解决的是浏览器自动化问题它通过WebDriver协议跟浏览器通信把打开页面点击按钮输入文本断言页面元素这些动作翻译成浏览器能执行的原生指令。这套生态之所以到现在还是UI自动化的主流是因为它支持多种浏览器而且浏览器厂商官方维护driver不容易被版本迭代甩掉。需要特别说明的是Selenium本身不关心你的测试用例怎么组织、怎么报告失败、怎么并发执行它只是一个操作浏览器的工具库。这也是为什么它必须配合TestNG这种测试框架来用——一个管怎么做一个管什么时候做、做完怎么收尾。1.3 TestNG比JUnit更适合复杂测试场景JUnit在单元测试里很香但做Web自动化这种偏集成、偏端到端的场景TestNG有几个硬优势。最核心的是它把测试套件的概念做得很完整通过testng.xml可以灵活组合哪些类参与执行、按组过滤、指定并行策略。JUnit 5虽然也在追赶但TestNG的DataProvider数据驱动、失败重试、依赖测试这些机制是天生为业务测试设计的。还有一个细节TestNG的断言失败默认会标记为fail并继续跑后续配置方法而不会像某些框架那样直接把整个JVM干掉。对于一套要跑几百条用例的UI自动化来说这个行为差异很影响运行效率。1.4 Allure是把测试结果变成可读报告的那一层Allure本身不执行任何测试它通过注解和监听器收集执行过程中的步骤、参数、附件、断言结果最后生成一个带时间线、步骤树、失败原因聚合的静态站点报告。为什么团队里要专门留一层来做报告因为测试跑完是要给人看的——开发要能一眼看出是不是自己改的东西把用例弄挂了测试要能定位是哪一步操作失败领导要能看出这轮回归的整体质量趋势。Allure在这方面的成熟度目前没有平替。2. 环境准备与项目骨架搭建这一步决定后面踩多少坑2.1 本地环境与版本搭配我实际用得比较稳的一套版本组合是JDK 8或JDK 11、Maven 3.8、SpringBoot 2.7.x、Selenium 4.x、TestNG 7.x、Allure TestNG适配器2.24.0。为什么SpringBoot不直接用3.xSpringBoot 3要求JDK 17如果团队还在用JDK 8维护老项目硬上3.x会把构建环境搞得很复杂。自动化测试框架追求的是稳定不是追新。浏览器方面Chrome配ChromeDriver是最省心的组合版本号必须严格匹配。这里强烈建议引入webdriver-manager这个工具库它会在运行时自动下载匹配的driver二进制文件省去手动去各浏览器官网找版本的痛苦。Selenium 4自带的Selenium Manager也在做类似的事但webdriver-manager在团队内网环境下的可控性更好我一直在用。2.2 Maven依赖引入与常见版本坑一个最小可用工程的pom.xml核心依赖长这样dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId version2.7.18/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId version2.7.18/version scopetest/scope /dependency dependency groupIdorg.seleniumhq.selenium/groupId artifactIdselenium-java/artifactId version4.15.0/version /dependency dependency groupIdorg.testng/groupId artifactIdtestng/artifactId version7.8.0/version scopetest/scope /dependency dependency groupIdio.qameta.allure/groupId artifactIdallure-testng/artifactId version2.24.0/version /dependency dependency groupIdio.github.bonigarcia/groupId artifactIdwebdrivermanager/artifactId version5.6.3/version scopetest/scope /dependency这里有两个容易炸的点。第一spring-boot-starter-test默认带的是JUnit如果你在同一个工程里同时引入TestNG跑mvn test时Surefire插件会纠结到底用哪个测试框架执行。解决办法是在pom里显式排除JUnit或者直接用testng.xml来驱动执行。第二allure-testng的版本和TestNG版本有兼容关系我遇到过TestNG升到7.9之后Allure步骤丢失的情况锁定7.8.0这个组合是实测相对稳定的。2.3 包结构设计按职责分层不按页面分层新手最容易犯的错是把页面类、测试类、工具类全堆在同一个包下跑上一个月就乱成一锅粥。我现在的标准结构是这样src/test/java ├── config # Spring配置类、WebDriver配置 ├── base # BaseTest、BasePage、自定义监听器 ├── page # 页面对象类 ├── testcase # 测试用例类 ├── service # 被测系统的业务调用封装 └── util # 数据构造、文件处理等工具关键原则是按类型分层按业务分包。比如登录相关的页面类放page包跟登录相关的测试类放testcase包二者通过类名对应而不是建一个login包把页面和测试塞在一起。这样当页面元素变更时你只需要去page包里找对应类不会在testcase包里翻半天。2.4 测试套件配置文件testng.xmlTestNG的执行编排不靠代码里的注解靠的是testng.xml。我在resources目录放了一个最小配置!DOCTYPE suite SYSTEM https://testng.org/testng-1.0.dtd suite nameUI Auto Test Suite parallelmethods thread-count4 test nameLogin Module classes class namecom.example.testcase.LoginTest/ /classes /test /suitesuite标签里的name会直接显示在报告里团队看报告第一眼就是看套件名。parallel和thread-count先不急着开等用例跑稳了再调整。一开始就开并行用例之间的数据冲突会让人怀疑人生。3. SpringBoot与Selenium的整合设计核心在对象管理3.1 用Configuration和Bean管理WebDriverWebDriver对象有个特性——它不是线程安全的而且每个实例都是一个真实的浏览器进程创建和销毁成本都不低。所以比较好的做法是交给Spring管理但是必须用prototype作用域确保每次取到的都是全新的浏览器实例而不是被多个测试共享。Configuration public class WebDriverConfig { Bean Scope(prototype) public WebDriver webDriver() { WebDriverManager.chromedriver().setup(); ChromeOptions options new ChromeOptions(); options.addArguments(--start-maximized); options.addArguments(--disable-notifications); options.addArguments(--ignore-certificate-errors); return new ChromeDriver(options); } }这个Bean按需创建的好处是测试类里只需要Autowired一个WebDriverSpring会保证每个测试方法拿到的都是独立的实例。配合下面的ThreadLocal方案能解决并行执行时driver互相覆盖的问题。3.2 BaseTest基类如何接住Spring上下文TestNG跑测试时不会自动认识Spring的注解所以基类必须继承Spring提供的抽象测试类或者使用SpringBootTest注解建立上下文。我用的是后者配合TestNG的配置方法控制浏览器生命周期SpringBootTest public class BaseTest { Autowired private WebDriverFactory driverFactory; private static final ThreadLocalWebDriver DRIVER_HOLDER new ThreadLocal(); BeforeMethod(groups {ui}) public void setUp() { WebDriver driver driverFactory.createWebDriver(); DRIVER_HOLDER.set(driver); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.manage().window().maximize(); } AfterMethod(groups {ui}) public void tearDown() { WebDriver driver DRIVER_HOLDER.get(); if (driver ! null) { driver.quit(); DRIVER_HOLDER.remove(); } } protected WebDriver driver() { return DRIVER_HOLDER.get(); } }这里有个实际经验如果自己的测试类同时用Test注解表明测试方法又继承了BaseTest一定要把SpringBootTest放在BaseTest上而不是每个测试类上都放。否则Spring容器会启动多次每次都重新加载上下文跑十条用例等于启动了十次应用慢得没法接受。3.3 内置服务器模式本地起服务跑端到端这套框架最常见的落地场景是测自己的SpringBoot Web应用。那就可以直接用SpringBootTest(webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT)启动内嵌服务器再用LocalServerPort拿到实际端口去拼URL。好处是完全不依赖外部环境本地能跑CI上也能跑。SpringBootTest( webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT ) public class LoginTest extends BaseTest { LocalServerPort private int port; private String baseUrl() { return http://127.0.0.1: port; } Test(description 正常登录流程) public void testLoginSuccess() { LoginPage loginPage new LoginPage(driver()); loginPage.open(baseUrl() /login); // 后续断言... } }注意这里有个隐藏问题SpringBoot的内嵌服务器启动是异步的LocalServerPort赋值后服务器不一定已经ready。稳妥的做法是在BaseTest里写一个等待逻辑轮询那个端口直到能建立连接再往下执行用例。3.4 测试数据服务化让Spring管数据准备登录测试用例里最烦的是每次跑之前要准备一条已注册、状态正常的用户数据。以前我是在测试代码里直接连数据库插一条。后来发现用Spring的JdbcTemplate或者直接注入业务Service来准备数据会清爽很多。Component public class TestDataFactory { Autowired private JdbcTemplate jdbcTemplate; public void createUser(String username, String password) { jdbcTemplate.update( INSERT INTO t_user(username, password, status) VALUES(?,?,?), username, password, VALID ); } }测试类里直接Autowired这个工厂类在BeforeMethod里造数据、AfterMethod里清数据。这套测试数据也走Spring管理的思路是SpringBoot测试框架比裸TestNG高一个段位的地方。4. Page Object模式与业务动作封装让用例像在说人话4.1 为什么必须用Page Object如果直接在测试方法里写driver.findElement(By.id(username)).sendKeys(admin)刚开始跑得通但一旦页面结构调整你要在几十个测试方法里改同一个元素定位改到想骂人。Page Object模式的核心是把页面元素定位和页面上的业务操作封装成一个类测试方法只描述业务行为不关心元素怎么找。一个直观对比// 反例直接裸写driver操作 driver.findElement(By.id(username)).sendKeys(admin); driver.findElement(By.id(password)).sendKeys(123456); driver.findElement(By.id(loginBtn)).click(); Thread.sleep(3000); driver.findElement(By.cssSelector(.error)).isDisplayed(); // 正例页面对象封装后用例像人话 LoginPage loginPage new LoginPage(driver()); loginPage.open(); loginPage.login(admin, 123456); Assert.assertTrue(new HomePage(driver()).isWelcomeMessageShown());第二种写法的好处一眼就能看出来。元素定位变动时只改LoginPage一个类登录动作被十个测试方法复用时不需要复制粘贴十遍操作代码。4.2 BasePage公共能力等待、点击、输入都封装好所有页面类继承一个BasePage把高频操作沉淀成公共方法public abstract class BasePage { protected WebDriver driver; protected WebDriverWait wait; public BasePage(WebDriver driver) { this.driver driver; this.wait new WebDriverWait(driver, Duration.ofSeconds(15)); } protected WebElement find(By locator) { return wait.until(ExpectedConditions.visibilityOfElementLocated(locator)); } protected void click(By locator) { WebElement element wait.until( ExpectedConditions.elementToBeClickable(locator) ); element.click(); } protected void type(By locator, String text) { WebElement element find(locator); element.clear(); element.sendKeys(text); } protected boolean isVisible(By locator) { try { return find(locator).isDisplayed(); } catch (TimeoutException e) { return false; } } }这里全部用显式等待不用Thread.sleep。我见过太多自动化代码靠sleep硬撑跑的时候一会儿快一会儿慢实际上显式等待配合ExpectedConditions既稳定又不浪费时间。4.3 页面类与业务动作的写法以登录页为例页面对象既要能描述页面长什么样也要能执行用户在这个页面能做的事情。核心动作返回的是下一个页面对象这样用例代码就能形成自然的页面流转链。public class LoginPage extends BasePage { private final By usernameInput By.id(username); private final By passwordInput By.id(password); private final By loginButton By.cssSelector(#loginBtn); private final By errorTip By.cssSelector(.error-tip); public LoginPage(WebDriver driver) { super(driver); } public void open(String url) { driver.get(url); } public HomePage login(String username, String password) { type(usernameInput, username); type(passwordInput, password); click(loginButton); return new HomePage(driver); } public String getErrorTipText() { return find(errorTip).getText(); } }返回HomePage这个小设计很多人忽略但它很关键它让调用方必须明确登录成功后进入的是哪个页面一旦页面跳转逻辑改了编译期就能发现问题比运行时才失败要好得多。4.4 元素定位策略与等待的取舍能用id就用id没有id再考虑name、CSS Selector最后才是XPath。CSS选择器在Selenium里的执行效率比XPath高而且可读性更好。XPath倒是灵活但一长串//div[classa][contains(text(),...)]的表达式维护起来是真的痛苦。另外要特别提醒一个坑implicitlyWait隐式等待和WebDriverWait显式等待不要混用。Selenium官方文档明确说明两种等待机制混用会把超时时间叠加导致页面卡住很久才报错。我在BaseTest里那个10秒的隐式等待后来实际项目里是去掉的全部换成BasePage里的显式等待稳定性反而好了。5. TestNG高级特性实战调度执行的核心玩法5.1 分组执行与环境差异化TestNG的分组机制非常适合指定环境跑指定范围用例这个需求。我在测试方法上习惯打两组标签一组是模块名Test(groups {login})一组是层级冒烟、回归、全量。Test(groups {login, smoke}, description 冒烟用例验证登录主流程) public void testLoginSuccess() { }testng.xml里可以这样控制执行范围test nameSmoke Test groups run include namesmoke/ exclude namebroken/ /run /groups classes class namecom.example.testcase.LoginTest/ /classes /test这样CI里可以配置代码提交后只跑smoke组每晚定时跑regression全量组。测试代码不需要改只需要在XML里调整过滤条件。5.2 DataProvider数据驱动一条用例跑多组数据UI测试最怕写重复代码。同一个登录校验逻辑正常账号、密码错误、用户不存在、账号锁定——四种场景不应该写四个几乎一样的测试方法而应该用DataProvider喂数据。DataProvider(name loginInvalidData) public Object[][] loginInvalidData() { return new Object[][] { {admin, wrong-pwd, 用户名或密码错误}, {not-exist, 123456, 用户不存在}, {locked-user, 123456, 账号已锁定} }; } Test( groups {login}, dataProvider loginInvalidData, description 登录异常场景校验 ) public void testLoginInvalid(String username, String password, String expectedTip) { LoginPage loginPage new LoginPage(driver()); loginPage.open(baseUrl() /login); loginPage.login(username, password); Assert.assertEquals(loginPage.getErrorTipText(), expectedTip); }用DataProvider还有个额外好处Allure报告里会把每一组数据的参数值展示在用例名旁边开发看到报告时能直接知道是哪组数据挂了不用翻代码去猜。5.3 失败重试机制别让偶发问题拖垮整轮回归UI自动化最大的敌人是偶发性失败——网络抖动、页面加载慢了半拍、动画没跑完就点击。这种失败跟业务bug无关但会让报告上出现一片红。解决思路是引入重试机制TestNG提供了IRetryAnalyzer接口。public class RetryAnalyzer implements IRetryAnalyzer { private int retryCount 0; private static final int MAX_RETRY 2; Override public boolean retry(ITestResult result) { if (retryCount MAX_RETRY) { retryCount; return true; } return false; } }在测试方法上标注Test(retryAnalyzer RetryAnalyzer.class)。配合IAnnotationTransformer可以全局统一加不用每个方法都写。有一点要克制重试次数别超过2次否则一个真bug会被重试机制掩盖成偶发失败测试反而失去了发现问题的能力。5.4 并行执行与线程安全TestNG的parallelmethods能让不同的测试方法并行跑大幅压缩回归时间。但并行前必须确认两件事第一WebDriver必须是线程隔离的也就是前面讲的ThreadLocal方案否则四个线程抢同一个浏览器场景没法看第二测试数据不能互相冲突两个方法同时往同一个账号表里写数据就会互相干扰。我的习惯是先让少量用例在本地并行验证确认没有数据冲突再逐步增加并发数。冒烟用例组保持串行回归组才开并行这是稳和快之间的平衡。6. Allure测试报告集成与优化让报告会说话6.1 用注解把执行过程变成步骤树Allure最有价值的特性是步骤级别的可视化。测试方法上加了Step注解的方法执行结果会展示成一棵可展开的步骤树每一步耗时、每步结果一目了然。用例方法上还可以加Description、Severity、Feature这些标签把业务维度的信息塞进报告。Step(登录系统用户名{0}) public HomePage login(String username, String password) { // 内部实现 } Test(description 验证登录后首页展示用户昵称) Story(账号登录) Severity(SeverityLevel.CRITICAL) public void testHomePageShowsNickname() { // ... }注意Step的占位符用法{0}代表第一个参数这样报告里每步操作都带着实际入参复盘时非常有用。6.2 截图自动挂载失败现场不能丢UI自动化没有截图等于白跑。Allure支持通过Attachment注解自动挂载附件我把截图逻辑封装在BaseTest的切面位置任何用例失败都会自动截图。public class ScreenshotListener extends TestBase { Override public void onTestFailure(ITestResult result) { WebDriver driver webDriverByThreadLocal.get(result.getTestClass().getName()); if (driver ! null) { saveScreenshot(driver); } } Attachment(value 失败截图, type image/png) private byte[] saveScreenshot(WebDriver driver) { return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES); } }在testng.xml里注册这个监听器listeners listener class-namecom.example.base.ScreenshotListener/ /listeners截图以字节数组直接返回并挂载到Allure报告上比在磁盘上存文件再引路径要稳。磁盘文件一旦清理或路径不对报告里就会出现碎图处理起来非常烦。6.3 报告生成与历史数据Allure报告不是自动生成的需要在构建时执行两步命令。我用Maven插件把生成报告绑定到测试执行之后plugin groupIdio.qameta.allure/groupId artifactIdallure-maven/artifactId version2.12.0/version configuration reportVersion2.24.0/reportVersion /configuration /plugin执行顺序是mvn test先跑完然后运行mvn allure:report生成静态报告报告输出到target/site/allure-maven目录。如果想本地实时看用mvn allure:serve会临时起一个HTTP服务并自动打开浏览器。历史趋势数据需要指定--history或把上次的allure-results目录保留下来CI里通常把测试结果和报告都归档为产物artifact这样每次构建的报告就能累积对比趋势。6.4 报告和团队工作流的对接Allure报告我建议至少从三个维度给团队解读按功能模块看哪些模块最近一直在红说明那边回归不够或代码质量在下滑按严重级别看BLOCKER级别的用例挂了必须当天处理MINOR级别的可以进待办池按失败原因看Allure会把相同步骤失败的问题聚合起来如果二十条用例全是同一个元素定位失败应该怀疑是页面改版了而不是修二十处用例。7. 常见问题与排查技巧实录实际踩坑记录7.1 TestNG跑不起来Spring上下文这是搭框架第一天最容易撞上的问题。现象是测试类明明有Autowired字段一运行就是空指针或者直接报找不到Spring上下文。原因通常有两个方向第一pom里没有spring-boot-starter-testSpring的TestContext框架压根没在classpath里第二Surefire插件同时识别到了JUnit和TestNG把TestNG的套件执行绕过去了。我的排查方法是先看target/surefire-reports目录下有没有TestNG的xml结果没有就说明Surefire没走TestNG执行器。解决办法是显式配置Surefireplugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-surefire-plugin/artifactId version3.1.2/version configuration suiteXmlFiles suiteXmlFilesrc/test/resources/testng.xml/suiteXmlFile /suiteXmlFiles /configuration /plugin7.2 并行跑用例时WebDriver打架症状是四个用例同时跑浏览器窗口乱跳日志里报session null或者元素在A用例的页面上被B用例操作。这个基本就是WebDriver实例没有隔离。我在3.2节给的ThreadLocal方案是防这一手的关键。另外一个隐蔽问题是即便用了ThreadLocalBaseTest里如果写的是静态WebDriver字段照样炸。记住一句话WebDriver要么用ThreadLocal包一层要么让Spring的Bean是prototype并且每个线程只拿自己的实例两条路任选但绝不能是类级共享。7.3 Allure报告里看不到步骤和附件跑完测试报告只有用例列表没有步骤树也没有截图。排查思路按顺序走allure-results目录里有没有生成json结果文件allure-testng依赖是否被正确加载监听器是否在testng.xml里注册。还有一个容易忽略的点如果你用IDE直接跑某个Test方法而不是通过testng.xml跑Allure监听器可能没有被注册结果大概率为空。所以统一用testng.xml执行是铁律谁也不能绕。7.4 偶发click失败ElementClickInterceptedException这个异常新加坡页面元素被其他元素挡住了。最常见原因是页面有一个loading遮罩或者弹窗刚好盖住了目标按钮。解决方案不是加sleep而是用更精确的显式等待等待加载遮罩消失再等待按钮可点击。我在BasePage里加了一个封装protected void clickAfterLoadingMaskGone(By buttonLocator, By loadingMaskLocator) { wait.until(ExpectedConditions.invisibilityOfElementLocated(loadingMaskLocator)); wait.until(ExpectedConditions.elementToBeClickable(buttonLocator)).click(); }这类稳定性问题方向永远是把等待目标从等待固定时间改成等待状态成立自动化测试里所有的偶发失败最后排查下来八成都是等待策略不到位。7.5 几条实在的避坑经验把自己这几年跑框架的经验浓缩成几条每条都是真金白银换来的。第一元素定位别用页面上的中文文本更多用稳定的属性标识文本改动会直接让用例崩掉。第二测试数据自包含每个用例自己建数据自己清数据不要依赖其他用例留下的数据否则用例之间的执行顺序会变成玄学。第三断言一定要写message参数Allure报告里失败的用例如果只有一句expected [true] but found [false]你和开发都得当场挠头写上用户昵称未展示当前URL为...这种上下文排查效率能翻倍。第四所有测试代码进代码仓库页面对象和测试用例一起走代码评审把测试当成产品代码的一部分来维护而不是可以随便乱丢的脚本。我个人搭这套东西时的体会是一个框架跑得顺不顺技术选型只占三成剩下七成都藏在等待策略、数据隔离、失败留痕这些看起来不起眼的细节里。SpringBoot Selenium TestNG Allure这条链路本身已经很成熟网上教程一大把但真正让你和别人的差距拉开的是那些踩过坑之后沉淀下来的习惯。如果这篇文章能帮你少踩几个我当年踩过的坑让第一次跑通全红变全绿的时候不那么折腾那就很值了。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号