目录
项目背景
项目功能
自动化测试
总结
项目背景
随着互联网的发展,链接(URL)变得越来越长且复杂,这不仅影响用户体验,还可能由于字符限制导致在某些平台或应用中无法完整显示。为了解决这一问题,我们推出了“简洁链接”项目,旨在为用户提供一种快速、简便的方式来缩短和美化他们的URL。
项目目标:
- 提供简洁的URL服务: 为用户提供简短的、易于分享和记忆的URL,优化在线体验。
- 确保链接安全: 通过多种技术手段确保短链接的跳转安全,防止恶意跳转和钓鱼网站。
- 优化性能: 确保短链接的生成和跳转过程快速、稳定。
- 提供数据分析: 为用户提供短链接的点击量、来源等数据分析,帮助他们更好地了解用户行为和市场趋势。
项目功能:
- 短链接生成: 用户可以将长URL转换为简短的自定义链接。
- 链接跳转: 用户点击短链接后,将被安全、快速地重定向到原始链接。
- 链接管理: 用户可以管理他们的短链接,包括查看统计、编辑和删除链接。
- API接口: 提供API接口,方便第三方开发者集成短链接功能。
技术栈:
SpringCloudAlibaba + MySQL + Redis + RocketMQ + ShardingJDBC
项目演示
项目测试用例
自动化测试
自动化工具类
package com.sfx.shortLink;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.time.Duration;
public class DriverUtils {
private static ChromeDriver driver;
public static ChromeDriver createDriver() {
if(driver == null) {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
}
return driver;
}
}
登陆测试
package com.sfx.shortLink;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import java.time.Duration;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ShortLinkLoginTest {
private static ChromeDriver driver;
/**
* 在所有的测试用例执行之前,先要创建驱动
*/
@BeforeAll
static void createAndGetDriver() {
driver = DriverUtils.createDriver();
driver.get("http://localhost:5173/");
}
public void userNameAndPasClear() {
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input")).clear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input")).clear();
}
@Order(2)
@ParameterizedTest
@CsvSource({"sfx3214,123456789","dyrrrwww,123456789"})
public void testLoginSuccess(String username , String password) {
// /html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input
// /html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input
// /html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input
// 输入正确的用户名和密码
userNameAndPasClear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input")).sendKeys(username);
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input")).sendKeys(password);
driver.findElement(By.xpath("//*[@id=\"app\"]/div[1]/div[1]/div[1]/form/div[2]/div[2]/button/span")).click();
String exceptedTest = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[1]/span")).getText();
Assertions.assertEquals(exceptedTest,"创建短链");
// /html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[2]/span
exceptedTest = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[2]/span")).getText();
Assertions.assertEquals(exceptedTest,"批量创建");
driver.navigate().back();
}
@Test
@Order(1)
public void testLoginFail(String username,String password) {
// 账户名和密码都为空
userNameAndPasClear();
driver.findElement(By.xpath("//*[@id=\"app\"]/div[1]/div[1]/div[1]/form/div[2]/div[2]/button/span")).click();
String text = driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[1]/h2")).getText();
Assertions.assertEquals(text,"用户登录");
// 账户为空,密码不为空
userNameAndPasClear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input")).sendKeys("123456789");
Assertions.assertEquals(text,"用户登录");
// 账户不为空,密码为空
userNameAndPasClear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input")).sendKeys("sfx3214");
Assertions.assertEquals(text,"用户登录");
// 账户都不为空,密码不为空
userNameAndPasClear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input")).sendKeys("svrfdffed");
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input")).sendKeys("1234eadfvefdwf56789");
Assertions.assertEquals(text,"用户登录");
// 密码小于8位
userNameAndPasClear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input")).sendKeys("svrfdffed");
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input")).sendKeys("1");
Assertions.assertEquals(text,"用户登录");
}
@AfterAll
static void after() {
driver.quit();
}
}
注册测试
package com.sfx.shortLink;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
public class ShortLinkRegisterTest {
private static ChromeDriver driver;
/**
* 在所有的测试用例执行之前,先要创建驱动
*/
@BeforeAll
static void createDriver() {
driver = DriverUtils.createDriver();
driver.get("http://localhost:5173/");
}
public void clear() {
// 输入用户名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[1]/div/div/div[2]/input")).clear();
// 输入邮箱
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[2]/div/div/div[2]/input")).clear();
// 输入手机号
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[3]/div/div/div[2]/input")).clear();
// 输入姓名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[4]/div/div/div[2]/input")).clear();
// 输入密码
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[5]/div/div/div[2]/input")).clear();
}
@Test
public void testRegisterSuccess() {
clear();
// 点击去注册
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[3]/button/span")).click();
// 输入用户名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[1]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入邮箱
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[2]/div/div/div[2]/input")).sendKeys("89@qq.com");
// 输入手机号
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[3]/div/div/div[2]/input")).sendKeys("13965896936");
// 输入姓名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[4]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入密码
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[5]/div/div/div[2]/input")).sendKeys("123456789");
// 点击注册
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[6]/div[2]/button/span")).click();
String exceptedTest = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[1]/span")).getText();
Assertions.assertEquals(exceptedTest,"创建短链");
// /html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[2]/span
exceptedTest = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[2]/span")).getText();
Assertions.assertEquals(exceptedTest,"批量创建");
}
@Test
public void testRegisterFail() {
//未输入任何一个
// 点击去注册
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[3]/button/span")).click();
clear();
// 点击注册
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[6]/div[2]/button/span")).click();
String text = driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/h2")).getText();
Assertions.assertEquals(text,"用户注册");
clear();
//不符合手机号格式
// 输入用户名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[1]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入邮箱
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[2]/div/div/div[2]/input")).sendKeys("89@qq.com");
// 输入手机号
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[3]/div/div/div[2]/input")).sendKeys("1568989");
// 输入姓名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[4]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入密码
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[5]/div/div/div[2]/input")).sendKeys("123456789");
// 点击注册
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[6]/div[2]/button/span")).click();
text = driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/h2")).getText();
Assertions.assertEquals(text,"用户注册");
//不符合邮箱格式
clear();
// 输入用户名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[1]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入邮箱
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[2]/div/div/div[2]/input")).sendKeys("89.com");
// 输入手机号
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[3]/div/div/div[2]/input")).sendKeys("13846789696");
// 输入姓名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[4]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入密码
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[5]/div/div/div[2]/input")).sendKeys("123456789");
// 点击注册
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[6]/div[2]/button/span")).click();
text = driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/h2")).getText();
Assertions.assertEquals(text,"用户注册");
//密码长度小于8位
// 输入用户名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[1]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入邮箱
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[2]/div/div/div[2]/input")).sendKeys("89@qq.com");
// 输入手机号
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[3]/div/div/div[2]/input")).sendKeys("13965896936");
// 输入姓名
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[4]/div/div/div[2]/input")).sendKeys("dyrrrwww");
// 输入密码
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[5]/div/div/div[2]/input")).sendKeys("111");
// 点击注册
driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/form/div[6]/div[2]/button/span")).click();
text = driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/h2")).getText();
Assertions.assertEquals(text,"用户注册");
}
@AfterAll
static void after() {
driver.quit();
}
}
短链接测试
package com.sfx.shortLink;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class ShortLinkProjectTest {
private static ChromeDriver driver;
@BeforeAll
static void createDriver() {
driver = DriverUtils.createDriver();
driver.get("http://localhost:5173/");
loginSuccess();
}
public static void userNameAndPasClear() {
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input")).clear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input")).clear();
}
public static void loginSuccess() {
// 登陆
userNameAndPasClear();
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[1]/div/div/div[2]/input")).sendKeys("sfx3214");
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[1]/form/div[1]/div[2]/div/div/div[2]/input")).sendKeys("123456789");
driver.findElement(By.xpath("//*[@id=\"app\"]/div[1]/div[1]/div[1]/form/div[2]/div[2]/button/span")).click();
String exceptedTest = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[1]/span")).getText();
Assertions.assertEquals(exceptedTest, "创建短链");
// /html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[2]/span
exceptedTest = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[2]/span")).getText();
Assertions.assertEquals(exceptedTest, "批量创建");
}
@Test
public void createShortLink() {
// 点击创建短链
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[1]/span")).click();
// 输入正确的短链,创建成功
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[6]/div/div/div/div/div[2]/div[1]/div/form/div[1]/div/div/div/input")).sendKeys("https://xiaolincoding.com/");
// 点击描述信息,自动输入描述信息
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[6]/div/div/div/div/div[2]/div[1]/div/form/div[2]/div/div/textarea")).click();
// 点击确认创建短连接诶
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[6]/div/div/div/div/div[2]/div[1]/div/form/div[5]/div/div/button[1]/span")).click();
}
@Test
public void creatFail() {
// 没有输入短链,点击确认,创建失败
// 点击创建短链
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[1]/div/button[1]/span")).click();
// 输入正确的短链,创建成功
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[6]/div/div/div/div/div[2]/div[1]/div/form/div[1]/div/div/div/input")).sendKeys("");
// 点击描述信息,自动输入描述信息
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[6]/div/div/div/div/div[2]/div[1]/div/form/div[2]/div/div/textarea")).click();
// 点击确认创建短连接诶
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[6]/div/div/div/div/div[2]/div[1]/div/form/div[5]/div/div/button[1]/span")).click();
}
@Test
public void restoreShortLink() {
// /html/body/div[1]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[3]/div/div/a/span
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[3]/div/div/a/span")).click();
String exceptedTest = driver.getCurrentUrl();
Assertions.assertNotEquals(exceptedTest, "https://xiaolincoding.com/");
}
@Test
public void updateShortLink() {
// /*[name()='svg']/*[name()='use']
// /html/body/div[1]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[8]/div/div/i[2]/svg
// //*[@id="app"]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[8]/div/div/i[2]//*[name()='svg']/*[name()='path']
// //*[@id="app"]/*[name()='svg']/*[name()='path']
driver.findElement(By.xpath("//*[@id=\"app\"]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[8]/div/div/i[2]//*[name()='svg']")).click();
WebElement element = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[7]/div/div/div/div/form/div[2]/div/div/textarea"));
element.clear();
element.sendKeys("i love you");
// 点击确认
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[7]/div/div/div/div/form/div[5]/div/div/button[1]/span")).click();
}
@Test
public void recycle() {
driver.findElement(By.xpath("//*[@id=\"app\"]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[8]/div/div/i[3]//*[name()='svg']")).click();
driver.findElement(By.xpath("/html/body/div[2]/div[9]/div/div[2]/button[2]")).click();
// 点击回收站
driver.findElement(By.xpath("//*[@id=\"app\"]/div/section/main/div/div/div[1]/div[2]/div")).click();
String text = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[2]/td[3]/div/div/a/span")).getText();
Assertions.assertEquals(text, "http://nurl.ink:8001/2CQufK");
// 回收站移除
driver.findElement(By.xpath("//*[@id=\"app\"]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[2]/td[8]/div/div/i[2]//*[name()='svg']")).click();
// 回到默认分组
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[1]/ul/li/div")).click();
// 验证
String text1 = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[3]/div/div/a/span")).getText();
System.out.println(text1);
}
@Test
public void shortLinkGroup() {
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[1]/div[1]/div[2]/img")).click();
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[4]/div/div/div/form/div/div/div/div/input")).sendKeys("新的分组");
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[4]/div/div/footer/span/button[2]")).click();
WebElement element = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[1]/ul/li[2]/div"));
System.out.println(element.getText());
Assertions.assertEquals(element.getText(), "新的分组\n" +
"0");
}
@Test
public void shortLinkStats() {
// 点击短链接统计按钮能够正常查看统计内容
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[2]/div/div[2]/div[1]/div[3]/div/div[1]/div/table/tbody/tr[1]/td[8]/div/div/i[1]//*[name()='svg']")).click();
WebElement element = driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[3]/div/div/div/div[2]/div[1]/div/div/div/div[2]"));
Assertions.assertTrue(element.getText() != null);
//跳转短链接后,统计的值与原先的有变化
//能否正常的从曲线切换到直方图
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[3]/div/div/div/div[2]/div[2]/div[1]/div/div[1]/div[1]/div/button")).click();
//能否查看访问记录
driver.findElement(By.xpath("/html/body/div[1]/div/section/main/div/div/div[3]/div/div/div/div[2]/div[1]/div/div/div/div[3]")).click();
}
@AfterAll
static void after() {
driver.quit();
}
}
测试套件
package com.sfx.shortLink;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
/**
* 套件类
*/
@Suite
@SelectClasses({ShortLinkLoginTest.class,ShortLinkProjectTest.class,ShortLinkRegisterTest.class})
public class TestSuite {
}
总结
以上便是本次短链接系统的测试报告~