秦皇岛网站推广报价seo技术培训广东
一、项目背景与技术选型
-
项目简介
-
目标系统:论坛系统
-
核心功能:用户注册/登录、会话框发送信息、好友列表、信息发送
-
技术栈:html + Springboot + MySQL数据库
-
-
为什么选择Selenium
-
支持多浏览器兼容性测试(Chrome/Firefox/Edge)
-
完善的元素定位体系(XPath/CSS Selector)
-
动态内容处理能力(WebDriverWait机制)
-
跨平台执行能力(Windows/Linux/macOS)
-
-
测试环境
在开始测试之前,我们需要准备好测试环境。以下是测试所需的硬件和软件环境:
-
硬件:普通个人电脑
-
操作系统:Windows 10 或 Windows 11
-
浏览器:Chrome(版本 128.0.6613.84 或以上)
-
项目运行环境:maven、JDK1.8
-
自动化测试工具:Selenium
二、测试用例设计+手动测试
用户注册
用户登录
用户退出+站内私信
个人中心
帖子模块
三、功能测试用例设计
3.1 注册页面测试
3.1.1 测试场景 1:注册信息不全
-
预期结果:页面提示部分信息不能为空。
-
实际结果:系统确实给出了相应的提示,要求补全所有必填项,与预期一致。
3.1.2 测试场景 2:用户名已存在
-
预期结果:系统应该提示用户该用户名已经存在。
-
实际结果:系统确实给出了提示,提示用户该用户名已经存在,与预期结果一致。
3.1.3 测试场景 3:密码与确认密码不一致
-
预期结果:系统应该提示用户检查确认密码是否输入一致。
-
实际结果:系统确实给出了相应的提示,指示用户检查确认密码,与预期结果一致。
3.1.4 测试场景 4:注册成功
-
预期结果:系统应该显示注册成功,并跳转回登录界面。
-
实际结果:系统确实显示了注册成功,并且跳转回了登录界面,符合预期。
3.2 登录页面测试
3.2.1 测试场景 1:用户名和密码正确
-
预期结果:系统应该显示登录成功,并跳转到论坛首页。
-
实际结果:系统确实显示了登录成功,并且跳转到了论坛首页,与预期结果一致。
3.2.2 测试场景 2:用户名正确,密码错误
-
预期结果:系统应该显示登录失败,并给出相应的错误提示。
-
实际结果:系统确实显示了登录失败,并给出了错误提示,符合预期。
3.2.3 测试场景 3:用户名不存在
-
预期结果:系统应该显示登录失败,并给出相应的错误提示。
-
实际结果:系统确实显示了登录失败,并给出了错误提示,符合预期。
3.3 首页测试
3.3.1 测试场景 1:未登录或登录过期
-
预期结果:系统应该自动跳转回登录界面,要求用户重新登录。
-
实际结果:系统确实执行了跳转回登录界面的操作,与预期一致。
3.3.2 测试场景 2:登录状态下点击“首页”按钮
-
预期结果:应该显示导航栏中的所有版块名称,下方应显示所有帖子列表,并且右上方应该显示登录用户的信息。
-
实际结果:系统确实展示了导航栏中的所有版块名称,下方显示了所有帖子列表,并且右上方显示了登录用户的信息,与预期一致。
3.4 编辑界面测试
3.4.1 测试场景 1:未登录状态下尝试进入编辑页面
-
预期结果:系统应该自动跳转回登录界面,要求用户重新登录。
-
实际结果:系统确实执行了跳转回登录界面的操作,与预期一致。
3.4.2 测试场景 2:登录状态下发布帖子时不输入帖子标题
-
预期结果:系统应该给出提示,要求用户输入帖子标题。
-
实际结果:系统确实给出了提示,要求用户输入帖子标题,与预期一致。
3.4.3 测试场景 3:登录状态下发布帖子时不输入帖子内容
-
预期结果:系统应该给出提示,要求用户输入帖子内容。
-
实际结果:系统确实给出了提示,要求用户输入帖子内容,与预期一致。
3.4.4 测试场景 4:登录状态下输入了帖子标题和帖子内容,然后点击发布按钮
-
预期结果:系统应该成功编辑帖子,并跳转回首页,最上方应该显示刚发布的帖子信息。
-
实际结果:系统确实执行了编辑成功的操作,跳转回了首页,并在最上方显示了刚发布的帖子信息,与预期一致。
3.5 帖子详情页面测试
3.5.1 测试场景 1:未登录或者登录过期的状态下,点击首页中的任意一条帖子内容
-
预期结果:系统应该自动跳转回登录界面,要求用户重新登录。
-
实际结果:系统确实执行了跳转回登录界面的操作,与预期一致。
3.5.2 测试场景 2:登录状态下,点击首页中的一条帖子内容–作者和登录用户不一样
-
预期结果:系统应该跳转到该帖子的详情页面。
-
实际结果:系统确实跳转到了该帖子的详情页面。
3.5.3 测试场景 3:登录状态下,点击首页中的一条帖子内容–作者和当前登录用户一样
-
预期结果:系统应该跳转到该帖子的详情页面,最上方应该显示该帖子的信息,左侧应该显示帖子作者的信息,下方应该显示点赞按钮、删除按钮和编辑按钮。
-
实际结果:系统没有展示了预期的内容,包括帖子信息、作者信息、帖子内容以及点赞按钮、删除按钮和编辑按钮,与预期一致。
、
等等一系列功能的手动测试实践
四、自动化测试实现
整体设计如下
4.1导入pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>ForumAutoTest</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.8.0</version></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.0.0</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency></dependencies><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties></project>
这次没有用到Junit单元测试方法,用的都是平常常见依赖
4.2 Utils类
package common;import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统公共方法*/public class Utils {public static WebDriver driver;public static WebDriver createDriver(){if(driver == null){WebDriverManager.chromedriver().setup();ChromeOptions options = new ChromeOptions();//允许访问所有链接options.addArguments("--remote-allow-origins=*");driver = new ChromeDriver(options);//等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));}return driver;}public Utils(String url) {//调用driver对象driver = createDriver();//访问urldriver.get(url);//窗口最大化driver.manage().window().maximize();}//屏幕截图public void getScreenShot(String str) throws IOException, IOException {// ./src/test/image/// /2024-07-17/// /test01-17453010.png// /2024-07-18/// /test01-17453030.png//屏幕截图SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");String dirTime = sim1.format(System.currentTimeMillis());String fileTime = sim2.format(System.currentTimeMillis());//./src/test/image/2025-xx-xx/test01-17453020.pngString filename ="./src/test/image/"+ dirTime +"/" + str + "-" + fileTime+".png";File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);//srcFile放到指定位置FileUtils.copyFile(srcFile,new File(filename));}}
常见的浏览器驱动和屏幕快照
4.3注册页面功能测试 RegisterPageTest.java
package Test;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统注册页面* Author: WJW*/
public class RegisterPageTest extends Utils {public static String url = "http://127.0.0.1:9580/sign-up.html";public RegisterPageTest() {super(url);}public void RegisterPageRight() {//论坛logo图标driver.findElement(By.cssSelector("body > div > div > div.text-center.mb-4 > img"));//用户注册driver.findElement(By.cssSelector("#signUpForm > div > h2"));}//注册成功public void RegisterSuc() throws InterruptedException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("橘子004");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("橘子树0");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000);//校验注册是否成功并返回登录页面String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}//注册失败01--该用户已存在public void RegisterFai01() throws IOException {//在登录页面点击注册按钮// driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("1");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail01.equals("警告");}//注册失败02--用户名为空public void RegisterFai02() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名 当前用户名为空driver.findElement(By.cssSelector("#username"));//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail02 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(2) > div")).getText();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail02.equals("用户名不能为空");}//注册失败03--昵称为空public void RegisterFai03() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("1");//输入昵称 当前昵称为空driver.findElement(By.cssSelector("#nickname"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail03 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(3) > div")).getText();//截图保存当前异常getScreenShot(getClass().getName());//断言assert fail03.equals("昵称不能为空");}//注册失败04--密码与确认密码不一致public void RegisterFai04() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("13");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail04 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(5) > div > div")).getText();getScreenShot(getClass().getName());assert fail04.equals("请检查确认密码");}//注册失败05--未点击同意使用条款和隐私服务public void RegisterFai05() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//未点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy"));//点击注册driver.findElement(By.cssSelector("#submit")).click();//截图保存当前异常getScreenShot(getClass().getName());}}
4.4登录页面功能测试 LoginPageTest.java
package Test;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统登录页面*/
public class LoginPageTest extends Utils {public static String url = "http://127.0.0.1:9580/sign-in.html";public LoginPageTest() {super(url);}//通过查看页面元素是否存在来检查页面加载成功与否public void loginPageRight(){//论坛logo图标driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.mb-4 > img"));//用户登录driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2"));}//检查登录功能public void LoginSuc(){//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("xiaoweng");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("0123");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//检查点击登录是否成功//通过查看比特论坛logo是否登录成功driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > h1 > a > img"));//通过查看发布帖子是否登录成功driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));//通过页面标题来检查是否成功String title = driver.getTitle();assert title.equals("比特论坛");//返回登录页面// driver.navigate().back();//刷新页面// driver.navigate().refresh();}//检查登录失败01--密码错误public void LoginFail01() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("aaa");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div>h2")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res01.equals("警告");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败02--用户名为空public void LoginFail02() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res02 = driver.findElement(By.cssSelector("#signInForm > div.mb-3 > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res02.equals("用户名不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败03--密码为空public void LoginFail03() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("swhdf");//输入密码driver.findElement(By.cssSelector("#password"));//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res03 = driver.findElement(By.cssSelector("#signInForm > div.mb-2 > div > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res03.equals("密码不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}}
4.5 不登入页面功能测试 PageByNoLogin.java
package Test;import common.Utils;public class PageByNoLogin extends Utils {public static String listurl = "http://127.0.0.1:9580/index.html";public PageByNoLogin() {super(listurl);}public void ListPageByNoLogin() throws InterruptedException {// driver.get(listurl);//直接返回登录界面Thread.sleep(1000);String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}
}
4.6 总测试用例 RunTests.java
import common.Utils;
import Test.ListPageTest;
import Test.LoginPageTest;
import Test.PageByNoLogin;
import Test.RegisterPageTest;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:论坛系统自动化测试* Author: HY* Date: 2025-03-02* Time: 21:16*/
public class RunTests {public static void main(String[] args) throws IOException, InterruptedException {//未登录页面测试PageByNoLogin pageByNoLogin = new PageByNoLogin();pageByNoLogin.ListPageByNoLogin();RegisterPageTest register = new RegisterPageTest();
// //测试注册页面是否加载成功register.RegisterPageRight();
// //注册成功register.RegisterSuc();//注册失败register.RegisterFai01();register.RegisterFai02();register.RegisterFai03();register.RegisterFai04();register.RegisterFai05();LoginPageTest login = new LoginPageTest();//测试登录页面是否加载成功login.loginPageRight();//登录失败login.LoginFail01();login.LoginFail02();login.LoginFail03();// 登录成功login.LoginSuc();ListPageTest list = new ListPageTest();//测试列表页面是否加载成功list.ListByLoging();//测试站内信息回复成功list.MessageSuc();//测试站内信息回复失败list.MessageFail();//成功发布帖子list.PublishPostSuc();//发布帖子失败list.PublishPostFail();//显示个人帖子list.ShowPost();// 点赞list.LickCount();/*//编辑成功list.EditSuc();//编辑失败list.EditFail();//删除成功list.DeleteSuc();//删除失败list.DeleteFail();*///回复成功list.RepleSuc();//回复失败list.RepleFail();//个人中心list.PersonalCenter();//个人中心修改失败list.PersonalCenterModifyFail01();list.PersonalCenterModifyFail02();list.PersonalCenterModifyFail03();//个人中心修改成功list.PersonalCenterModifySuc();//退出list.Exit();//释放driver对象Utils.driver.quit();}
}
五、常见错误Exception in thread "main" org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point
常见的很多都是一些基础的写法,有一部分地方当我们直接使用
类似于
driver.findElement(By.cssSelector("#setting_submit_email")).click();
这样的写法时,我们会发现,如果这个提交或者修改按钮不在你打开的这个页面当中时,我们会发现一个
Exception in thread "main" org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point
这样的一个报错,我所作的修改是类似于
// 定位提交按钮WebElement submitButton = driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button"));((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'});",submitButton);// 添加短暂等待确保滚动完成Thread.sleep(1000);WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));wait.until(ExpectedConditions.elementToBeClickable(submitButton)).click();
这样的写法,显示等待并用js去定位我们的按钮,当然,很重要的一点,你在自己将页面滑下去的时候,它会停留在你定位按钮的位置,接下来当然要把它在返回上去
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
这是我在编写我的测试时遇到的一个比较常见且应该记住的一个错误
测试完整版视频可见我主页视频资源内
论坛测试