
1. 拿到自动化赛题后先想清楚这四件事再动手蓝桥杯软件测试赛道的自动化测试题很多第一次参赛的同学拿到题目后第一反应就是“赶紧写脚本”。这个冲劲是对的但方向上特别容易跑偏。我自己带过几届备赛学生也做过模拟题的阅卷核对先说一个反直觉的结论自动化测试这道题代码能跑通只占一半分数另一半在工程规范和用例设计上。这里说的“模拟1期”本质就是复刻正式比赛中自动化测试实操题的题型给你一个部署好的Web管理系统给你一份业务需求描述让你在限定时间内用Selenium完成指定场景的自动化测试脚本产出可运行的代码和测试报告。注意正式比赛用的往往不是公开的电商Demo而是比赛方自研的业务系统比如学生信息管理、在线考试系统、商品订单后台这类。别指望网上能找到一模一样的xpath也别指望被测系统会给你留什么好定位的id——它跟你平时练的那些开源Demo有差距但核心套路是共通的。开始写代码之前必须把四件事确认清楚这决定你后面2小时是畅通还是爬坑环境版本。比赛机器上预装的JDK版本、Maven仓库是否可用、Selenium和WebDriverManager版本是多少、浏览器是Chrome还是Firefox、有没有配置好镜像源。这些没确认就写代码后面极有可能出现驱动版本不匹配、依赖下载失败这种能直接把你心态搞崩的问题。正式比赛通常允许提前查看环境说明一定要把版本号记下来写进pom.xml之前先在本地跑一遍。浏览器驱动路径。很多同学在自己电脑上用的是WebDriverManager自动下载驱动到了比赛环境没有外网或者版本不一致就会出现SessionNotCreatedException。稳妥做法是用System.setProperty方式配合手动指定本机驱动路径或先检查WebDriverManager底层目录里是否已经缓存好对应版本。被测系统账号。题目一定会提供至少一个可用账号比如admin/123456。但别只记这一个把密码输错几次测试一下系统是否有验证码、是否有登录失败锁定机制。这会影响你的登录测试用例怎么写。题目给分的颗粒度。蓝桥杯自动化测试的评分点通常拆得很细用例设计是否覆盖需求、元素定位是否有泛化性、是否显式等待、断言是否合理、是不是用了Page Object模式、有没有测试报告和截图、异常场景是否考虑到了。每一小项都扣分所以在写代码之前把题目的功能需求表格看两遍把要覆盖的场景列出来比你多写几十行代码有用得多。模拟1期这个套题我当时是按一个典型的“学生信息管理后台”来设计的。功能上包含登录、学生信息的增删改查、分页查询、退出登录。听起来简单但自动化测试的坑往往不是功能复杂而是你以为某个元素一定能定位到的时候它偏偏定位不到。2. 第一期模拟题的业务场景拆分与用例设计思路2.1 被测系统功能边界模拟题里被测系统是一个学生信息管理后台模块包括登录模块账号密码登录错误密码提示空值校验记住密码学生列表分页显示、按学号/姓名模糊查询、关键字重置新增学生表单字段包括学号、姓名、年龄、性别、班级、邮箱带前端校验和后端校验编辑学生点击行内“编辑”按钮回填数据修改后保存删除学生单条删除删除前有确认弹窗退出登录右上角退出回到登录页2.2 用例设计不要只写“快乐路径”这个最关键。很多新手会把自动化测试题写成“脚本跑通就行”于是用例全是正向操作登录成功、添加成功、查询成功。但题目给的业务需求文档里一般会有一段话“请对以上系统功能进行自动化测试覆盖正常流程和异常流程。”异常流程才是拉开差距的地方。我设计的用例结构是分层级的级别用例编号场景说明预期结果P0TC_LOGIN_001输入正确用户名和密码登录跳转首页右上角显示用户名P0TC_LOGIN_002输入正确用户名、错误密码提示“用户名或密码错误”停留在登录页P1TC_LOGIN_003用户名为空前端提示“请输入用户名”不提交P0TC_STU_ADD_001填写完整合法学生信息提交列表出现新增学生弹出成功提示P1TC_STU_ADD_002学号填写已存在的值后端提示“学号已存在”提交被阻止P1TC_STU_ADD_003必填项为空提交前端标红提示不提交P0TC_STU_QUERY_001按学号精确查询列表只显示该学号记录P1TC_STU_QUERY_002输入不存在关键字列表显示“暂无数据”P0TC_STU_EDIT_001修改学生姓名和班级列表展示修改后的数据P0TC_STU_DEL_001单条删除并确认列表记录消失P1TC_STU_DEL_002删除时取消弹窗记录不删除P0TC_LOGOUT_001点击退出登录回到登录页session清空注意P0和P1的划分。比赛时间有限优先把所有P0跑通跑稳再用剩余时间做P1。如果你的脚本能做到异常场景全覆盖且全部通过这份代码已经能排在不少参赛者前面了因为估摸着有一半人只写正向用例。2.3 需求里的隐性要求读题目时要注意几个容易漏的地方“查询结果需断言到具体字段”比如查询后要断言表格第一行的学号文本等于输入值而不只是“元素存在”“新增成功后需刷新页面验证”这是考你对同步机制的理解直接断言弹窗文本还不够最好reload之后再次断言列表数据“测试报告需包含用例执行时间、通过率、失败截图”这就意味着报告中要自己接日志或者截图逻辑“不得修改被测系统”意味着你不能给页面加id、加data-testid只能基于现有结构定位这些内容题目不一定直接写但会通过“测试报告包含”“测试用例须体现”这样的句式埋着。考试不是看谁写的代码炫而是看谁读懂了题。3. 核心代码逐段拆解登录、增删改查和断言怎么写得又稳又得分3.1 工程结构与依赖版本技术上我用的是Java Selenium 4.x TestNG Maven。这也是蓝桥杯软件测试赛道最主流的组合因为正式赛题里提供的基础模板通常就是这套。student-manager-test/ ├── pom.xml ├── testng.xml └── src/ └── test/ └── java/ ├── base/ │ └── BaseTest.java ├── pages/ │ ├── LoginPage.java │ ├── StudentPage.java │ └── DashboardPage.java ├── utils/ │ ├── ScreenshotUtil.java │ └── ExcelDataProvider.java └── cases/ ├── LoginTest.java └── StudentManageTest.javapom.xml里核心依赖就三个selenium-java、testng、webdrivermanager。版本尽量跟你本机验证过的一致。我用的是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.github.bonigarcia/groupId artifactIdwebdrivermanager/artifactId version5.6.3/version /dependencySelenium 4和3最大的区别是Wait现在推荐用Duration.ofSeconds()而不是ExpectedConditions里传int秒数。其实底层能力没变但写法上4更统一也支持了相对定位器with(By)偶尔能用到比如在学生列表里查某个单元格旁边那行的编辑按钮。被测系统如果是在比赛内网环境没有公网访问Maven中央仓库那么pom里尽量别用最新版本比赛环境预装什么就用什么。我建议你把整套依赖和浏览器驱动提前打一个离线包放在U盘里比赛现场万一环境有问题这是救命稻草。3.2 BaseTest驱动初始化的正确姿势BaseTest是所有测试类的父类核心职责是创建和销毁WebDriver。这里容易犯的错误有两个每个测试方法都new一个浏览器太慢或者整个测试类共用一个浏览器但是用例间数据互相污染。正确的方案是TestNG的BeforeMethod每个用例独立开浏览器AfterMethod负责截图和关闭。public class BaseTest { protected WebDriver driver; BeforeMethod public void setUp() { WebDriverManager.chromedriver().setup(); ChromeOptions options new ChromeOptions(); options.addArguments(--headlessnew); options.addArguments(--no-sandbox); options.addArguments(--disable-dev-shm-usage); options.addArguments(--window-size1920,1080); driver new ChromeDriver(options); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5)); driver.manage().deleteAllCookies(); driver.get(http://localhost:8080/student-manager/login.html); } AfterMethod public void tearDown(ITestResult result) { if (result.getStatus() ITestResult.FAILURE) { ScreenshotUtil.takeScreenshot(driver, result.getName()); } if (driver ! null) { driver.quit(); } } }这里有几个要点--headlessnew是无头模式。比赛机器未必有显示器或者显示器分辨率很低无头模式运行更稳定速度也快。但注意无头模式下截图大小、字体渲染可能和普通模式有细微差异断言文本内容时建议去空白后再比较。隐式等待5秒是兜底策略。不要只用隐式等待后面我强调的显式等待才是关键。两者可以叠加隐式等待是超长上限显式等待会优先返回。每次deleteAllCookies是防止登录状态跨用例相互影响。自动化测试的用例之间要保持独立这也是工程规范的一部分。3.3 Page Object模式为什么比赛里建议用但别用得过度Page Object模式PO模式几乎是自动化测试岗位面试必问题蓝桥杯的评分标准里也隐含了这一点。它的核心思想是把页面元素定位和操作逻辑封装到页面类中测试用例里只写业务步骤和断言。这样浏览器改版时只改页面类用例代码不需要动用例读起来也像需求文档谁都能看懂。public class LoginPage { private WebDriver driver; private By usernameInput By.id(username); private By passwordInput By.id(password); private By loginButton By.id(loginBtn); private By errorMsg By.className(error-tip); private By rememberCheckbox By.name(remember); public LoginPage(WebDriver driver) { this.driver driver; } public void login(String username, String password) { driver.findElement(usernameInput).clear(); driver.findElement(usernameInput).sendKeys(username); driver.findElement(passwordInput).clear(); driver.findElement(passwordInput).sendKeys(password); driver.findElement(loginButton).click(); } public String getErrorMsg() { return driver.findElement(errorMsg).getText(); } }别过度封装是指在元素定位和操作中间增加太多层次比如再包一层BasePage的click(By)、input(By, String)通用方法又包一层业务关键字驱动。比赛只有三四个小时你是在跟时间赛跑不是在做企业级框架。我见过有同学在比赛里写了一个90行的BasePage基类最后用例都没写完。适度的封装一个页面一个类登录、学生管理各一个类就足够。3.4 登录用例DataProvider把代码缩到最短登录这类场景最适合数据驱动。做法是用TestNG的DataProvider把多组账号密码和预期结果放一起一组数据跑一遍用例。代码量直接从3个方法缩到1个方法加1个数据源而且新增用例不用改代码加分项明显。DataProvider(name loginData) public Object[][] loginData() { return new Object[][]{ {admin, 123456, 常用操作, true}, {admin, wrong, 用户名或密码错误, false}, {, 123456, 请输入用户名, false}, {admin, , 请输入密码, false} }; } Test(dataProvider loginData, priority 1) public void testLogin(String username, String password, String expected, boolean success) { LoginPage loginPage new LoginPage(driver); loginPage.login(username, password); if (success) { WebDriverWait wait new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.textToBePresentInElementLocated( By.cssSelector(.welcome a), admin)); Assert.assertTrue(driver.getCurrentUrl().contains(index)); Assert.assertEquals(driver.findElement(By.cssSelector(.welcome a)).getText(), admin); } else { WebDriverWait wait new WebDriverWait(driver, Duration.ofSeconds(5)); wait.until(ExpectedConditions.visibilityOfElementLocated(By.className(error-tip))); Assert.assertEquals(loginPage.getErrorMsg(), expected); } }这段代码里有一个细节很多人会忽略成功登录后不要只断言URL还要断言页面右上角出现用户名。URL的index.html可能所有用户都跳转过去但显示的用户名是区分账号的。这就是所谓的“断言到业务状态”比断言页面跳转更有力。另外注意错误提示的等待方式。密码错误时系统可能是异步校验前端需要几百毫秒才把错误提示渲染出来所以必须显式等待error-tip可见再取文本。我见过有人这里用Thread.sleep(3000)能过但被扣了工程规范分。3.5 学生新增用例动态数据怎么处理不踩重复数据的坑新增学生最容易踩的坑是你上一次跑脚本时已经往数据库里插入了一条学号2024001的数据第二次跑同一条用例时系统报“学号已存在”测试失败。这不是你代码的问题是数据环境污染。常规解法有三个每次生成唯一学号比如基于时间戳String studentNo 2024 System.currentTimeMillis() % 1000000;测试开始前先用SQL或页面删除历史数据但比赛一般不给数据库权限在用例里捕获“已存在”的错误断言为通过这有点投机不建议在正式比赛用我推荐第一种同时断言时用这个动态值去列表里查而不是硬编码。这样脚本无论跑几遍都是绿的。新增用例的核心是表单填写和提交后的双向验证Test(priority 2) public void testAddStudent() { StudentPage studentPage new StudentPage(driver); studentPage.gotoAddPage(); String studentNo 2024 System.currentTimeMillis() % 1000000; String studentName 测试生 System.currentTimeMillis() % 1000; studentPage.fillForm(studentNo, studentName, 20, 男, 软件2101, testexample.com); studentPage.submit(); WebDriverWait wait new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.visibilityOfElementLocated(By.className(layui-layer-content))); Assert.assertTrue(studentPage.getDialogText().contains(新增成功)); // 关闭弹窗后回到列表按学号查询并断言 studentPage.closeDialog(); studentPage.queryByStudentNo(studentNo); wait.until(ExpectedConditions.textToBePresentInElementLocated(By.xpath(//tbody/tr[1]/td[1]), studentNo)); String actualNo studentPage.getFirstRowCol(1); Assert.assertEquals(actualNo, studentNo); Assert.assertEquals(studentPage.getFirstRowCol(2), studentName); }注意提交后要等弹窗出现断言弹窗文案然后关弹窗回列表查询再断言行数据。这是一个完整的闭环写入、提交、回查、断言。测试关注的不只是一次提交动作而是数据库里真的有这条数据且UI展示正确。这种“双向验证”在评分表里往往有一项叫“数据正确性”专门给这种考虑。3.6 删除用例处理弹窗是重点删除操作通常有确认弹窗。有两种常见实现一是原生JavaScript的window.confirm这个Selenium会自动接受你甚至不需要做什么二是页面自定义的Modal弹窗Layui、Element UI这类这个必须拿到弹窗上的按钮定位。蓝桥杯模拟系统里用的是Layui弹窗按钮结构一般是div classlayui-layer-page div classlayui-layer-content确认删除该学生信息吗/div a classlayui-layer-btn0确定/a a classlayui-layer-btn1取消/a /div删除时先点行内的删除按钮等.layui-layer-btn0可见再点确定最后等列表刷新。同时要验证这条数据不在了程序员思维是看接口测试思维是看页面Test(priority 3) public void testDeleteStudent() { // 先造一条数据再删保证不会因为环境数据差异失败 String studentNo addTempStudent(); StudentPage studentPage new StudentPage(driver); studentPage.queryByStudentNo(studentNo); WebDriverWait wait new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(//tr[contains(data-id, studentNo )]//button[text()删除]))); studentPage.clickDelete(studentNo); wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(//a[contains(text(),确定)]))); studentPage.confirmDelete(); wait.until(ExpectedConditions.textToBePresentInElementLocated(By.className(layui-empty), 暂无数据)); Assert.assertTrue(studentPage.isNoData()); }这里我特意先走一遍新增流程构造一条临时数据再删除它。这样做的好处是测试用例可重复执行不依赖环境中预先存在的数据。你可能觉得多花时间但比赛环境下数据往往是共享的多花20秒写这个步骤能帮你避免因为别人把数据删了而用例失败这种冤案。4. 把代码工程化TestNG配置、截图报告和失败重试4.1 testng.xml怎么组织决定了你的用例执行顺序蓝桥杯自动化测试题会要求用例按模块执行不能乱七八糟随机跑。TestNG默认的方法执行顺序受priority控制但是跨多个测试类的时候还需要用preserve-order和test标签来定义。我用testng.xml把所有模块串成一个流程!DOCTYPE suite SYSTEM https://testng.org/testng-1.0.dtd suite nameStudentManagerAutoTest verbose1 test nameLoginModule classes class namecases.LoginTest/ /classes /test test nameStudentManageModule preserve-ordertrue classes class namecases.StudentManageTest/ /classes /test /suite这里选择把LoginTest和StudentManageTest分成两个test原因在于它们共用一套系统但业务上相对独立。如果放同一个test里TestNG默认按方法名的hashcode顺序执行优先级控制不好就会出现“先删除再新增”这种奇怪顺序。分开写就是强制了一个模块跑完再跑下一个可读性和稳定性都更好。在IDE里也可以用Maven插件直接执行mvn clean test -DsuiteXmlFiletestng.xml不过正式比赛判分时判分系统不一定会执行你的Maven命令也可能是直接运行编译后的class或扫描源代码评分。所以代码里每个测试方法最好都能独立运行、不依赖其他方法的运行状态。这也是为什么前面删除用例里要自己先造数而不是依赖另一个测试方法已经插入的数据。4.2 失败自动截图与日志记录测试失败的证据链分三层断言信息、日志输出、截图。截图是给判分老师看的直观凭据也是你自己定位问题的关键。我封装了一个ScreenshotUtil在BaseTest里调用public class ScreenshotUtil { public static void takeScreenshot(WebDriver driver, String caseName) { if (driver instanceof TakesScreenshot) { File src ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); String timestamp new SimpleDateFormat(yyyyMMddHHmmss).format(new Date()); String path reports/screenshots/ caseName _ timestamp .png; try { FileUtils.copyFile(src, new File(path)); } catch (IOException e) { e.printStackTrace(); } } } }还要注意不要在断言失败之后截图因为driver可能已经不在目标页面。正确做法是在AfterMethod里根据ITestResult判断是否失败再截图这时候页面还保留在失败现场。这也是为什么BaseTest里把截图写在tearDown方法中而不是用例内部。关于截图格式PNG比JPG清楚但文件大。比赛报告上传有大小限制的话可以加一句ImageIO压缩或者只保留失败截图。成功用例不需要截图否则report文件会非常大。4.3 报告生成除了TestNG自带报告再加一个HTML汇总TestNG默认会在test-output目录生成一个emailable-report.html包含通过/失败/跳过的数量和时间。这个可以直接交给判分系统。但老练的参赛者会再多做一步——生成一份包含用例设计说明、脚本执行结果、问题记录的统一文档。我的做法是写一个简单的ReportUtil执行完后收集TestNG的测试结果生成一份Markdown格式的汇总内容包含用例编号和名称执行时间通过/失败状态失败原因摘要取断言信息前100字符截图路径这份汇总文件既方便自己复盘也可以作为“测试总结报告”的素材。题目如果要求“提交测试报告”直接贴这个文档肯定比贴一堆控制台输出强。另外建议在测试执行中引入失败的自动重试机制。TestNG里可以用IRetryAnalyzer失败用例自动重跑1次。注意这个不是让你掩盖问题而是处理网络抖动或偶发元素未渲染这类不稳定因素。正式比赛的评分系统如果执行了你的用例一次失败可能只扣一次分但若失败后能重试成功通常不会扣分尤其在“稳定性”这一项上是加分项。public class RetryAnalyzer implements IRetryAnalyzer { private int count 0; private static final int MAX_RETRY 1; Override public boolean retry(ITestResult result) { if (count MAX_RETRY) { count; return true; } return false; } }在Test上标注retryAnalyzer RetryAnalyzer.class即可。不过我提醒一句重试只对“偶发环境问题”有意义如果断言逻辑本身错了重试一百次也过不了。比赛时间宝贵别把重试次数设太高。5. 运行中的稳定性问题我实测踩过的一串坑和排除思路5.1 元素定位失败但手工操作明明能找到这是自动化测试里最常见的报错NoSuchElementException。新手的第一反应是“xpath写错了”第二反应是加Thread.sleep。这两个方向都沾点但都不是根本解法。我的排查链路是这样的第一步打开浏览器开发者工具CtrlF输入你的xpath看能不能定位到且是不是唯一的。注意Selenium的xpath和浏览器的xpath在某些边角情况下结果有差异但绝大多数一致。第二步在报错的最开始把你执行到该步骤时的页面HTML保存下来跟预期对比。很多情况下你会发现页面有两层结构比如iframe。被测系统如果用了iframe直接driver.findElement是找不到里面元素的必须先switchTo().frame()。第三步检查元素是否被遮罩层遮挡。有些Modal弹窗或下拉框展开后屏幕上有透明遮罩Selenium能定位到元素但点击时报ElementClickInterceptedException。解决方法是先点击关闭遮罩或者用js.executeScript(arguments[0].click();, element)强制点击。但强制点击是双刃剑能不用就不用用了需要在注释里写明原因这是工程规范。第四步看是不是页面已经跳转或刷新你操作的还是老的Page类里面的元素引用。Selenium里的WebElement在DOM刷新后会变“失效”StaleElementReferenceException。解决办法是重新查找元素或者封装一个方法每次都重新定位public WebElement reFind(By locator) { return driver.findElement(locator); }在循环分页遍历时这个异常尤其高频。比如翻页后再次获取元素需要重查不要复用之前保存的WebElement引用。5.2 显式等待到底等什么不等什么比赛里我见过最极端的写法是每隔一处就Thread.sleep(2000)。这代码在自己电脑上也许能过但一到判分机器上就时好时坏。判分机器性能可能比你笔记本差页面加载慢500毫秒你的sleep就炸了。显式等待的原则是等一个“业务条件”不是等固定时间。Selenium的ExpectedConditions提供了几十个条件常用的有visibilityOfElementLocated、textToBePresentInElementLocated、elementToBeClickable、invisibilityOfElementLocated。用对了场景稳定性和效率都高。举个例子查询按钮点击后表格刷新可能耗时几百毫秒到几秒。我等的是“某个单元格文本变成查询内容”这个条件足够稳定。而不要等“某个元素存在”——因为表格框架可能查询前后都存在只是内部内容变了。另外注意隐式等待和显式等待的叠加问题。Selenium官方文档说过不要同时使用隐式等待和显式等待否则会导致不可预测的等待时间。但实际中两者叠加并不会报错只是隐式等待被重置或者产生额外等待。稳妥做法是设置隐式等待为兜底3-5秒显式等待用于关键业务点。这种组合在比赛中够用也不至于过度设计。5.3 弹窗和验证码这类“自动化公敌”被测系统如果不幸有验证码先看它是图片校验还是滑块校验。图片校验码自动化有两个思路一是集成OCR识别但准确率在比赛环境不可控而且会消耗大量时间二是直接调后端接口绕过验证码或者找前端隐藏的验证码输入框把验证码字段直接置空或填入万能值。正式比赛通常不会把验证码设成硬门槛因为这是自动化测试不是图像识别比赛。大部分系统在无验证码模式下运行写了验证码的反而少见。如果系统确实有验证码又没提供万能码最不推荐的做法是用Robot类去模拟人工操作。代码写起来很炫但脆得一塌糊涂屏幕分辨率变了就全盘崩溃。我建议题目如果遇到这种系统先在用例里跳过登录直接从已有session开始跑业务流程把登录模块用例标为“手动测试”。这不算作弊而是合理地管理测试范围。弹窗也是重灾区。前面说过了原生alert/confirm/prompt用driver.switchTo().alert()处理自定义Modal弹窗要靠元素定位。两种我都封装成了方法public void handleAlertIfPresent() { try { Alert alert driver.switchTo().alert(); alert.accept(); } catch (NoAlertPresentException e) { // 没有原生弹窗忽略 } }5.4 无头模式与有头模式的诡异差异有一次模拟题跑下来用例在无头模式下全绿但有头模式有两条红。一查发现是某个日期控件在无头模式下渲染的默认值跟有头模式不同。这种事在真实项目里也不少。建议比赛前确定一种运行模式之后全程统一。如果判分系统用无头模式跑你提交的代码就要用同一模式验证。最稳妥的做法是让运行模式可以由系统参数控制String headless System.getProperty(headless, true); if (true.equals(headless)) { options.addArguments(--headlessnew); }这样判分时系统不传参数默认无头你自己调试时加-Dheadlessfalse就能看到真实界面。代码里没有写死可维护性也高。5.5 数据清理与用例独立性自动化测试的铁律是用例之间不能有依赖。但在一个登录态贯穿始终的Web系统里完全独立有点难。我的折中方案是新增模块里造的测试数据统一用Test数据_时间戳命名避免跟真实数据撞车删除模块自己造数据自己删不留垃圾查询模块只查不写用只读断言所有数据操作用例结束后恢复系统到初始状态比如把修改过的数据改回去这一条在比赛中看起来不太重要但“测试数据独立性”在评分表里通常和“测试用例设计”挂钩。别小看这几分蓝桥杯赛道的区分度就体现在这些容易被忽略的细节上。6. 对照评分点做最后的自检清单模拟题跑完之后不要急着交卷按照下面的清单逐项过一遍。这条清单是我反复对照历届赛事要求、模拟评分系统和自己参赛经验总结出来的对正式比赛同样适用。6.1 代码质量维度工程结构是否清晰是否区分了base、pages、utils、cases四个包有没有出现硬等待Thread.sleep如果有注释里有没有写明原因元素定位方式是否统一是都用id还是混用xpath和css推荐统一用css优先涉及复杂结构才用xpath。有没有做显式等待关键操作点击、获取文本、断言之前是否等待了对应业务条件Page Object是否真正落地还是只是建了几个空类摆样子6.2 用例覆盖维度P0用例是否全部覆盖登录正反、增删改查、查询、退出异常场景有没有密码错误、必填空、重复数据、删除取消断言是否到位是否断言了具体业务数据而不只是页面URL或标题数据是否可重复执行第二次运行脚本会不会因为环境数据残留而失败6.3 输出物维度测试报告里是否能清晰看到每个用例执行结果和时间失败截图是否自动保存并能在报告里索引到代码注释是否简洁能不能看出你的设计意图我比赛前会给自己定一个硬指标模拟题整套脚本在全新环境里从拉代码到跑完不超过15分钟且两次执行全部通过。如果做不到说明代码里有隐性的环境依赖没暴露出来。最后分享一个个人习惯赛前把所有浏览器、JDK、Maven依赖、驱动、被测系统部署包全部打包成一份离线备件清单U盘里放一份网盘里放一份。比赛时最怕的不是题难是你以为能跑的环境突然跑不起来。这些准备工作看起来跟“自动化测试”本身没关系但真正决定了你能不能把平时练的实力完整发挥出来。蓝桥杯自动化测试这道题练到后面拼的不是你会不会写findElement而是你在一个不确定的环境里能不能稳定地产出高质量代码。把上面这些步骤都走一遍模拟1期这套题吃透了后面再遇到什么变形题思路都不会乱。