我的项目测试

article/2025/11/7 3:50:47

我的项目测试


文章目录

  • 我的项目测试
  • 前言
  • 一、单元测试
  • 二、功能测试
    • 1.界面测试
    • 2.功能测试
      • (1)已发布专辑列表功能
      • (2)播放功能
      • (3)用户管理功能
      • (4)音频管理功能
      • (5)专辑管理功能
      • (6)异常情况
    • 3.易用性测试
    • 4.性能测试
    • 5.兼容性测试
  • 三、自动化测试
    • 1.首页专辑列表及播放功能
    • 2.注册、登录、注销功能
    • 3.音频管理功能
    • 4.专辑管理功能
    • 5.组合所有的测试用例
    • 6.生成测试报告
  • 四、性能测试


前言

自己写了一个项目,“一起听书吧”,该项目是一个听书网站,未注册用户访问时直接进入专辑列表页面(首页),可以看到所 有已发布专辑,并选择某个专辑播放音频或音频切换,也可以进行账号注册,但是不支持上传音频、 录制音频、管理专辑等操作。已注册用户访问时也是进入首页,可以点击进入”创作中心“ 进行登录, 登录后就可以上传音频、录制音频、查看个人音频列表、创建专辑、为专辑绑定音频、查看专辑列表、 上下架专辑等……

项目 URL:点击开始使用项目


一、单元测试

单元测试是对软件基本组成单元进行的测试,而且软件单元是在与程序的其他部分相隔离的情况下进行独立的测试。其目标确保单元模块能被正确地编码、保证代码在结构上可靠且健全。单元测试可以尽早发现错误、发现问题比较容易、修正问题比较容易。

在本项目中,我采用JUnit单元测试框架进行单元测试。鉴于项目比较简单、大多数处理逻辑都是一些增删查改,所以我的单元测试写的比较少。

