在线音乐播放器测试报告
文章目录
- [1. 项目背景](#1. 项目背景)
- [2. 项目简介](#2. 项目简介)
-
-
- 2.1登录页面
- [2.2 主页面](#2.2 主页面)
- [2.3 收藏页面](#2.3 收藏页面)
- [2.4 上传音乐页面](#2.4 上传音乐页面)
- [2.5 注册页面](#2.5 注册页面)
-
- [3. 需求评测](#3. 需求评测)
- [4. 制定测试计划](#4. 制定测试计划)
- [5. 设计测试用例](#5. 设计测试用例)
-
- [5.1 注册](#5.1 注册)
- [5.2 登录](#5.2 登录)
- [5.3 主页面](#5.3 主页面)
- [5.4 收藏页面](#5.4 收藏页面)
- [5.5 添加歌曲](#5.5 添加歌曲)
- [6. 执行测试用例](#6. 执行测试用例)
-
- [6.1 注册](#6.1 注册)
- [6.2 登录](#6.2 登录)
- [6.2 主页面](#6.2 主页面)
- [6.3 收藏页面](#6.3 收藏页面)
1. 项目背景
在线音乐播放器是一个简单的个人项目,主要通过项目来学习 spring boot , mybatis,spring AOP 等框架,以及测试流程
2. 项目简介
项目主要功能: 登录,注册,上传音乐,播放音乐,收藏音乐,搜索音乐,批量删除音乐等.
2.1登录页面
业务描述: 管理员用户需要通过登录页面进入在线音乐播放器系统,登录页面是进入系统的唯一页面
需求描述: 管理员需要输入用户名,密码才能登该系统.
行为人: 管理员
UI 界面:
业务规则:
- 用户名长度 1-8 区分大小写但不含特殊字符.
- 用户密码长度为 6 - 15 且不含特殊字符 当用户输入完用户名和用户密码点击登录才能进入系统.
2.2 主页面
业务描述: 登录系统后,管理员可以上传音乐,播放音乐,对上传后的音乐点击喜欢加入收藏,可以删除已上传的音乐,还可以通过搜索框对 音乐进行搜索. 除了但个删除单个收藏外,还支持 批量删除音乐和收藏音乐.
需求描述:
上传音乐 : 用户点击添加歌曲按钮后,跳转到上传歌曲页面.
播放音乐 : 用户选中歌曲后,点击播放音乐,网站通过读取服务器本地音乐文件进行播放.
添加喜欢: 用户选中歌曲后,点击喜欢按钮,歌曲被收藏然后跳转到收藏页面.
删除音乐: 用户选中歌曲后,点击删除按钮,歌曲被删除,如果歌曲再用户的收藏列表,歌曲一同被删除.
搜索音乐: 用户可以在搜索框输入歌曲名(可以不完整,支持模糊查询)然后点击查询 ,页面出现需要搜索的歌曲.
批量删除/喜欢: 用户对多首歌曲点击删除或喜欢,歌曲被删除或被添加至喜欢列表.
行为人: 管理员
UI 界面:
业务规则:
- 主页面的按钮点击后能供切换颜色,让用户感觉出按钮被点击.
- 用户为在输入框输入歌曲名点击查询将数据库中的歌曲全部查出放到页面
- 用户在输入框输入歌曲名应支持模糊查询 比如 输入 白,页面应将 歌曲含 白 的歌曲 都查出来并放到页面上.
2.3 收藏页面
业务描述: 在主页面点击喜欢列表后跳转至收藏页面,在收藏页面可以对收藏的音乐进行播放,删除,批量删除,搜索音乐.
需求描述:
播放音乐 : 用户选中歌曲后,点击播放音乐,网站通过读取服务器本地音乐文件进行播放.
删除音乐: 用户选中歌曲后,点击删除按钮,歌曲被删除,如果歌曲再用户的收藏列表,歌曲一同被删除.
搜索音乐: 用户可以在搜索框输入歌曲名(可以不完整,支持模糊查询)然后点击查询 ,页面出现需要搜索的歌曲.
批量删除: 用户对多首歌曲点击删除,歌曲被删除
行为人: 管理员
UI 界面:
业务规则:
- 主页面的按钮点击后能供切换颜色,让用户感觉出按钮被点击.
- 用户为在输入框输入歌曲名,点击查询将当前用户喜欢的音乐全部展示.
- 用户在输入框输入歌曲名应支持模糊查询 比如 输入 白,在当前用户收藏的音乐进行搜索,如果没有找到表格置空
2.4 上传音乐页面
业务描述: 用户在主页面点击添加歌曲跳转到上传音乐页面,在上传音乐页面,点击选择文件可以从本地上传 mp3 文件, 输入完歌手名后点即上传按钮完成音乐上传.
需求描述: 用户点击上传文件,从本地选中 mp3 文件后,在输入完歌手名后,点击上传按钮,对文件进行上传.
行为人: 管理员
UI 界面:
业务规则: 用户上传重复文件后,系统报错,提示文件已上传.
2.5 注册页面
业务描述: 用于注册用户
需求描述 : 用户 进入 注册页面后,输入用户名和密码,再次确认密码后,点击确定完成注册.
行为人: 用户
UI 界面:
业务规则:
- 用户名区分大小写但不含特殊字符
- 用户密码长度为 6 - 15且不含特殊字符, 当用户输入完用户名 , 密码和确认密码后才能点击按钮进行注册
3. 需求评测
4. 制定测试计划
目的 : 对在线音乐播放器进行测试.
测试内容:
模块名称 | 测试点 | 优先级 | 说明 |
---|---|---|---|
用户模块 | 注册 | 高 | 功能测试 |
用户模块 | 登录 | 高 | 并发性测试 |
主模块 | 上传音乐 | 高 | 功能测试 |
主模块 | 播放音乐 | 高 | 功能测试 |
主模块 | 收藏音乐 | 高 | 功能测试 |
主模块 | 搜索音乐 | 高 | 功能测试 |
主模块 | 删除音乐 | 高 | 功能测试 |
主模块 | 批量删除/喜欢音乐 | 中 | 功能测试 |
收藏模块 | 播放音乐 | 高 | 功能测试 |
收藏模块 | 取消收藏 | 高 | 功能测试 |
收藏模块 | 搜索音乐 | 高 | 功能测试 |
收藏模块 | 批量取消收藏 | 高 | 功能测试 |
上传模块 | 上传音乐 | 高 | 功能测试 |
上传模块 | 上传大额文件 | 高 | 性能测试 |
测试环境 :
- Windows
- 浏览器
Chrome
版本: 125.0.6422.142(正式版本) (64 位)
测试方法: 黑盒测试
测试工具: ApiPost , Selenium , Junit
测试人员 : 牧..
5. 设计测试用例
5.1 注册
用户名 : 用户名长度 1-8 区分大小写但不含特殊字符.
密码: 用户密码长度为 6 - 15, 当用户输入完用户名和用户密码点击登录才能进入系统
划分等价类
输入条件 | 有效等价类 | 无效等价类 |
---|---|---|
用户名 | 不含特殊字符且长度在 1-8 之间 | 空白字符串 |
用户名 | 含有特殊字符 | |
用户名 | 长度大于 8 | |
密码 | 不含特殊字符 长度在 6 - 15 之间 | 空白字符串 |
密码 | 含有特殊字符 | |
密码 | 长度大于8 |
边界值
用户名 | 密码 |
---|---|
用户名长度: 0,1,2,7,8,9 | 密码长度:5,6,7,14,15,16 |
测试用例
方案 | 用户名 | 密码 | 确认密码 | 注册 | 预期 | 说明 |
---|---|---|---|---|---|---|
1 | abc | 123456 | 123456 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符且大于1小于8 密码和确认密码相同,密码长度大于 6 小于 15 |
2 | 123456 | 123456 | 无效 | 注册失败,弹出提框用户名不能为空 | 用户名长度小于1 | |
3 | a | 123456 | 123456 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符,用户名长度正好达到最低要求 密码和确认密码相同,密码长度大于 6 小于 15 |
4 | ab | 123456 | 123456 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符, 用户名长度 大于 1 小于 8 密码和确认密码相同,密码长度大于 6 小于 15 |
5 | abc1234 | 123456 | 123456 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符, 用户名长度 大于 1 小于 8 密码和确认密码相同,密码长度大于 6 小于 15 |
6 | abc12345 | 123456 | 123456 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符, 用户名长度 大于 1 小于 8 密码和确认密码相同,密码长度大于 6 小于 15 |
7 | abc123456 | 123456 | 123456 | 无效 | 注册失败,弹出提示用户名长度大于8 | 用户名长度大于8 |
8 | abc""\ | 123456 | 123456 | 无效 | 注册失败,弹出提示用户名含有特殊字符 | 用户名含有特殊字符 " / |
9 | abc | 12345 | 12345 | 无效 | 注册失败,弹出提示密码长度小于6 | 密码长度小于6 |
10 | abc | 1234567 | 1234567 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符, 用户名长度 大于 1 小于 8 密码和确认密码相同,密码长度大于 6 小于 15 |
11 | abc | 12345671234567 | 12345671234567 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符, 用户名长度 大于 1 小于 8 密码和确认密码相同,密码长度大于 6 小于 15 |
12 | abc | 123456712345671 | 123456712345671 | 有效 | 注册成功,跳蛛至登录页面 | 用户名不含特殊字符, 用户名长度 大于 1 小于 8 密码和确认密码相同,密码长度大于 6 小于 15 |
13 | abc | 1234567123456712 | 1234567123456712 | 无效 | 注册失败,弹出提示密码长度大于15 | 密码长度大于15 |
14 | abc | 123456 | 无效 | 注册失败,弹出提示框,密码不能为空 | 密码长度小于6 | |
15 | abc | 123456 | 无效 | 注册失败,弹出提示框,提示再次输入密码 | 确认密码为空 |
5.2 登录
测试用例
方案 | 用户 | 密码 | 登录 | 预期 | 说明 |
---|---|---|---|---|---|
16 | 输入已注册的用户名: abc | 123456 | 有效 | 登录成功跳转至主页面 | 用户和密码已经保存在数据库 |
17 | 输入未注册的用户名: abcd | 123456 | 无效 | 登录失败,弹出提示框提示用户未注册 | 用户未注册 (数据库查询不到) |
18 | 输入含有特殊字符的用户名 | 123456 | 无效 | 登录失败,弹出提示框提示用户名含有特殊字符 | 用户名含有特殊字符 |
19 | 输入已注册的用户名: abc | 12345 | 无效 | 登录失败,弹出提示框提示密码长度小于6 | 密码长度小于6 |
20 | 输入已注册的用户名: abc | 1234567 (错误密码) | 无效 | 登录失败,弹出提示框用户或密码错误 | 密码错误 |
21 | 输入已注册的用户名: abc | 1234567123456712 | 无效 | 登录失败,弹出提示框密码长度大于15 | 密码长度大于15 |
5.3 主页面
方案 | 功能 | 操作步骤 | 预期结果 |
---|---|---|---|
22 | 播放音乐 | 选中哆啦A梦的播放音乐按钮点击 | 音乐播放成功 |
23 | 收藏歌曲 | 选中需要收藏的歌曲点击喜欢按钮 | 音乐被收藏,然后跳转至收藏页面 |
24 | 收藏歌曲 | 选中用户已收藏的歌曲点击喜欢按钮 | 弹出提示框歌曲已收藏 |
25 | 删除音乐 | 选中要删除的歌曲点击删除按钮 | 歌曲删除 |
26 | 批量删除音乐 | 选中需要删除的歌曲点击删除按钮 | 歌曲删除 |
27 | 校验登录 | 未登录用户通过 URL 直接进入页面 | 弹出提示框提示用户登录然后页面跳转至登录页面 |
28 | 查找音乐 | 用户在输入框输入完整歌曲名 如 哆啦A梦 | 页面展示出有关哆啦A梦的歌曲 |
29 | 查找音乐 | 用户在输入框输入 部分歌曲名称 如 哆 | 页面展示出有关 哆 的歌曲 |
30 | 跳转功能 | 用户点击添加歌曲或喜欢列表按钮 | 页面跳转至上传文件页面或收藏页面 |
5.4 收藏页面
方案 | 功能 | 操作步骤 | 预期结果 |
---|---|---|---|
31 | 播放音乐 | 选中哆啦A梦的播放音乐按钮点击 | 音乐播放成功 |
32 | 取消收藏 | 选中要取消收藏的歌曲点击删除按钮 | 歌曲删除 |
33 | 校验登录 | 未登录用户通过 URL 直接进入页面 | 弹出提示框提示用户登录然后页面跳转至登录页面 |
34 | 查找音乐 | 用户在输入框输入完整歌曲名 如 哆啦A梦 | 页面展示出有关哆啦A梦的歌曲 |
35 | 查找音乐 | 用户在输入框输入 部分歌曲名称 如 哆 | 页面展示出有关 哆 的歌曲 |
36 | 跳转功能 | 用户点击回到首页按钮 | 页面跳转至主页面 |
5.5 添加歌曲
方案 | 功能 | 操作步骤 | 预期结果 |
---|---|---|---|
37 | 上传歌曲 | 点击选中文件,在本地选中要上出的 mp3 文件 然后输入歌手名点击上传 | 弹出提示框文件上传成功,页面跳转至主页面 |
6. 执行测试用例
搭建自动化测试环境: jdk8 + selenium + junit
创建 maven 项目 导入相关依赖:
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>csdn_test_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- selenium 相关依赖-->
<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>
<!-- Junit 相关依赖-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-reporting</artifactId>
<version>1.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
创建 Constants,创建常量存储 url :
java
package constants;
public class Constants {
// public static final String LOGIN_URL = "https://www.csdn.net/";
public static final String ALL_REQUEST = "--remote-allow-origins=*";
public static final String MY_LOGIN_URL = "http://127.0.0.1:8080/login.html";
public static final String MY_INDEX_URL = "http://127.0.0.1:8080/list.html";
public static final String MY_REGISTER_URL = "http://127.0.0.1:8080/register.html";
public static final String MY_LOVEMUSIC_URL = "http://127.0.0.1:8080/loveMusic.html";
public static final String MY_UPLOADMUSICFILE_URL = "http://127.0.0.1:8080/upload.html";
public static final String MY_FILE_UPLOAD_PATH = "D:/SSM项目存放/project/j_music/test/";
}
创建 DriverUtils
,更好获取 webDriver
java
package utils;
import constants.Constants;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class DriverUtils {
public static WebDriver getWebDriver() {
ChromeOptions options = new ChromeOptions();
// 允许浏览器接受来自任何源的远程请求
options.addArguments(Constants.ALL_REQUEST);
return new ChromeDriver(options);
}
}
6.1 注册
页面 符合 UI 设计
编写自动化测试
在 resources 下创建 registerTest.csv 文件 存放 要测试的数据
测试数据
csv
abc,123456,123456
,123456,123456
a,123456,123456
ab,123456,123456
abc1234,123456,123456
abc12345,123456,123456
abc123456,123456,123456
abc""\,123456,123456
abce,12345,12345
abcd,1234567,1234567
abcde,12345671234567,12345671234567
abcdef,123456712345671,123456712345671
abcf,1234567123456712,1234567123456712
abc,123456,
abc,,123456
创建 registerTest 类 , 编写自动化测试方法
java
package register;
import constants.Constants;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import utils.DriverUtils;
public class RegisterTest {
private WebDriver webDriver;
@AfterEach
public void quit() {
webDriver.quit();
}
@ParameterizedTest
@CsvSource(value = "黑蛋243,123456,123456")
public void singleRegister(String name, String password, String repetitionPassword) throws InterruptedException {
WebDriver webDriver = DriverUtils.getWebDriver();
webDriver.get(Constants.MY_REGISTER_URL);
webDriver.findElement(By.cssSelector("#user")).sendKeys(name);
webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
webDriver.findElement(By.cssSelector("#repetition_password")).sendKeys(repetitionPassword);
webDriver.findElement(By.cssSelector("#submit")).click();
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = webDriver.switchTo().alert();
alert.accept();
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(currentUrl, Constants.MY_LOGIN_URL);
}
@ParameterizedTest
@CsvFileSource(resources = "/registerTest.csv")
public void batchRegister(String name, String password, String repetitionPassword) {
webDriver = DriverUtils.getWebDriver();
webDriver.get(Constants.MY_REGISTER_URL);
webDriver.findElement(By.cssSelector("#user")).sendKeys(name == null ? "" : name);
webDriver.findElement(By.cssSelector("#password")).sendKeys(password == null ? "" : password);
webDriver.findElement(By.cssSelector("#repetition_password")).sendKeys(repetitionPassword == null ? "" : repetitionPassword);
webDriver.findElement(By.cssSelector("#submit")).click();
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = webDriver.switchTo().alert();
alert.accept();
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(currentUrl, Constants.MY_LOGIN_URL);
// webDriver.quit();
}
}
执行 batchRegister 方法 :
执行完自动化后,会发现出了密码为空和确认密码为空的两个用例没有过,其他的都通过了就说明:
- 系统没有对用户名做非空验证
- 系统没有对用户名做长度校验
- 系统没有对用户名是否含有特殊字符做校验
- 系统没有对密码长度做判断
此时数据库:
6.2 登录
页面符合 UI 设计
验证按钮是否可点击:
java
package login;
import constants.Constants;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import utils.DriverUtils;
import java.util.concurrent.TimeUnit;
public class MyMusicWebsiteLoginTest {
private WebDriver driver;
@BeforeEach
public void getWebDriver() {
driver = DriverUtils.getWebDriver();
}
@AfterEach
public void quit() {
driver.quit();
}
// 验证登录按钮是否有用
@Test
public void checkLongButton() {
driver.get(Constants.MY_LOGIN_URL);
// 找到 button 按钮进行点击
driver.findElement(By.cssSelector("#submit")).click();
// 校验是否出现弹出框
WebDriverWait wait = new WebDriverWait(driver, 6);
// 等待弹出框
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
Assertions.assertNotNull(alert);
alert.accept();
}
}
测试通过
测试登录功能:
- 登录成功: 判断依据用户输入完账户密码后点击确认按钮,成功进入到主页面 (判断当前 页面 url 是否为主页面 url 即可)
- 登录失败 : 判断是点击完弹窗是否还是在 登录页面即可
编写自动化测试脚本:
java
@ParameterizedTest
@CsvSource(value = "abc,123456")
public void checkLoginSuccess(String name, String password) {
driver.get(Constants.MY_LOGIN_URL);
driver.findElement(By.cssSelector("#user")).sendKeys(name == null ? "" : name);
driver.findElement(By.cssSelector("#password")).sendKeys(password == null ? "" : password);
driver.findElement(By.cssSelector("#submit")).click();
// 此时出现 alter
WebDriverWait wait = new WebDriverWait(driver, 5);
// 显示等待出现弹出框
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
// 判断 alert --> 到这里就可以判断出否登录成功了
Assertions.assertEquals("登录成功!!!", alert.getText());
alert.accept();
// 在这里还可以通过判断 url
String currentUrl = driver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_INDEX_URL, currentUrl);
}
测试结果:
构造测试数据(登录失败用例): 在 resources 创建 logintest.csv 在文件中输入一下数据.
java
abc,123456
abcd,123456
abc/"",123456
abc,12345
abc,1234567
abc,1234567123456712
编写自动化脚本
java
@ParameterizedTest
@CsvFileSource(resources = "/logintest.csv")
public void checkLoginFail(String name, String password) {
driver.get(Constants.MY_LOGIN_URL);
driver.findElement(By.cssSelector("#user")).sendKeys(name == null ? "" : name);
driver.findElement(By.cssSelector("#password")).sendKeys(password == null ? "" : password);
driver.findElement(By.cssSelector("#submit")).click();
// 显示等待 弹出框
WebDriverWait wait = new WebDriverWait(driver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
if (name == null || name.equals("") || Objects.equals(password, "")) {
Assertions.assertEquals("用户名或密码为空 !!!", alert.getText());
} else {
Assertions.assertEquals("用户名或密码错误 !!!!", alert.getText());
}
alert.accept();
// 判断 url
Assertions.assertEquals(Constants.MY_LOGIN_URL, driver.getCurrentUrl());
}
这里 abc , 123456 是 正确的账号和密码 所以被拦住了
看完上面运行会发现问题:
- 未对用户名做长度校验
- 未对密码做长度校验
- 未校验用户名是否含有特殊字符
6.2 主页面
页面符合 UI 设计
执行测试用例:
方案 | 功能 | 操作步骤 | 预期结果 |
---|---|---|---|
22 | 播放音乐 | 选中哆啦A梦的播放音乐按钮点击 | 音乐播放成功 |
23 | 收藏歌曲 | 选中需要收藏的歌曲点击喜欢按钮 | 音乐被收藏,然后跳转至收藏页面 |
24 | 收藏歌曲 | 选中用户已收藏的歌曲点击喜欢按钮 | 弹出提示框歌曲已收藏 |
25 | 删除音乐 | 选中要删除的歌曲点击删除按钮 | 歌曲删除 |
26 | 批量删除音乐 | 选中需要删除的歌曲点击删除按钮 | 歌曲删除 |
27 | 校验登录 | 未登录用户通过 URL 直接进入页面 | 弹出提示框提示用户登录然后页面跳转至登录页面 |
28 | 查找音乐 | 用户在输入框输入完整歌曲名 如 哆啦A梦 | 页面展示出有关哆啦A梦的歌曲 |
29 | 查找音乐 | 用户在输入框输入 部分歌曲名称 如 哆 | 页面展示出有关 哆 的歌曲 |
30 | 跳转功能 | 用户点击添加歌曲或喜欢列表按钮 | 页面跳转至上传文件页面或收藏页面 |
31 | 上传音乐 | 点击选中文件,在本地选中要上出的 mp3 文件 然后输入歌手名点击上传 | 弹出提示框文件上传成功,页面跳转至主页面 |
编写自动化脚本:
java
package login;
import constants.Constants;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import utils.DriverUtils;
import java.time.Duration;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MainPageTest {
private static WebDriver webDriver;
// 在所有方法执行之前执行一下这个获取 driver 的方法
@BeforeAll
static void getWebDriver() {
webDriver = DriverUtils.getWebDriver();
}
// 在所有方法执行之后 对 driver 进行关闭
@AfterAll
static void quit() {
webDriver.quit();
}
@Order(1)
@Test
// 未登录直接通过 url 进入 主页面
public void noLoginEnterIHomePage() {
webDriver.get(Constants.MY_INDEX_URL);
// 此时会直接回到登录页面
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_LOGIN_URL, currentUrl);
}
// 登录
@Order(2)
@ParameterizedTest
@CsvSource(value = "abc,123456")
public void login(String name, String password) {
// webDriver.get(Constants.MY_LOGIN_URL);
webDriver.findElement(By.cssSelector("#user")).sendKeys(name == null ? "" : name);
webDriver.findElement(By.cssSelector("#password")).sendKeys(password == null ? "" : password);
webDriver.findElement(By.cssSelector("#submit")).click();
// 此时出现 alter
WebDriverWait wait = new WebDriverWait(webDriver, 5);
// 显示等待出现弹出框
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
// 判断 alert --> 到这里就可以判断出否登录成功了
Assertions.assertEquals("登录成功!!!", alert.getText());
alert.accept();
}
@Order(3)
@Test
public void playMusic() {
webDriver.findElement(By.cssSelector("#info > tr:nth-child(1) > td:nth-child(4) > button")).click();
// 此时判断歌曲是否被播放,只要判断播放器,上显示歌曲的名字是否不为 空即可
String musicName = webDriver.findElement(By.cssSelector("#body > div:nth-child(2) > div > div > div.topbar > div.topbar-program > div.topbar-program-title")).getText();
Assertions.assertNotEquals("", musicName);
}
@Order(4)
@Test
public void loveMusic() {
webDriver.findElement(By.cssSelector("#info > tr:nth-child(1) > td:nth-child(5) > button:nth-child(2)")).click();
// 弹出提示框
WebDriverWait wait = new WebDriverWait(webDriver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
String loveMusicDesc = alert.getText();
alert.accept();
if (loveMusicDesc.equals("歌曲已经收藏,请重新选择")) {
return;
}
Assertions.assertEquals("添加成功", loveMusicDesc);
// webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
// 此时跳转至喜欢页面
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_LOVEMUSIC_URL, currentUrl);
// 此时将喜欢音乐添加成功,将页面退回至主页面 通过窗口操作
webDriver.navigate().back();
}
// 添加重复的音乐
@Order(5)
@Test
public void loveRepetitionMusic() {
webDriver.findElement(By.cssSelector("#info > tr:nth-child(1) > td:nth-child(5) > button:nth-child(2)")).click();
// 弹出提示框
WebDriverWait wait = new WebDriverWait(webDriver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
String loveMusicDesc = alert.getText();
Assertions.assertEquals("歌曲已经收藏,请重新选择", loveMusicDesc);
alert.accept();
// webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
// 此时跳转至喜欢页面
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_INDEX_URL, currentUrl);
// 此时将喜欢音乐添加成功,将页面退回至主页面 通过窗口操作
// webDriver.navigate().back();
}
// 上传音乐
@Order(6)
@ParameterizedTest
@CsvFileSource(resources = "/musicName.csv")
public void uploadMusicFile(String musicName, String singerName) {
webDriver.findElement(By.cssSelector("#body > div.container > div:nth-child(3) > a:nth-child(2)")).click();
// 此时页面进行跳转
// 上传文件 1.找到上传文件按钮,然后通过 sendKeys 输入要上传文件的路径即可
webDriver.findElement(By.cssSelector("body > form > input[type=file]:nth-child(1)")).sendKeys(Constants.MY_FILE_UPLOAD_PATH + musicName);
// 输入歌手名 --> 避免上传文件重复 (后端主要同故宫 判断歌曲名和歌手名) 这里就对 歌手名加一个随机数
singerName = singerName + DriverUtils.getRandomStr(Constants.LEN_5);
// 输入歌手名
webDriver.findElement(By.cssSelector("body > form > label > input[type=text]")).sendKeys(singerName);
// 点击上传按钮
webDriver.findElement(By.cssSelector("body > form > input[type=submit]:nth-child(3)")).click();
// 此时校验是否长传成功,判断当前页面的 url 是否为主页面即可
String currentUrl = webDriver.getCurrentUrl();
// System.out.println("------------------当前页面Url: " + currentUrl + "----------------");
Assertions.assertEquals(Constants.MY_INDEX_URL, currentUrl);
}
@Order(7)
@ParameterizedTest
@CsvFileSource(resources = "/findMusicKeys.csv")
public void findMusicByKey(String key) {
// 找到查找框
webDriver.findElement(By.cssSelector("#exampleInputName2")).sendKeys(key);
// 点击查询按钮
webDriver.findElement(By.cssSelector("#submit1")).click();
// 拿到整个 表格
WebElement tableElement = webDriver.findElement(By.cssSelector("#info"));
// 获取 表格中的每一行的数据
List<WebElement> trElements = tableElement.findElements(By.tagName("tr"));
// 这里的结构是
// <tr>xxxxx<tr/>
// <tr><tr/>
for (WebElement nowTrLabel : trElements) {
// 获取到当前 tr 标签
// 获取标签中的 th 元素
List<WebElement> thElements = nowTrLabel.findElements(By.tagName("td"));
if (thElements.isEmpty()) {
continue;
}
// 此时不为空 -- 校验 musicName
WebElement thElement = thElements.get(0);
// 判断 音乐名是否含有 key 比如 哆啦a梦 是否含有 哆
Assertions.assertTrue(thElement.getText().contains(key));
}
// 此时查找完成后,再次找到输入框 输入 "" , 再次点击查询按钮 查询到所有的音乐
// 找到查找框
// webDriver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("");
// 点击查询按钮
webDriver.findElement(By.cssSelector("#submit1")).click();
}
// 删除音乐 --> 删除单个音乐
@Order(8)
@Test
public void deleteMusic() {
// 获取 表格
WebElement tableElement = webDriver.findElement(By.cssSelector("#info"));
// 获取 表格中的每一行的数据
List<WebElement> trElements = tableElement.findElements(By.tagName("tr"));
int totalSize = trElements.size();
// 删除最后一个
WebElement finallyTrElement = trElements.get(trElements.size() - 2);
// 拿到勾选框
List<WebElement> thElements = finallyTrElement.findElements(By.tagName("th"));
List<WebElement> tdElements = finallyTrElement.findElements(By.tagName("td"));
// 找到 input 框进行点击
thElements.get(0).findElement(By.tagName("input")).click();
// 找到删除按钮
List<WebElement> buttons = tdElements.get(3).findElements(By.tagName("button"));
WebElement deleteButton = buttons.get(0);
deleteButton.click();
// 此时删除音乐弹出对话框
WebDriverWait wait = new WebDriverWait(webDriver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
// 判断是否删除 重新获取 table 判断个数即可
// 获取 表格
tableElement = webDriver.findElement(By.cssSelector("#info"));
// 获取 表格中的每一行的数据
trElements = tableElement.findElements(By.tagName("tr"));
Assertions.assertEquals(totalSize - 2, trElements.size());
}
// 批量删除音乐
@Order(9)
@ParameterizedTest
@CsvSource(value = "3")
public void batchDeleteMusic(Integer count) {
// 获取整个表格
WebElement tableElement = webDriver.findElement(By.cssSelector("#info"));
// 获取 tr 标签
List<WebElement> trElements = tableElement.findElements(By.tagName("tr"));
int totalSize = trElements.size();
// 循环勾选
for (int i = 0; i < count * 2; i += 2) {
// 拿到勾选框
WebElement nowTrElement = trElements.get(i);
// 获取 th 标签里面的 input
WebElement thElement = nowTrElement.findElement(By.tagName("th"));
// 找到 input 框 进行勾选
thElement.findElement(By.tagName("input")).click();
}
// 此时该删除的都勾选了 点击 批量删除按钮
webDriver.findElement(By.cssSelector("#delete")).click();
WebDriverWait wait = new WebDriverWait(webDriver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
// 校验是否删除成功 --> 判断当前表格 tr 个数即可
tableElement = webDriver.findElement(By.cssSelector("#info"));
trElements = tableElement.findElements(By.tagName("tr"));
Assertions.assertEquals(totalSize - count * 2, trElements.size());
}
}
执行脚本:
校验登录不符合预期结果,用户在未登录的情况下,进入 主页面并没有弹出提示框而是直接回到登录页面.
6.3 收藏页面
页面符合 UI 设计
方案 | 功能 | 操作步骤 | 预期结果 |
---|---|---|---|
32 | 播放音乐 | 选中哆啦A梦的播放音乐按钮点击 | 音乐播放成功 |
33 | 取消收藏 | 选中要取消收藏的歌曲点击删除按钮 | 歌曲删除 |
34 | 校验登录 | 未登录用户通过 URL 直接进入页面 | 弹出提示框提示用户登录然后页面跳转至登录页面 |
35 | 查找音乐 | 用户在输入框输入完整歌曲名 如 哆啦A梦 | 页面展示出有关哆啦A梦的歌曲 |
36 | 查找音乐 | 用户在输入框输入 部分歌曲名称 如 哆 | 页面展示出有关 哆 的歌曲 |
36 | 跳转功能 | 用户点击回到首页按钮 | 页面跳转至主页面 |
37 | 校验登录 | 未登录用户通过 URL 直接进入页面 | 弹出提示框提示用户登录然后页面跳转至登录页面 |
编写自动化脚本:
java
package login;
import constants.Constants;
import org.checkerframework.checker.units.qual.A;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import utils.DriverUtils;
import java.awt.*;
import java.lang.annotation.Documented;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Random;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LovePageTest {
private static WebDriver webDriver;
// 在所有方法执行之前执行一下这个获取 driver 的方法
@BeforeAll
static void getWebDriver() {
webDriver = DriverUtils.getWebDriver();
}
// 在所有方法执行之后 对 driver 进行关闭
@AfterAll
static void quit() {
webDriver.quit();
}
@Order(1)
@Test
// 未登录直接通过 url 进入 收藏页面
public void noLoginEnterIHomePage() {
webDriver.get(Constants.MY_LOVEMUSIC_URL);
// 此时会直接回到登录页面
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_LOGIN_URL, currentUrl);
}
// 登录
@Order(2)
@ParameterizedTest
@CsvSource(value = "abc,123456")
public void login(String name, String password) {
// webDriver.get(Constants.MY_LOGIN_URL);
webDriver.findElement(By.cssSelector("#user")).sendKeys(name == null ? "" : name);
webDriver.findElement(By.cssSelector("#password")).sendKeys(password == null ? "" : password);
webDriver.findElement(By.cssSelector("#submit")).click();
// 此时出现 alter
WebDriverWait wait = new WebDriverWait(webDriver, 5);
// 显示等待出现弹出框
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
// 判断 alert --> 到这里就可以判断出否登录成功了
Assertions.assertEquals("登录成功!!!", alert.getText());
alert.accept();
}
// 防止收藏页面没有歌曲,先对歌曲进行收藏
@Order(3)
@Test
public void loveMusic() {
// 拿到表格
WebElement tableElement = webDriver.findElement(By.cssSelector("#info"));
List<WebElement> trElements = tableElement.findElements(By.tagName("tr"));
// int randomUnevenNumber = DriverUtils.getRandomEvenNumber(trElements.size());
// 拿到勾选框
List<WebElement> thElements = null;
List<WebElement> tdElements = null;
while (true) {
int size = new Random().nextInt(trElements.size());
thElements = trElements.get(size).findElements(By.tagName("th"));
tdElements = trElements.get(size).findElements(By.tagName("td"));
if (thElements.size() == 1) {
break;
}
}
thElements.get(0).click();
// 拿到喜欢按钮
WebElement treeTdElement = tdElements.get(3);
List<WebElement> buttons = treeTdElement.findElements(By.tagName("button"));
WebElement loveButton = buttons.get(1);
// 使用JavaScript滚动到元素位置 --> 要不然找会找不到按钮点击会报错
// ((JavascriptExecutor) webDriver).executeScript("arguments[0].scrollIntoView(true);", loveButton);
// loveButton.click();
// 上面移动还是有点问题 直接 调用 javascript 进行点击即可
// 使用JavaScript点击元素
((JavascriptExecutor) webDriver).executeScript("arguments[0].click();", loveButton);
// 点击弹窗
WebDriverWait wait = new WebDriverWait(webDriver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
if (!alert.getText().equals("添加成功")) {
return;
}
alert.accept();
// 校验 url
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_LOVEMUSIC_URL, currentUrl);
// 退回 主页面
webDriver.navigate().back();
}
// 点击添加歌曲按钮进入收藏页面
@Order(4)
@Test
public void clickLoveButton() {
// 找到按钮进行点击
webDriver.findElement(By.cssSelector("#body > div.container > div:nth-child(3) > a:nth-child(1)")).click();
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_LOVEMUSIC_URL, currentUrl);
}
// 播放音乐
@Order(5)
@Test
public void playMusic() {
webDriver.findElement(By.cssSelector("#info > tr:nth-child(1) > td:nth-child(3) > button")).click();
WebDriverWait wait = new WebDriverWait(webDriver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("body > div:nth-child(2) > div > div > div.topbar > div.topbar-program > div.topbar-program-title")));
// 此时判断歌曲是否被播放,只要判断播放器,上显示歌曲的名字是否不为 空即可
String musicName = webDriver.findElement(By.cssSelector("body > div:nth-child(2) > div > div > div.topbar > div.topbar-program > div.topbar-program-title")).getText();
// System.out.println(musicName);
Assertions.assertNotEquals("", musicName);
}
// 查找收藏音乐
@Order(6)
@ParameterizedTest
@CsvFileSource(resources = "/findMusicKeys.csv")
public void findLoveMusicByKey(String key) {
// 找到查找框
webDriver.findElement(By.cssSelector("#exampleInputName2")).sendKeys(key);
// 点击查询按钮
webDriver.findElement(By.cssSelector("#submit1")).click();
// 拿到整个 表格
WebElement tableElement = webDriver.findElement(By.cssSelector("#info"));
// 获取 表格中的每一行的数据
List<WebElement> trElements = tableElement.findElements(By.tagName("tr"));
// 这里的结构是
// <tr>xxxxx<tr/>
// <tr><tr/>
for (WebElement nowTrLabel : trElements) {
// 获取到当前 tr 标签
// 获取标签中的 th 元素
List<WebElement> thElements = nowTrLabel.findElements(By.tagName("td"));
if (thElements.isEmpty()) {
continue;
}
// 此时不为空 -- 校验 musicName
WebElement thElement = thElements.get(0);
// 判断 音乐名是否含有 key 比如 哆啦a梦 是否含有 哆
Assertions.assertTrue(thElement.getText().contains(key));
}
webDriver.findElement(By.cssSelector("#submit1")).click();
}
// 移除收藏音乐
@Order(7)
@Test
public void deleteLoveMusic() {
webDriver.findElement(By.cssSelector("#info > tr:nth-child(1) > td:nth-child(4) > button")).click();
WebDriverWait wait = new WebDriverWait(webDriver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals(Constants.MY_INDEX_URL, currentUrl);
}
}
运行结果:
到此该项目基础功能都测试完成, 简述当前系统存在的 bug
注册:
-
未对用户名做长度校验
-
未对用户名做特殊字符判断 (用户名包含特殊字符)
-
未对用户输入框做判空校验 (用户名可以未空 ,然后进行注册)
-
未对用户密码做长度校验
登录:
- 未对用户名做长度校验
- 未对用户名做特殊字符判断 (用户名包含特殊字符)
- 未对用户密码做长度校验
主页面:
- 用户在未登录情况下 ,通过 url 进入主页面后,直接跳转至登录页面 (未弹出提示框让用户登录)