目录
项目介绍
// "唠嗑星球" 项目专注于打造私密、深度的沟通场景,是一款仅支持一对一交流的即时通讯平台,为用户带来专注且安全的聊天体验;
// 在功能设计上,摒弃了群聊模式,全力优化一对一聊天体验; 项目配备实时消息推送功能,确保重要信息及时触达;聊天记录云端存储,方便用户随时回溯查看;
// 对于用户而言,本项目是维系情感、深入沟通的绝佳工具。无论是与亲朋好友分享生活感悟,还是与合作伙伴进行业务洽谈,都能在这里获得专注、高效且安全的交流体验,助力每一次一对一沟通都充满温度与价值。
项目源码库地址
唠嗑星球 git 仓库地址, 点击跳转https://gitee.com/zhou-jintao2002/web-chat-auto-test
项目功能测试
1.自动化实施步骤
1.1 编写测试用例
1.2 自动化测试脚本开发
1.2.1 配置相关环境, 添加相关依赖
// 自动化测试基础知识及相关函数, 包括 Selenium 的安装和使用基础教程
1.2.2 相关代码编写
// 我们将需要测试的内容按照具体需求放到不同的文件夹中, 方便管理
common/Untils.java
public class Untils {
public static WebDriver driver;
public static WebDriver createDriver() {
if (driver == null) {
// 创建驱动对象
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
// 设置无头模式
options.addArguments("-headless");
// 设置浏览器加载策略
options.setPageLoadStrategy(PageLoadStrategy.NORMAL);
// 允许访问所有链接
options.addArguments("--remote-allow-origins=*");
// 驱动创建好了
driver = new ChromeDriver(options);
// 创建隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));
}
return driver;
}
public Untils(String url) {
// 调用 driver 对象
driver = createDriver();
// 访问url
driver.get(url);
}
/*
创建屏幕截图
*/
public void getScreenShot(String str) throws IOException {
// 屏幕截图
SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");
String dirTime = sim1.format(System.currentTimeMillis());
String fileTime = sim2.format(System.currentTimeMillis());
// 生成文件的格式为: 年-月-日/test.类名-时分秒毫秒.png
String fileName = "./src/test/image/" + dirTime + "/" + str + "-" + fileTime + ".png";
// System.out.printf("fileName:" + fileName);
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// srcFile 放到指定位置
FileUtils.copyFile(srcFile,new File((fileName)));
}
}
tests/LoginPage.java
public class LoginPage extends Untils {
public static String url = "http://127.0.0.1:8080/login.html";
public LoginPage() {
super(url);
}
/*
检查页面是否加载成功
*/
public void loginPageRight() throws InterruptedException, IOException {
getScreenShot(getClass().getName());
// 通过查看页面元素是否存在来检查页面加载成功与否
driver.findElement(By.cssSelector("body > div.nav"));
// Thread.sleep(3000);
// driver.quit();
}
/*
检查登录功能
*/
// 成功登录
public void LoginSuc() throws InterruptedException, IOException {
getScreenShot(getClass().getName());
// 登录成功测试前可以先 刷新页面 或者 清除一下输入框, 确保输入框中没有文本
// 方法一: 通过 clear 保证输入框没有文本
// driver.findElement(By.cssSelector("username")).clear();
// driver.findElement(By.cssSelector("password")).clear();
// 方法二: 通过界面刷新操作清除输入框文本
driver.navigate().refresh();
driver.findElement(By.cssSelector("#username")).sendKeys("lisi");
driver.findElement(By.cssSelector("#password")).sendKeys("123");
driver.findElement(By.cssSelector("#submit")).click();
// 加一个等待
Thread.sleep(1000);
//有弹窗先解决弹窗
Alert alert = driver.switchTo().alert();
alert.accept();
// 程序执行过快, 导致报错, 加一个显式等待 (是处理弹窗前需要等待, 所以这行代码先不用)
// WebDriverWait off = new WebDriverWait(driver, Duration.ofSeconds(3));
// off.until(ExpectedConditions.elementToBeClickable(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-friend")));
// 通过新页面的图标来检查点击登录之后是否登录成功
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-session"));
// 通过新页面的标题来再次检查点击登录之后是否登录成功
String expect = driver.getTitle();
// 通过断言功能来检查
assert expect.equals("网页聊天程序");
getScreenShot(getClass().getName());
// 回退
driver. Navigate().back();
// 回退之后就刷新一下页面
driver. Navigate().refresh();
}
// 异常登录(账号为空)
public void LoginFail1() throws InterruptedException, IOException {
// 清除输入框中原有的内容
// 方法一: 通过 clear 保证输入框没有文本
// driver.findElement(By.cssSelector("username")).clear();
// driver.findElement(By.cssSelector("password")).clear();
// 方法二: 通过界面刷新操作清除输入框文本
// driver.navigate().refresh();
driver.findElement(By.cssSelector("#username")).sendKeys("");
driver.findElement(By.cssSelector("#password")).sendKeys("123");
driver.findElement(By.cssSelector("#submit")).click();
// 加一个等待
Thread.sleep(1000);
//有弹窗先解决弹窗
Alert alert = driver.switchTo().alert();
alert. Accept();
// 弹窗解决后再判断是否登录成功, 若登录失败, 则表示还在登录界面
String u = driver.getCurrentUrl();
assert u.equals("http://127.0.0.1:8080/login.html");
// 页面刷新一下, 确保输入框没有文本
driver.navigate().refresh();
// driver.quit();
}
// 异常登录(密码为空)
public void LoginFail2() throws InterruptedException, IOException {
driver.findElement(By.cssSelector("#username")).sendKeys("lisi");
driver.findElement(By.cssSelector("#password")).sendKeys("");
driver.findElement(By.cssSelector("#submit")).click();
// 加一个等待
Thread.sleep(1000);
//有弹窗先解决弹窗
Alert alert = driver.switchTo().alert();
alert.accept();
// 弹窗解决后再判断是否登录成功, 若登录失败, 则表示还在登录界面
String u = driver.getCurrentUrl();
assert u.equals("http://127.0.0.1:8080/login.html");
// 页面刷新一下, 确保输入框没有文本
driver.navigate().refresh();
// driver.quit();
}
// 异常登录(账号错误)
public void LoginFail3() throws InterruptedException, IOException {
driver.findElement(By.cssSelector("#username")).sendKeys("lisizi");
driver.findElement(By.cssSelector("#password")).sendKeys("123");
driver.findElement(By.cssSelector("#submit")).click();
// 加一个等待
Thread.sleep(1000);
//有弹窗先解决弹窗
Alert alert = driver.switchTo().alert();
alert.accept();
// 弹窗解决后再判断是否登录成功, 若登录失败, 则表示还在登录界面
String u = driver.getCurrentUrl();
assert u.equals("http://127.0.0.1:8080/login.html");
// 页面刷新一下, 确保输入框没有文本
driver.navigate().refresh();
// driver.quit();
}
// 异常登录(密码错误)
public void LoginFail4() throws InterruptedException, IOException {
driver.findElement(By.cssSelector("#username")).sendKeys("lisi");
driver.findElement(By.cssSelector("#password")).sendKeys("1234");
driver.findElement(By.cssSelector("#submit")).click();
// 加一个等待
Thread.sleep(1000);
//有弹窗先解决弹窗
Alert alert = driver.switchTo().alert();
alert.accept();
// 弹窗解决后再判断是否登录成功, 若登录失败, 则表示还在登录界面
String u = driver.getCurrentUrl();
assert u.equals("http://127.0.0.1:8080/login.html");
// 页面刷新一下, 确保输入框没有文本
driver.navigate().refresh();
// driver.quit();
//
driver.navigate().back();
driver.navigate().refresh();
}
}
tests/ListPage.java
public class ListPage extends Untils {
private static String url = "http://127.0.0.1:8080/login.html";
public ListPage() {
super(url);
}
/*
未登录状态下 --- 访问列表页
由 PageByNoLogin类 进行测试
*/
/*
登录状态下 --- 访问主页面
*/
public static String username = null;
public static String se1 = null;
public static String se2 = null;
public void ListLogin() throws InterruptedException {
// Thread.sleep(1000);
// 重新返回并清空登录页面进行登录
driver.navigate().refresh();
// 登录
driver.findElement(By.cssSelector("#username")).sendKeys("lisi");
username = driver.findElement(By.cssSelector("#username")).getText();
driver.findElement(By.cssSelector("#password")).sendKeys("123");
driver.findElement(By.cssSelector("#submit")).click();
// 为了能等到弹窗出现,加一个等待
Thread.sleep(1000);
// 有弹窗先解决弹窗
Alert alert = driver.switchTo().alert();
alert.accept();
// 通过查看页面元素是否存在来检查页面加载成功与否
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-session"));
se1 =driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-session")).getText();
}
/*
检查个人信息是否正确
*/
public void PersonalInformation() {
// 找到登录用户名
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.user"));
// 用断言来比较这个用户名和登录的用户名是否一致
assert se1.equals(username);
}
/*
检查搜索框
*/
public void SearchBox() throws InterruptedException {
// 检查是否可以正常输入
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.search > input[type=text]")).sendKeys("zhangsan");
// 点击搜索按钮
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.search > button"));
// 这里按钮虽然可以点击,但是做不到搜索功能
}
/*
检查聊天内容预览
因为这个消息是动态的,所以只能测试一次,一次过后就要改 test2
*/
public void ChatPage() throws InterruptedException {
// 程序执行过快,网站内容还没加载完全,加一个显式等待
WebDriverWait off = new WebDriverWait(driver, Duration.ofSeconds(20));
off.until(ExpectedConditions.textToBe (By.cssSelector("#session-list > li:nth-child(2) > h3"),("zhangsan")));
// 查询到主页预览中的聊天内容
String test1 = driver.findElement(By.cssSelector("#session-list > li.selected > p")).getText();
// 点击对应用户并查询到聊天界面中的聊天内容
driver.findElement(By.cssSelector("#session-list > li:nth-child(2)")).click();
String test2 = driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.message-show > div:nth-child(14) > div > p")).getText();
// 使用断言判断预览功能是否成功
assert test1.equals(test2);
}
/*
给其他用户发送消息
*/
public void SendMessage() {
// 程序执行过快,网站内容还没加载完全,加一个显式等待
WebDriverWait off = new WebDriverWait(driver, Duration.ofSeconds(20));
off.until(ExpectedConditions.textToBe (By.cssSelector("#session-list > li:nth-child(2) > h3"),("zhangsan")));
// 选择一个用户并点击进入消息发送界面
driver.findElement(By.cssSelector("#session-list > li:nth-child(2)")).click();
// 找到输入框, 并输入想要发送的内容(空)
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > textarea")).sendKeys("");
// 点击发送按钮,发送消息
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.ctrl > button")).click();
// 找到输入框, 并输入想要发送的内容(仅文字)
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > textarea")).sendKeys("你好呀!");
se2 = driver.findElement(By.cssSelector("#session-list > li.selected > p")).getText();
// 点击发送按钮,发送消息
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.ctrl > button")).click();
// 找到输入框, 并输入想要发送的内容 (文字 + 其他内容)
// driver.findElement(By.cssSelector("body > div.client-container > div > div.right > textarea")).sendKeys("你好呀!35465466654^&%^%$^%$&^*&%^#$%&%*&$^%#^%#^%&^*&^&");
// 点击发送按钮,发送消息
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.ctrl > button")).click();
}
/*
检查接收消息
*/
public void ReceiveMessage() throws InterruptedException {
// 需要登录另一个接收账号来测试
// 首先回退,刷新重新登录
driver.navigate().back();
driver.navigate().refresh();
// 登录
driver.findElement(By.cssSelector("#username")).sendKeys("zhangsan");
username = driver.findElement(By.cssSelector("#username")).getText();
driver.findElement(By.cssSelector("#password")).sendKeys("123");
driver.findElement(By.cssSelector("#submit")).click();
// 为了能等到弹窗出现,加一个等待
Thread.sleep(2000);
// 有弹窗先解决弹窗
Alert alert = driver.switchTo().alert();
alert.accept();
// 通过查看页面元素是否存在来检查页面加载成功与否
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-session"));
// 进行收发件验证
// 程序执行过快,网站内容还没加载完全,加一个显式等待
WebDriverWait off = new WebDriverWait(driver, Duration.ofSeconds(25));
off.until(ExpectedConditions.textToBe (By.cssSelector("#session-list > li:nth-child(1) > h3"),("zhaoliu")));
// 找到发件人昵称,点击进去
driver.findElement(By.cssSelector("#session-list > li:nth-child(3)")).click();
// 用断言检查发件人发送的内容是否接收到了
String ele = driver.findElement(By.cssSelector("#session-list > li.selected > p")).getText();
// System.out.println(ele+"1");
// System.out.println(se2+"2");
assert se2.equals(ele);
}
/*
检查好友列表页
*/
public void FriendsList() {
// 找到好友图标并点击,通过查看好友列表的好友昵称判断是否成功跳转
driver.findElement(By.cssSelector("body > div.client-container > div > div.left > div.tab > div.tab-friend")).click();
driver.findElement(By.cssSelector("#friend-list > li:nth-child(1) > h4"));
// 点击好友,跳转到聊天界面
driver.findElement(By.cssSelector("#friend-list > li:nth-child(1) > h4")).click();
driver.findElement(By.cssSelector("body > div.client-container > div > div.right > div.title"));
}
}
tests/PageByNoLogin.java
/*
测试未登录的用例
*/
public class PageByNoLogin extends Untils {
public static String url = "http://127.0.0.1:8080/client.html";
public PageByNoLogin() {
super(url);
}
public void ListPageByNoLogin() throws IOException, InterruptedException {
// 保证未登录状态
Thread.sleep(1000);
// 主页未登录处理
// 处理弹窗
Alert alert = driver.switchTo().alert();
alert.accept();
// 跳转到登录页面
String expect = driver.getTitle();
getScreenShot(getClass().getName());
assert expect.equals("登录页面");
// driver.quit();
}
}
RunTests.java
public class RunTests {
public static void main(String[] args) throws InterruptedException, IOException {
LoginPage login = new LoginPage();
login.loginPageRight();
login.LoginSuc();
login.LoginFail1();
login.LoginFail2();
login.LoginFail3();
login.LoginFail4();
PageByNoLogin noLogin = new PageByNoLogin();
noLogin.ListPageByNoLogin();
ListPage list = new ListPage();
list.ListLogin();
list.PersonalInformation();
list.SearchBox();
list.ChatPage();
list.SendMessage();
list.ReceiveMessage();
list.FriendsList();
Thread.sleep(1000);
driver.quit();
}
}
2. 自动化功能测试总结
2.1 弹窗的解决相关问题
// 有弹窗先处理弹窗, 弹窗未处理之前不能对页面元素进行操作
// 在执行登录测试的程序时, 报了以下错误
// 我就觉得是在解决弹窗时出了点问题, 调试了几遍发现是程序执行过快导致弹窗没有被检测到
// 所以我就个加了等待, 再次尝试运行就没有弹窗错误了
2.2 断言的使用和说明
// 断言语法: assert 变量1.equals(变量2);
// 判断是否相同的情况可以多使用断言
// 要想在 idea 中使用断言, 需要先按照以下步骤进行配置
2.3 重新登录问题
// 成功登录测试完之后, 我们需要测试登录失败的用例时, 就需要重新登录, 这时候就要用到 回退(driver.navigate().back();) 操作, 但仅仅回退还不行, 因为在之前登录的时候, 用户名和密码的输入框中已经输入了内容, 我们如果直接进行测试的话, 会在原基础上拼接, 所以我们需要先将输入框中的内容清空才能继续进行测试, 这里我们可以用两种方法, 一种是使用 clear 语句, 第二种是 使用 刷新 (driver.navigate().refresh();) 操作
// 为了防止我们的测试代码因执行顺序发生变化导致报错, 每次登录不管是否成功, 我们都可以 back 并 refresh 一下, 这样不论我们是先测试成功用例还是失败用例, 到最后都可以实现
项目性能(接口)测试
// 使用 JMeter 进行性能测试
// 可以和 Postman 配合使用
1. 进行性能测试
2.生成的性能测试报告