class TrackRepoTest {private TrackRepo trackRepo=new TrackRepo();@Testvoid selectCountByUid() {UserVO currentUser=new UserVO(3,"吕倩");int count=trackRepo.selectCountByUid(currentUser);//15:预期值//count:实际值//message:预期值与实际值不相等时,以异常形式输出 messageAssertions.assertEquals(15,count,"该用户的专辑数量查找错误");}
}

这个方法是根据当前登录用户(currentUser) 去查找该用户的专辑数量,因为我可以从数据库中得到该用户的专辑数量,所以只需要调用被测方法得到专辑数量,然后利用断言,即调用Assertions.assertEquals()方法进行实际值和预期值的比较,如果实际值和预期值相等,说明被测方法是没有问题的,否则就赶紧改改代码吧🤗

class AlbumRepoTest {AlbumRepo albumRepo=new AlbumRepo();@Testvoid selectUidByAid() {int aid=4;int uid=albumRepo.selectUidByAid(aid);int expectUid=3;Assertions.assertEquals(expectUid,uid,"aid为"+aid+"的专辑不属于uid为"+expectUid+"的用户");}
}

这个被测方法方法的作用是根据aid(专辑编号)查找uid(用户编号),我的测试思路是,已知expectUid=3(这是从数据库中看到的),然后调用被测方法获得实际uid,断言,判断实际值和预期值是否相同。

其他的单元测试也都类似,基本上都是增删查改,就展示这两个吧。

二、功能测试

对项目的界面、功能、易用性、性能、兼容性等进行了功能测试,测试用例如下:

1.界面测试

界面测试测试用例

2.功能测试

(1)已发布专辑列表功能

已发布专辑列表功能

(2)播放功能

播放功能

(3)用户管理功能

用户管理功能

(4)音频管理功能

①上传音频功能
上传功能
②录制音频功能
录制音频功能
③音频列表功能
音频列表功能

(5)专辑管理功能

专辑管理功能

(6)异常情况

异常情况

3.易用性测试

易用性测试

4.性能测试

采用 LoadRunner 进行性能测试。

5.兼容性测试

测试方法:自动化测试。
兼容性测试

三、自动化测试

对系统的大致流程,使用 unittest 框架进行了自动化测试,并生成了测试报告。

1.首页专辑列表及播放功能

首先,进入首页,检查其是否能正常显示所有已发布专辑列表。然后,点击任意一个专辑,进入播放页面播放专辑绑定的音频,并且切换音频,观察能否正常播放和音频切换。

我在里面加了很多打印信息,是为了让自己清楚的看到哪一步出了问题😊

from selenium import webdriver
import unittest
import timecoding = "utf-8"from selenium.webdriver.common.by import By# 点击进入网站首页(已发布专辑列表页面),任意点击一个专辑,播放音频,切换下一首、上一首、暂停,返回首页,点击进入创作中心
class publishedAlbumList(unittest.TestCase):def setUp(self):print("************setUp************")# self.driver,driver 就是全局变量了self.driver = webdriver.Chrome()self.url = "http://49.234.24.213:8080/"self.driver.maximize_window()time.sleep(5)# tearDown:测试环境的清理def tearDown(self):print("************tearDown************")self.driver.quit()def test_aChoiceAlbum(self):driver = self.driverurl = self.urldriver.get(url)time.sleep(2)# 点击专辑名称(进入专辑)driver.find_element(By.LINK_TEXT, "海阔天空").click()# 固定等待(必须等够设置的时长)time.sleep(5)# 隐式等待(只能等待,等到页面上的元素加载出来之后就去执行下一条指令)# driver.implicitly_wait(5);print("************进入专辑啦************")time.sleep(2)# 进人播放页面(开始播放)play = driver.find_element(By.CSS_SELECTOR, '.fa-play')driver.execute_script("arguments[0].click();", play)time.sleep(15)# 下一首print("************开始播放啦************")driver.find_element(By.ID, "next").click()time.sleep(15)print("************播放下一首************")# 上一首driver.find_element(By.ID, "prev").click()time.sleep(15)print("************播放上一首************")# 暂停driver.execute_script("arguments[0].click();", play)print("************暂停************")time.sleep(3)# 返回首页driver.find_element(By.LINK_TEXT, "一起听书吧").click()time.sleep(3)print("************返回首页************")driver.find_element(By.LINK_TEXT, "创作中心").click()time.sleep(3)print("************进入创作中心************")if __name__ == "__main__":unittest.main(verbosity=2)

2.注册、登录、注销功能

先注册,再用注册的用户名和密码登录,最后注销,观察现象。

import unittest
from selenium import webdriver
import timecoding = "utf-8"from selenium.webdriver.common.by import Byclass login(unittest.TestCase):def setUp(self):print("************setUp************")# self.driver,driver 就是全局变量了self.driver = webdriver.Chrome()self.url = "http://49.234.24.213:8080/studio/"self.driver.maximize_window()time.sleep(5)# tearDown:测试环境的清理def tearDown(self):print("************tearDown************")self.driver.quit()@unittest.skip("skipping")def test_aRegister(self):driver = self.driverurl = self.urldriver.get(url)time.sleep(2)driver.find_element(By.LINK_TEXT, "注册").click()driver.implicitly_wait(3)driver.find_element(By.NAME, "username").send_keys("测试1")driver.find_element(By.NAME, "password").send_keys("123")driver.find_element(By.TAG_NAME, "button").click()time.sleep(5)print("************注册成功************")def test_bLogin(self):driver = self.driverurl = self.urldriver.get(url)time.sleep(2)driver.find_element(By.LINK_TEXT, "登录").click()driver.implicitly_wait(5)driver.find_element(By.NAME, "username").send_keys("测试")driver.find_element(By.NAME, "password").send_keys("123")driver.find_element(By.TAG_NAME, "button").click()time.sleep(5)print("*********登录成功*********")def test_cQuit(self):driver = self.driverurl = self.urldriver.get(url)time.sleep(2)driver.find_element(By.LINK_TEXT, "注销").click()time.sleep(5)print("*********登录成功*********")if __name__ == "__main__":unittest.main(verbosity=2)

3.音频管理功能

因为音频管理必须登录后才能使用,所以先观察未登录时点击上传音频、录制音频、音频列表的结果,再观察已登录时点击上传音频、录制音频、音频列表的结果。

from selenium import webdriver
import unittest
import timecoding = "utf-8"from selenium.webdriver.common.by import By# 登录之后新建专辑功能class uploadAndRecordTrack(unittest.TestCase):# 测试固件# setUp:测试环境初始化def setUp(self):print("************setUp************")# self.driver,driver 就是全局变量了self.driver = webdriver.Chrome()self.url = "http://49.234.24.213:8080/studio/user/login.html"self.driver.maximize_window()time.sleep(5)# tearDown:测试环境的清理def tearDown(self):print("************tearDown************")self.driver.quit()# 未登录时音频列表页面def test_aListNoLogin(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.XPATH, "/html/body/div[1]/div[2]/a[3]").click()time.sleep(3)print("************未登录的音频列表页面************")# 未登录时上传音频页面def test_bUploadTrackNoLogin(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.LINK_TEXT, "上传").click()time.sleep(3)print("************未登录的上传音频页面************")# 未登录时录制音频页面def test_cRecordTrackNoLogin(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.LINK_TEXT, "录制").click()time.sleep(3)print("************未登录的录制音频页面************")# 已登陆音频列表页面def test_dListWithLogin(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.NAME, "username").send_keys("测试")time.sleep(2)driver.find_element(By.NAME, "password").send_keys("123")time.sleep(2)driver.find_element(By.TAG_NAME, "button").click()time.sleep(3)print("************登录成功************")driver.find_element(By.XPATH, "/html/body/div[1]/div[2]/a[3]").click()time.sleep(3)print("************当前用户音频列表************")# 已登陆上传音频页面def test_eUploadTrack(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.NAME, "username").send_keys("测试")time.sleep(2)driver.find_element(By.NAME, "password").send_keys("123")time.sleep(2)driver.find_element(By.TAG_NAME, "button").click()time.sleep(3)print("************登录成功************")driver.find_element(By.XPATH, "/html/body/div[1]/div[2]/a[1]").click()time.sleep(3)print("************当前用户要上传音频************")a = driver.find_element(By.CSS_SELECTOR, '.main > form:nth-child(1) > input:nth-child(2)')driver.execute_script("arguments[0].click();", a)# driver.find_element(By.XPATH,"/html/body/div[3]/form/input[2]").click();print("************选择音频************")time.sleep(3)# 已登陆录制音频页面@unittest.skip("skipping")def test_fRecordTrack(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.NAME, "username").send_keys("测试")time.sleep(2)driver.find_element(By.NAME, "password").send_keys("123")time.sleep(2)driver.find_element(By.TAG_NAME, "button").click()time.sleep(3)print("************登录成功************")driver.find_element(By.LINK_TEXT, "录制").click()time.sleep(3)print("************准备录制************")a = driver.find_element(By.CSS_SELECTOR, '#authorize')driver.execute_script("arguments[0].click();", a)# 定位弹出框/获得弹出框的操作句柄time.sleep(3)alert = driver.switch_to.alerttime.sleep(3)# 关闭alertalert.accept()print("************授权啦************")alert = driver.switch_to.alerttime.sleep(3)# 关闭alertalert.accept()if __name__ == "__main__":unittest.main(verbosity=2)

4.专辑管理功能

跟音频管理类似,先观察未登录时点击专辑列表和新建专辑的效果,再观察已登录时点击专辑列表和新建专辑的效果。

from selenium import webdriver
import unittest
import timecoding = "utf-8"from selenium.webdriver.common.by import By# 登录之后新建专辑功能class listAndCreateAlbum(unittest.TestCase):# 测试固件# setUp:测试环境初始化def setUp(self):print("************setUp************")# self.driver,driver 就是全局变量了self.driver = webdriver.Chrome()self.url = "http://49.234.24.213:8080/studio/user/login.html"self.driver.maximize_window()time.sleep(5)# tearDown:测试环境的清理def tearDown(self):print("************tearDown************")self.driver.quit()# 未登录时专辑列表页面def test_aListNoLogin(self):driver = self.driverurl = self.urldriver.get(url)a = driver.find_element(By.CSS_SELECTOR, 'div.entry-point:nth-child(5) > a:nth-child(3)')driver.execute_script("arguments[0].click();", a)time.sleep(3)print("************未登录的列表页面************")# 未登录时新建页面def test_bCreateAlbumNoLogin(self):driver = self.driverurl = self.urldriver.get(url)# driver.find_element(By.LINK_TEXT,"新建").click()a = driver.find_element(By.CSS_SELECTOR, 'body > div.sidebar > div:nth-child(5) > a:nth-child(2)')driver.execute_script("arguments[0].click();", a)time.sleep(3)print("************未登录的新建页面************")# 已登录专辑列表页面def test_cListAlbum(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.NAME, "username").send_keys("测试")time.sleep(2)driver.find_element(By.NAME, "password").send_keys("123")time.sleep(2)driver.find_element(By.TAG_NAME, "button").click()time.sleep(3)print("************登录成功************")time.sleep(3)a = driver.find_element(By.CSS_SELECTOR, 'div.entry-point:nth-child(5) > a:nth-child(3)')driver.execute_script("arguments[0].click();", a)# driver.find_element(By.XPATH,"/html/body/div[1]/div[3]/a[2]").click()time.sleep(5)print("************该用户的专辑列表************")# 已登录新建专辑页面@unittest.skip("skipping")def test_dCreateAlbum(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.NAME, "username").send_keys("测试")time.sleep(2)driver.find_element(By.NAME, "password").send_keys("123")time.sleep(2)driver.find_element(By.TAG_NAME, "button").click()time.sleep(3)print("************登录成功************")a = driver.find_element(By.CSS_SELECTOR, 'body > div.sidebar > div:nth-child(5) > a:nth-child(2)')driver.execute_script("arguments[0].click();", a)time.sleep(5)print("************到了新建页面了************")driver.find_element(By.NAME, "title").send_keys("这是标题")driver.find_element(By.NAME, "cover").send_keys("https://img0.baidu.com/it/u=164187230,3971185330&fm=253&fmt=auto&app=138&f=JPEG?w=525&h=500")driver.find_element(By.TAG_NAME, "button").click()time.sleep(3)print("************新专辑创建成功************")#登陆后给专辑绑定音频def test_eBindTrack(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.NAME, "username").send_keys("测试")time.sleep(2)driver.find_element(By.NAME, "password").send_keys("123")time.sleep(2)driver.find_element(By.TAG_NAME, "button").click()time.sleep(3)print("************登录成功************")a = driver.find_element(By.CSS_SELECTOR, 'div.entry-point:nth-child(5) > a:nth-child(3)')driver.execute_script("arguments[0].click();", a)print("************该用户的专辑列表************")time.sleep(3)# a = driver.find_element(By.CSS_SELECTOR, 'tr.empty: nth - child(1) > td:nth - child(2) > a: nth - child(1)')# driver.execute_script("arguments[0].click();", a)driver.find_element(By.XPATH,"/html/body/div[3]/div/table/tbody/tr[1]/td[2]/a").click()print("************到绑定页面了************")time.sleep(3)driver.find_element(By.ID,"add").click()# driver.implicitly_wait(3)time.sleep(3)print("************选择音频************")if __name__ == "__main__":unittest.main(verbosity=2)

5.组合所有的测试用例

把测试脚本中所有的测试用例都添加到测试套件中。

def creatSuit():# 把一个测试脚本中所有的测试用例都添加到suit中suit = unittest.TestSuite()suit.addTest(unittest.makeSuite(publishedAlbumList.publishedAlbumList))suit.addTest(unittest.makeSuite(login.login))suit.addTest(unittest.makeSuite(uploadAndRecordTrack.uploadAndRecordTrack))suit.addTest(unittest.makeSuite(listAndCreatAlbum.listAndCreateAlbum))return suit

6.生成测试报告

测试报告:点击查看测试报告

import HTMLTestRunner
import sys
import unittest
import time
import osfrom myTest import publishedAlbumList, login, uploadAndRecordTrack, listAndCreatAlbumdef creatSuit():# 把一个测试脚本中所有的测试用例都添加到suit中suit = unittest.TestSuite()suit.addTest(unittest.makeSuite(publishedAlbumList.publishedAlbumList))suit.addTest(unittest.makeSuite(login.login))suit.addTest(unittest.makeSuite(uploadAndRecordTrack.uploadAndRecordTrack))suit.addTest(unittest.makeSuite(listAndCreatAlbum.listAndCreateAlbum))return suitif __name__ == "__main__":# 文件夹要创建在哪里curpath = sys.path[0]print(sys.path)print(sys.path[0])# 1,创建文件夹,创建的这个文件夹干什么if not os.path.exists(curpath + '/resultreport'):os.makedirs(curpath + '/resultreport')# 2,文件夹的命名,不能让名称重复# 时间  时分秒 ——》名称绝对不会重复now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))print(now)print(time.time())print(time.localtime(time.time()))# 文件名filename = curpath + '/resultreport/' + now + 'resultreport.html'with open(filename, 'wb') as fp:runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u"测试报告",description=u"用例执行情况", verbosity=2)suit = creatSuit()# verbersity= 0, 1, 2runner.run(suit)

四、性能测试

使用 LoadRunner 对该项目的登录后创建专辑功能进行了性能测试。
并发用户数量:2;
运行时间:3分钟;
实际运行时间:3分52秒,因为还包含了线程初始化和销毁的时间。
统计信息:
统计信息
如图所示,本次测试运行的最大并发数为2,总吞吐量为11,333,978字节,平均每秒的吞吐量为48,643,682字节,总的请求数为1,413,平均每秒的请求为6.064,对于吞吐量,单位时间内吞吐量越大,说明服务器的处理能越好,而请求数仅表示客户端向服务器发出的请求数,与吞吐量一般是成正比关系。



http://chatgpt.dhexx.cn/article/lQboeBfh.shtml

相关文章

性能测试项目案例

一、项目介绍与部署 1.1微商城功能介绍 轻商城是一个电商项目,需要综合评估各个项目各个接口的功能,给出优化建议; 功能框架 前台:首页、商品页详情、加入购物车、订单、支付、团购、优惠券;后台:商品管…

项目测试报告

图书管理系统测试报告 一、测试概述 1.编写目的 本报告为图书管理系统阶段测试的总结,目的在于考察软件的功能和缺陷,尽可能多的发现软件的缺陷和漏洞。 2.项目介绍 为了方便学校师生管理或借阅图书而开发出的一个图书管理系统,在Windows环境下创建…

开源测试项目

在如今开源的时代,我们就不要再闭门造车了,热烈的拥抱开源吧!本文针对性能测试、Web UI 测试、APP测试、数据库测试、接口测试、单元测试等方面,为大家整理了github或码云上优秀的自动化测试开源项目,希望能给大家带来…

关于项目的测试

文章目录 前言(测试的相关知识)一、需求分析二、测试设计三、测试计划1.功能测试:1).题目展示及提交2).异常情况3).网络测试 2.兼容性测试:1).各种浏览器器访问:2).同一浏览器不同版本3).不同的操作系统: 3…

