音乐播放器测试报告
项目背景
这是一个简易在线音乐服务器项目。该项目旨在为用户提供一个轻量级、易操作的音乐管理平台,让用户能够轻松上传、管理、查询和分享自己的音乐文件。通过该项目,用户可以享受到更加个性化、私密且高效的音乐体验。
项目功能
- 登录 ——用账号和密码登陆系统,进入音乐列表页面
- 上传音乐——用户可上传MP3文件到服务器
- 删除指定音乐——用户可删除指定的音乐
- 批量删除选中的音乐——用户可批量删除选中的音乐
- 查询你想要的音乐——用户可通过音乐名模糊查询音乐
- 播放音乐——借助Sewise Player开源库来实现音乐播放
- 添加音乐至喜欢的列表——用户可添加选中的音乐到喜欢列表
- 移除喜欢的音乐——用户可以删除自己喜欢列表中的音乐
测试计划
该项目相关的测试用例:
功能测试
测试环境:Win10系统 + Chrome
开发环境:idea
测试方式:人工测试
1.登陆功能测试
测试功能:登陆功能
执行测试的操作步骤:
1.在登陆界面填写正确的账号密码
2.点击登录
预期结果:有登陆成功的弹窗提醒,跳转到音乐列表页面
实际结果:有登陆成功的弹窗提醒,跳转到音乐列表页面
测试功能:登陆功能
执行测试的操作步骤:
1.在登陆界面填写错误的账号或者密码
2.点击登录
预期结果:有登陆失败的弹窗提醒,输入框清空
实际结果:有登陆失败的弹窗提醒,输入框清空
测试功能:登陆功能(异常测试)
执行测试的操作步骤:
1.在登陆界面输入框的账号或者密码为空
2.点击登录
预期结果:有用户名或密码不能为空的弹窗提醒
实际结果:有用户名或密码不能为空的弹窗提醒
2.上传音乐功能测试
测试功能:上传音乐功能
执行测试的操作步骤:
1.点击添加歌曲按钮跳转到音乐上次页面
2.点击选择音乐按钮,选择本地音乐
3.在输入框输入歌手名
4.点击上传
预期结果:跳转到音乐列表页面,新增的音乐显示在最下行的数据
实际结果:跳转到音乐列表页面,新增的音乐显示在最下行的数据
测试功能:上传音乐功能(重复上传相同音乐和歌手名)
执行测试的操作步骤:
1.点击添加歌曲按钮跳转到音乐上次页面
2.点击选择音乐按钮,选择本地音乐
3.在输入框输入歌手名
4.点击上传
预期结果:有音乐已存在的弹窗提醒
实际结果:有音乐已存在的弹窗提醒
3.删除音乐功能测试
测试功能:删除单个音乐功能
执行测试的操作步骤:
1.选择着要删除的音乐
2.点击删除
预期结果:有删除成功的弹窗的提醒,确认重新刷新页面
实际结果:有删除成功的弹窗的提醒,确认重新刷新页面
测试功能:批量删除音乐功能
执行测试的操作步骤:
1.勾选多个音乐
2.点击删除选中
预期结果:有删除成功的弹窗的提醒,确认重新刷新页面
实际结果:有删除成功的弹窗的提醒,确认重新刷新页面
4.查询音乐
测试功能:查询音乐功能
执行测试的操作步骤:
1.在输入框输入歌名
2.点击查询按钮
预期结果:音乐列表页面只剩下歌名为bysh的数据
实际结果:音乐列表页面只剩下歌名为bysh的数据
5.添加喜欢的音乐
测试功能:添加喜欢的音乐功能
执行测试的操作步骤:
1.选择要收藏的音乐
2.点击喜欢按钮
预期结果:有收藏成功的弹窗的提醒,喜欢列表页面新增一条对应要收藏的音乐数据
实际结果:有收藏成功的弹窗的提醒,喜欢列表页面新增一条对应要收藏的音乐数据
6.播放音乐功能测试
测试功能:播放音乐功能
执行测试的操作步骤:
1.点击播放音乐按钮
预期结果:有音乐播放
实际结果:有音乐播放
自动化测试
音乐播放器自动化测试用例
1.登陆页面
测试点
测试代码
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // 指定类的测试顺序
public class LoginTest extends AutoTest {
// 这里我们调用了父类AutoTest中的静态方法,获取驱动对象
public static ChromeDriver driver = createDriver();
@Test
@BeforeAll // 被@BeforeAll修饰的方法要是静态的
static void init() {
// 跳转到博客登录页面
driver.get("http://127.0.0.1:8080/login.html");
driver.manage().window().maximize();
}
// 检查登录页面显示是否正常
@Test
@Order(1)
void loginPageTest() {
String expect = "登录";
String actual = driver.findElement(By.xpath("/html/body/div[2]/div/h3")).getText();
// 通过断言查看页面显示
Assertions.assertEquals(expect, actual);
// 查看页面相关元素是否存在
driver.findElement(By.cssSelector("#submit"));
driver.findElement(By.cssSelector("body > div.nav > a"));
Assertions.assertEquals("音乐播放器", driver.findElement(By.cssSelector("body > div.nav > span.title")).getText());
}
// 检查用户名密码出错的情况(登录失败的情况)
@Order(2)
@ParameterizedTest // 多个参数
@CsvSource({"lisi, 123"})
void loginFailTest(String username, String password) throws InterruptedException {
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#username")).sendKeys(username);
driver.findElement(By.cssSelector("#password")).sendKeys(password);
driver.findElement(By.cssSelector("#submit")).click();
Thread.sleep(100);
Alert alert = driver.switchTo().alert();
Assertions.assertEquals("登录失败,密码或者用户名错误!", alert.getText());
alert.accept();
}
// 检查用户名或者密码错误(登录成功的情况)
@Order(3)
@ParameterizedTest // 多个参数
@CsvSource({"zhangsan, 123456"})
void loginSuccessfulTest(String username, String password) throws InterruptedException, IOException {
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#username")).sendKeys(username);
driver.findElement(By.cssSelector("#password")).sendKeys(password);
driver.findElement(By.cssSelector("#submit")).click();
Thread.sleep(200);
Alert alert = driver.switchTo().alert();
Assertions.assertEquals("登录成功!", alert.getText());
alert.accept();
// 上述步骤只是说明输入了账号和密码,但还不知道点击提交后是否会跳转到音乐列表页
String expect = "127.0.0.1:8080/list.html";
String actual = driver.getCurrentUrl();
Assertions.assertEquals(expect, actual); // 查看当前的url是否音乐列表页面
// 进行截图,看当前是否跳转到了音乐列表界面
// 程序执行的速度和页面渲染的速度
File srcFile = driver.getScreenshotAs(OutputType.FILE);
String fileName = "loginRightTest.png";
FileUtils.copyFile(srcFile, new File(fileName));
}
@AfterAll
@Test
static void exit() {
driver.quit();
}
}
2.音乐列表页面
测试点
测试代码
package loginedTests;
import common.AutoTest;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.*;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.File;
import java.io.IOException;
/**
* 登录情况下
* 音乐总列表页面的测试
*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // 指定类的测试顺序(根据每个方法的order序号)
public class musicList extends AutoTest {
public static ChromeDriver driver = createDriver();
@Test
@BeforeAll
static void init() {
driver.get("http://127.0.0.1:8080/list.html?pindex=1&name=");
driver.manage().window().maximize();
}
@Test
@Order(1)
void pageTest() { // 检查页面显示和音乐播放功能
// 跳转后的新页面的文字显示
Assertions.assertEquals("音乐列表", driver.findElement(By.cssSelector("#body > div.container > h3")).getText());
// 查看播放悬浮框是否存在
driver.findElement(By.cssSelector("#body > div:nth-child(3) > div > div > div.big-play-btn > a"));
Assertions.assertEquals("喜欢列表", driver.findElement(By.cssSelector("#body > div.container > div:nth-child(3) > a:nth-child(1)")).getText());
Assertions.assertEquals("添加歌曲", driver.findElement(By.cssSelector("#body > div.container > div:nth-child(3) > a:nth-child(2)")).getText());
Assertions.assertEquals("删除选中", driver.findElement(By.cssSelector("#delete")).getText());
Assertions.assertEquals("退出登录", driver.findElement(By.cssSelector("#logout")).getText());
// 各个链接、按钮,能否正常跳转到对应页面
// driver.findElement(By.cssSelector("#body > div.container > div:nth-child(3) > a:nth-child(1)")).click();
// String expectUrl1 = "http://49.235.66.46:9090/loveMusic.html";
// Assertions.assertEquals(expectUrl1, driver.getCurrentUrl());
// driver.navigate().back(); // 回退到音乐列表页面
driver.findElement(By.cssSelector("#body > div.container > div:nth-child(3) > a:nth-child(2)")).click();
String expectUrl = "http://127.0.0.1:8080/upload.html";
Assertions.assertEquals(expectUrl, driver.getCurrentUrl());
driver.navigate().back();
// 检查音乐播放功能
// 获取第一首歌曲的播放按钮元素,点击播放
driver.findElement(By.cssSelector("#info > tr:nth-child(1) > td:nth-child(4) > button")).click();
String expectSrc = "http://jackzhang1204.github.io/materials/where_did_time_go.mp3";
String actualSrc = driver.findElement(By.cssSelector("#body > div:nth-child(3) > div > audio")).getAttribute("src");
// 默认未点击播放的src值为:http://jackzhang1204.github.io/materials/where_did_time_go.mp3
// 如果正常播放:比如当前页面的第一个个歌曲——此时src的值 :http://49.235.66.46:9090/music/get?path=%E5%BC%80%E5%A7%8B%E6%87%82%E4%BA%86-%E5%AD%99%E7%87%95%E5%A7%BF.128.mp3
Assertions.assertNotEquals(expectSrc,actualSrc); // 如果不匹配,说明音乐可以正常播放
}
@Test
@Order(2)// 搜索功能测试
void searchTest() throws IOException, InterruptedException {
// 往搜索框中输入文本,点击搜索,查看页面是否出现你要找的搜索结果(按歌曲名称查找)
driver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("开始懂了");
driver.findElement(By.cssSelector("#submit1")).click();
// 进行截图,看当前是否跳转到了登录界面
// 程序执行的速度和页面渲染的速度
File srcFile = driver.getScreenshotAs(OutputType.FILE);
String fileName = "searchTest.png";
FileUtils.copyFile(srcFile, new File(fileName));
// 如果搜索到了,应该能找到对应的歌手
String expect = "孙燕姿";
Assertions.assertEquals(expect, driver.findElement(By.cssSelector("#info > tr > td:nth-child(3)")).getText());
// 如果搜索结果为空,是否有弹窗提醒
driver.findElement(By.cssSelector("#exampleInputName2")).clear();
driver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("ddf懂了");
driver.findElement(By.cssSelector("#submit1")).click();
Thread.sleep(200);
Alert alert = driver.switchTo().alert();
Assertions.assertEquals("当前搜索结果为空,请重新搜索", alert.getText());
alert.accept();
}
@AfterAll
@Test
static void exit() {
driver.quit();
}
}
3.音乐收藏页面
测试点
测试代码
package loginedTests;
import common.AutoTest;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import javax.swing.tree.TreeNode;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static loginedTests.LoginTest.driver;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // 指定类的测试顺序(根据每个方法的order序号)
public class myMusicListTest extends AutoTest {
// 这里我们调用了父类AutoTest中的静态方法,获取驱动对象
// public static ChromeDriver driver = createDriver();
// 我们这里不用重新生成驱动,用的还是登录页面的驱动
@Test
@BeforeAll // 被@BeforeAll修饰的方法要是静态的
static void init() {
// 跳转到博客登录页面
driver.get("http://127.0.0.1:8080/loveMusic.html");
// driver.manage().window().maximize();
}
// 返回当前页面是否存在弹窗
private boolean isAlertPresent(WebDriver driver) {
try {
driver.switchTo().alert();
return true;
} catch (NoAlertPresentException e) {
return false;
}
}
/**
* 检查页面显示和各个按钮所对应的功能(音乐播放,从收藏列表中移除该元素)
*/
@Test
@Order(1)
void lovePageTest() throws InterruptedException, IOException {
/**
* 判断是否有弹窗,如果当前收藏列表为空,会出现弹窗提示
*/
// 初始化 WebDriverWait 对象
// WebDriverWait 类来设置等待时间为3秒,并使用 until() 方法结合 ExpectedConditions.alertIsPresent() 来等待弹窗的出现。
// 如果在等待时间内成功找到弹窗,until() 方法返回一个 Alert 对象;否则,返回 null。然后,我们将 Alert 对象与 null 进行比较,以判断弹窗是否存在。
File srcFile1 = driver.getScreenshotAs(OutputType.FILE);
String fileName1 = "myMusicListTest.png";
FileUtils.copyFile(srcFile1, new File(fileName1));
Duration timeout = Duration.ofSeconds(3); // 设立弹窗轮询查看时间
boolean isAlert = isAlertPresent(driver);
WebDriverWait wait = new WebDriverWait(driver, timeout);
try {
// 等待弹窗出现---如果出现弹窗,说明当前收藏(喜欢)列表为空,就不执行接下来的测试步骤,直接返回
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
System.out.println("弹窗内容:" + alert.getText());
alert.accept();
return;
} catch (TimeoutException e) {
// 异常处理:超时未出现弹窗--收藏(喜欢列表)不为空
System.err.println("等待弹窗超时");
}
String expect = "我喜欢的音乐列表";
String actual = driver.findElement(By.cssSelector("body > div.container > h3")).getText();
Assertions.assertEquals(expect, actual);
// 查看页面相关元素是否存在,文本是否一致
Assertions.assertEquals("回到首页", driver.findElement(By.cssSelector("body > div.container > div:nth-child(3) > a.btn.btn-primary")).getText());
Assertions.assertEquals("退出登录", driver.findElement(By.cssSelector("#logout")).getText());
// 搜索框和搜索按钮
driver.findElement(By.cssSelector("#exampleInputName2"));
Assertions.assertEquals("查询", driver.findElement(By.cssSelector("#submit1")).getText());
// 查看播放悬浮框是否存在
driver.findElement(By.cssSelector("body > div:nth-child(3) > div"));
// 检查音乐播放功能
//
// 获取第一首歌曲的播放按钮元素,点击播放
driver.findElement(By.cssSelector("#info > tr:nth-child(1) > td:nth-child(3) > button")).click();
String expectSrc = "http://jackzhang1204.github.io/materials/where_did_time_go.mp3";
String actualSrc = driver.findElement(By.cssSelector("body > div:nth-child(3) > div > audio")).getAttribute("src");
// 默认未点击播放的src值为:http://jackzhang1204.github.io/materials/where_did_time_go.mp3
// 如果正常播放:比如当前页面的第一个个歌曲——此时src的值 :http://49.235.66.46:9090/music/get?path=%E5%BC%80%E5%A7%8B%E6%87%82%E4%BA%86-%E5%AD%99%E7%87%95%E5%A7%BF.128.mp3
Assertions.assertNotEquals(expectSrc,actualSrc); // 如果不匹配,说明音乐可以正常播放
/**
* 从音乐列表中移除该元素(移除 列表中的第三首歌)
*/
// 移除前,喜欢列表的歌曲数目 = 移除后,喜欢列表的歌曲数目 + 1;
// // 定位歌曲表格
WebElement table = driver.findElement(By.cssSelector("body > div.container > table"));
// 定位歌曲行元素
List<WebElement> songRows = table.findElements(By.tagName("tr"));
// 获取歌曲数量
int songCount = songRows.size() - 1; //减去表格的头部
System.out.println("移除前,当前页面歌曲的数目:" + songCount);
// 移除元素--移除元素
WebElement elementPlay;
try {
elementPlay = driver.findElement(By.cssSelector("#info > tr:nth-child(3) > td:nth-child(4) > button"));
} catch (Exception e) {
System.err.println("你要移除的元素不存在!!!");
return; // // 如果要移除的元素(歌曲),没有显示在列表中(或者已经移除),出现异常,直接返回
}
System.out.println("从而达到是");
elementPlay.click();
/**
* 我们获取弹窗的时候,最好都try catch一下,这样更保险,处理因为找不到弹窗而出现的异常
*/
// 会出现一个弹窗,提示是否要移除该元素
try {
Alert alert2 = driver.switchTo().alert();
alert2.accept();
}
catch (TimeoutException e) {
// 异常处理:超时未出现弹窗
System.err.println("等待弹窗超时");
}
// 点击,确定,系统会处理这个操作,从数据库的喜欢列表中移除该元素,这是需要时间的,所有需要等待弹窗的出现
// 移除后,有会出现一个弹窗,提示移除成功
try {
Alert alert3 = wait.until(ExpectedConditions.alertIsPresent());
alert3.accept();
File srcFile4 = driver.getScreenshotAs(OutputType.FILE);
String fileName4 = "moveResultTest.png";
FileUtils.copyFile(srcFile4, new File(fileName4));
}
catch (TimeoutException e) {
// 异常处理:超时未出现弹窗
System.err.println("等待弹窗超时");
}
// 删除后,重新计算歌曲数量
WebElement tableNew = driver.findElement(By.cssSelector("body > div.container > table"));
// 定位歌曲行元素
songRows = tableNew.findElements(By.tagName("tr"));
// 获取歌曲数量
int songCountNew = songRows.size() - 1; //减去表格的头部
System.out.println("移除后,当前页面歌曲的数目:" + songCountNew);
Assertions.assertEquals(songCount, songCountNew + 1);
}
/**
* 搜索功能测试
* @throws IOException
* @throws InterruptedException
*/
@Test
@Order(2)
void searchTest() throws IOException, InterruptedException {
// 往搜索框中输入文本,点击搜索,查看页面是否出现你要找的搜索结果(按歌曲名称查找)
driver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("阴天快乐");
driver.findElement(By.cssSelector("#submit1")).click();
// 等待弹窗出现
Duration timeout = Duration.ofSeconds(3);
WebDriverWait wait = new WebDriverWait(driver, timeout);
// 尝试获取弹窗
// 我们在输入框中输入文本内容,点击查询,看是否出现弹窗
// 如果出现弹窗,说明搜索结果为空————直接返回
try {
Alert alert4 = wait.until(ExpectedConditions.alertIsPresent());
alert4.accept();
return;
}
catch (TimeoutException e) {
// 异常处理:超时未出现弹窗
System.err.println("等待弹窗超时");
}
// 程序走到这里,说明上面点击搜索后----没有弹窗————搜索结果不为空
System.out.println("No Alert Found.");
// 搜索结果截图
File srcFile = driver.getScreenshotAs(OutputType.FILE);
String fileName = "searchResultTest.png";
FileUtils.copyFile(srcFile, new File(fileName));
// 如果按歌曲名搜索到了,应该能找到该歌曲名所对应的歌手
String expect = "陈奕迅";
Assertions.assertEquals(expect, driver.findElement(By.cssSelector("#info > tr > td:nth-child(2)")).getText());
}
}
测试结果
本项目基本实现一个简易在线音乐服务器的应有功能,所有功能均符合预期,性能稳定,无重大缺陷,用户体验良好。