我的项目测试
文章目录
前言
自己写了一个项目,“一起听书吧”,该项目是一个听书网站,未注册用户访问时直接进入专辑列表页面(首页),可以看到所 有已发布专辑,并选择某个专辑播放音频或音频切换,也可以进行账号注册,但是不支持上传音频、 录制音频、管理专辑等操作。已注册用户访问时也是进入首页,可以点击进入”创作中心“ 进行登录, 登录后就可以上传音频、录制音频、查看个人音频列表、创建专辑、为专辑绑定音频、查看专辑列表、 上下架专辑等……
项目 URL:点击开始使用项目
一、单元测试
单元测试是对软件基本组成单元进行的测试,而且软件单元是在与程序的其他部分相隔离的情况下进行独立的测试。其目标确保单元模块能被正确地编码、保证代码在结构上可靠且健全。单元测试可以尽早发现错误、发现问题比较容易、修正问题比较容易。
在本项目中,我采用JUnit单元测试框架进行单元测试。鉴于项目比较简单、大多数处理逻辑都是一些增删查改,所以我的单元测试写的比较少。
class TrackRepoTest {
private TrackRepo trackRepo=new TrackRepo();
@Test
void selectCountByUid() {
UserVO currentUser=new UserVO(3,"吕倩");
int count=trackRepo.selectCountByUid(currentUser);
//15:预期值
//count:实际值
//message:预期值与实际值不相等时,以异常形式输出 message
Assertions.assertEquals(15,count,"该用户的专辑数量查找错误");
}
}
这个方法是根据当前登录用户(currentUser) 去查找该用户的专辑数量,因为我可以从数据库中得到该用户的专辑数量,所以只需要调用被测方法得到专辑数量,然后利用断言,即调用Assertions.assertEquals()方法进行实际值和预期值的比较,如果实际值和预期值相等,说明被测方法是没有问题的,否则就赶紧改改代码吧🤗
class AlbumRepoTest {
AlbumRepo albumRepo=new AlbumRepo();
@Test
void 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 time
coding = "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.driver
url = self.url
driver.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 time
coding = "utf-8"
from selenium.webdriver.common.by import By
class 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.driver
url = self.url
driver.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.driver
url = self.url
driver.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.driver
url = self.url
driver.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 time
coding = "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.driver
url = self.url
driver.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.driver
url = self.url
driver.get(url)
driver.find_element(By.LINK_TEXT, "上传").click()
time.sleep(3)
print("************未登录的上传音频页面************")
# 未登录时录制音频页面
def test_cRecordTrackNoLogin(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element(By.LINK_TEXT, "录制").click()
time.sleep(3)
print("************未登录的录制音频页面************")
# 已登陆音频列表页面
def test_dListWithLogin(self):
driver = self.driver
url = self.url
driver.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.driver
url = self.url
driver.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.driver
url = self.url
driver.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.alert
time.sleep(3)
# 关闭alert
alert.accept()
print("************授权啦************")
alert = driver.switch_to.alert
time.sleep(3)
# 关闭alert
alert.accept()
if __name__ == "__main__":
unittest.main(verbosity=2)
4.专辑管理功能
跟音频管理类似,先观察未登录时点击专辑列表和新建专辑的效果,再观察已登录时点击专辑列表和新建专辑的效果。
from selenium import webdriver
import unittest
import time
coding = "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.driver
url = self.url
driver.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.driver
url = self.url
driver.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.driver
url = self.url
driver.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.driver
url = self.url
driver.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.driver
url = self.url
driver.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 os
from myTest import publishedAlbumList, login, uploadAndRecordTrack, listAndCreatAlbum
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
if __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, 2
runner.run(suit)
四、性能测试
使用 LoadRunner 对该项目的登录后创建专辑功能进行了性能测试。
并发用户数量:2;
运行时间:3分钟;
实际运行时间:3分52秒,因为还包含了线程初始化和销毁的时间。
统计信息:
如图所示,本次测试运行的最大并发数为2,总吞吐量为11,333,978字节,平均每秒的吞吐量为48,643,682字节,总的请求数为1,413,平均每秒的请求为6.064,对于吞吐量,单位时间内吞吐量越大,说明服务器的处理能越好,而请求数仅表示客户端向服务器发出的请求数,与吞吐量一般是成正比关系。