【2023必看】17个值得关注的测试开源项目大盘点

目录 引言 项目汇总 值得关注的项目 总结 引言 在软件测试领域,开源项目已经成为了一个重要的趋势。 作为测试人员,我们可以通过参与或关注这些开源项目,不仅可以学习到先进的测试思想、技术和工具,还可以积极参与社区建设&…

测试自学人必看:软件测试如何找测试项目?

目录 前言 方法一:自己找一些开源的开发/测试项目 方法二:从一些线上课程里找开发项目,付费和免费的都可以 方法三:报测试培训班,机构会提供测试项目。 结语 前言 测试新手不知道上哪找测试项目,这应…

【Linux 下】 信号量

文章目录 【Linux 下】 信号量信号量概念信号量操作初始化和销毁P()操作V()操作理解PV操作 基于信号量与环形队列实现的CS模型基于信号量和环形队列实现的生产者与消费者模型 【Linux 下】 信号量 信号量概念 信号量(…

Linux 信号量

信号量 信号量信号量的定义信号量理论例子Linux信号量机制使用信号量 信号量 信号量:用于管理对资源的访问。 (1) 当我们编写的程序使用了线程时,不管它是运行在多用户系统上、多进程系统上,还是运行在多用户多进程系统上,我们通…

Linux内核信号量:二值信号量/互斥信号量,计数信号量,读写信号量

《semaphore信号量:一个简单的示例程序》用户态程序 目录 概念 应用场景 使用方法 内核信号量的构成 信号量的API 初始化 PV操作 获取信号量(P) 释放内核信号量(V) 补充 内核信号量的使用例程 场景1 场景…

Linux系统中信号量的基本使用方法

大家好,今天主要和大家聊一聊,如何使用信号量的方法。 目录 第一: 父子进程相隔1s报数一次 第二:利用信号量实现父子进程通信 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施&#…

信号量【Linux】

文章目录 1. POSIX信号量1.1 引入1.2 概念1.3 PV原语(原理)1.4 相关接口 2. 二进制信号量3. 基于环形队列的生产消费模式3.1 介绍3.2 为什么要使用环形队列3.3 环形队列的作用3.4 实现互斥和同步两个信号量框架生产和消费的逻辑完善环形队列1信号量完善环…

Linux信号量操作

信号量简介: 在对于临界区资源管理的过程中,多个程序同时访问一个共享资源经常容易引发一系列问题:如死锁,结果不唯一等等,在1965年,由荷兰科学家E.W.Dijkstra提出了一种新的进程同步工具,信号…

【关于Linux中----信号量及其使用场景】

文章目录 一、解释信号量1.1 概念的引入1.2 信号量操作和使用接口 二、信号量使用场景2.1 引入环形队列&&生产消费问题2.2 代码实现2.3 对于多生产多消费的情况2.4 申请信号量和加锁的顺序问题2.5 多生产多消费的意义 一、解释信号量 1.1 概念的引入 我们知道&#x…

linux(信号量)

信号量 几个基本概念临界资源临界区原子性互斥 信号量后台进程前台进程 信号储存信号处理信号(信号捕捉) 发送信号1、键盘产生:2、系统调用接口发送信号3、由软件条件产生信号4、硬件异常发送信号 内核中的信号量**信号量在内核中的数据结构****信号集操作函数** 信…

Linux--信号量

1.信号量的定义: 信号量是一个特殊的变量,一般取正数值。它的值代表允许访问的资源数目, 获取资源时,需要对信号量的值进行原子减一,该操作被称为p操作。当信号量值为0时,代表没有资源可用,p操作会阻塞。释…

【Linux】Linux的信号量集

所谓信号量集,就是由多个信号量组成的一个数组。作为一个整体,信号量集中的所有信号量使用同一个等待队列。Linux的信号量集为进程请求多个资源创造了条件。Linux规定,当进程的一个操作需要多个共享资源时,如果只成功获得了其中的…

linux信号量简介

一、什么是信号量 为了防止多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种访问机制,它可以通过生成并使用令牌来授权,在同一时刻只能有一个线程访问代码的临界区域。 临界区域是指执行数据更新的代码需要独占式地执行。而信…

Linux下信号量使用总结

目录 1.Linux下信号量简介 2.POSIX信号量 2.1 无名信号量 2.2 有名信号量 3.System V信号量 1.Linux下信号量简介 信号量是解决进程之间的同步与互斥的IPC机制,互斥与同步关系存在的症结在于临界资源。 临界资源是在同一个时刻只容许有限个(一般只有…

Linux信号量详解

Linux信号量详解 1.什么是信号量信号量是一种特殊的变量,访问具有原子性。只允许对它进行两个操作:1)等待信号量当信号量值为0时,程序等待;当信号量值大于0时,信号量减1,程序继续运行。2)发送信号量将信号量…

Linux进程间通信—信号量

一、概述 进程间通信(interprocess communication,简称 IPC)指两个进程之间的通信。系统中的每一个进程都有各自的地址空间,并且相互独立、隔离,每个进程都处于自己的地址空间中。所以同一个进程的不同模块譬如不同的函…