当前位置: 首页 > news >正文

论坛系统测试报告

1.项目背景

本项目是基于 SSM 框架(Spring、Spring MVC、MyBatis) 开发的 论坛系统,包括 用户注册、登录、帖子发布、编辑、删除、查看 等功能,同时提供 帖子列表页和详情页 供用户浏览论坛内容。

用户登录后可以 查看自己和其他用户的帖子,并通过系统 记录帖子发布时间、标题、作者信息。论坛支持 用户评论、私信交流、帖子点赞等社交互动功能,提升用户体验。

为了确保系统的稳定性和功能完整性,项目采用 Selenium 自动化测试 进行功能验证,测试内容涵盖:

  • 用户注册与登录:测试不同输入情况下的账号验证逻辑

  • 帖子列表展示:确保帖子加载、排序和分页功能正常

  • 用户信息校验:验证用户个人资料、修改信息的功能

  • 帖子管理:测试帖子发布、编辑、删除是否符合预期

  • 帖子详情页:检查帖子的内容是否正确加载,包括评论、点赞等互动功能

  • 搜索功能:验证用户输入关键词后,搜索结果是否匹配

本项目通过自动化测试覆盖核心功能,确保论坛系统在不同用户操作和高并发场景下的稳定性和可靠性,同时减少人工测试成本,提高测试效率。

2.测试内容

2.1.功能测试

2.1.1.编写测试用例  

2.1.2.执行测试用例
登录测试
  • (a)界面展示

  • (b)输入正确的账号和密码(如:账号 qiyu,密码 123456
    • 预期结果:成功登录,并跳转至主页。
    • 实际结果:正常
  • (c)输入错误的账号和密码(如:账号 q,密码 1234
    • 预期结果:登录失败,跳出提示
    • 实际结果:正常
  • (d)只输入密码(如:密码 123456
    • 预期结果:登录失败,提示密码不可为空
    • 实际结果:正常
  • (b)只输入账号(如:账号 qiyu
    • 预期结果:登录失败,提示账号不可为空
    • 实际结果:正常
  • (e)不输入账号和密码
    • 预期结果:登录失败,提示账号密码不可为空
    • 实际结果:显示正确
个人中心页测试
  • (a)界面展示

  • (b)测试各各输入框
    • 预期结果:能正常输入修改
    • 实际结果:头像可上传但无法修改,其他正常
帖子编辑页测试
  • (a)界面展示
  • (b)测试板块
    • 预期结果:默认是java和能正常修改
    • 实际结果:正常

  • (c)测试标题框和文字框能否正常输入修改
    • 预期结果:能否正常输入修改
    • 实际结果:修改正常
  • (d)测试能否正常发布
    • 预期结果:发布成功
    • 实际结果
帖子详细页测试
  • (a)界面展示

  • (b)测试菜单栏搜索框
    • 预期结果:正常输入,正常搜索
    • 实际结果:正常输入,但搜索功能无法使用
  • (c)测试菜单栏日间夜间切换按钮
    • 预期结果:可正常切换
    • 实际结果:正常,但会自动切回主页
  • (d)测试菜单栏信息按钮
    • 预期结果:可弹出消息页
    • 实际结果:正常
  • (e)测试个人信息
    • 预期结果:能与登录用户对应
    • 实际结果:对应
  • (f)测试点赞按钮
    • 预期结果:弹窗提示,点赞数量增加
    • 实际结果:成功
  • (g)测试评论区
    • 预期结果:可发送评论
    • 实际结果:正常发送,但在夜间模式输入框输入的文字不可见
  • (h)测试发私信按钮
    • 预期结果:可弹出回复私信页,可正常发送
    • 实际结果:正常
回复私信页测试
  • (a)界面展示
  • (b)测试输入框
    • 预期结果:能正常输入修改
    • 实际结果:正常
  • (c)测试能否正常发送
    • 预期结果:可正常发送
    • 实际结果:正常
首页测试
  • (a)界面展示
  • (b)测试各板块跳转
    • 预期结果:可正常跳转
    • 实际结果:可正常跳转,但缺失部分板块名称
  • (c)测试帖子列表
    • 预期结果:点击进入帖子详细页
    • 实际结果:正常
我的帖子页测试
  • (a)界面展示
  • (b)检查页面信息
    • 预期结果:能与登录用户对应
    • 实际结果:可对应
注册页测试
  • (a)界面展示
  • (b)正常注册测试
    • 预期结果:注册完跳转至登录页
    • 实际结果:正常
  • (c)异常注册测试
    • 预期结果:未输入或两次密码不一致时提示
    • 实际结果:正常

2.2 使用 Selenium 进行 Web 自动化测试(Python)

2.2.1 安装 WebDriverManager 和 Selenium

WebDriverManager 是用于管理 Web 驱动程序的工具,在进行 Selenium 测试时,浏览器需要对应的 WebDriver 进行控制和操作。WebDriverManager 能够自动检测本地浏览器版本并下载匹配的驱动程序(如 ChromeDriver、FirefoxDriver 等),避免手动下载和配置的繁琐过程,提高测试效率和稳定性。


2.2.2 创建测试项目
  1. 在项目中打开 File → Settings,进入设置界面。

  2. 在“Project: 当前项目名”下,检查是否已安装 selenium 和 webdriver-manager 依赖。

  3. 若未安装,可使用以下命令进行安装:

pip install selenium webdriver-manager
公共工具(Utils.py)

测试目标

  • 提供 WebDriver 实例,供各测试脚本调用。

  • 统一管理浏览器驱动,支持截图功能。

测试步骤

  1. 在 Utils.py 中定义 BlogDriver 类,初始化 Edge 浏览器驱动。

  2. 提供 get_driver() 方法,返回 WebDriver 实例。

  3. 提供 screenshot() 方法,支持测试过程中截图。

import datetime
import os
import sys
from webdriver_manager.microsoft import EdgeChromiumDriverManager
from selenium import webdriver
from selenium.webdriver.edge.service import Serviceclass Driver:driver = Nonedef __init__(self):"""初始化WebDriver并启动浏览器"""options = webdriver.EdgeOptions()options.page_load_strategy = 'eager'# options.add_argument('-headless')  # 启动无界面模式edge_driver_path = EdgeChromiumDriverManager().install()self.driver = webdriver.Edge(service=Service(edge_driver_path), options=options)def getScreenShot(self):"""保存当前页面的截图到指定目录"""dirname = datetime.datetime.now().strftime('%Y-%m-%d')screenshot_dir = os.path.join(os.path.dirname(os.getcwd()), 'images', dirname)# 如果截图目录不存在,则创建if not os.path.exists(screenshot_dir):os.makedirs(screenshot_dir)# 根据方法名和时间戳生成唯一的文件名filename = sys._getframe().f_back.f_code.co_name + "-" + datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S') + ".png"# 保存截图screenshot_path = os.path.join(screenshot_dir, filename)self.driver.save_screenshot(screenshot_path)# 创建BlogDriver实例
BlogDriver = Driver()

登录页自动化测试(Login.py)

测试目标

  • 确保用户登录功能正常,包括不同输入组合的处理逻辑。

测试步骤

  1. 创建 Login.py,引入 Utils.py 及相关依赖。

  2. 定义 Login 类,管理登录页面的测试用例。

  3. 实现以下测试方法:

    • 正确登录测试:使用正确的用户名和密码进行登录,并验证登录成功。

    • 用户名/密码为空测试:测试用户名或密码为空时的登录提示。

    • 用户名/密码错误测试:输入错误的用户名或密码,检查是否拒绝登录。

    • 页面跳转测试:确保登录成功后跳转到主页。

执行方式

  • RunTest.py 中调用 Login 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.alert import Alertclass Login:url = ''driver = ''def __init__(self):# 初始化URL和driver,打开登录页面self.url = 'http://127.0.0.1:9580/sign-in.html'self.driver = Driver.driverself.driver.get(self.url)def _login(self, username, password):# 等待提交按钮可点击,输入用户名和密码,并点击登录按钮WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#submit')))self.driver.find_element(By.CSS_SELECTOR, '#username').clear()self.driver.find_element(By.CSS_SELECTOR, "#password").clear()self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys(username)self.driver.find_element(By.CSS_SELECTOR, "#password").send_keys(password)self.driver.find_element(By.CSS_SELECTOR,'#submit').click()def _verify_login_success(self):"""验证用户是否成功登录"""try:# 等待文章列表标题元素出现来验证是否登录成功WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#article_list_board_title')))except:pass# 确认登录后页面中存在文章列表标题assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title') is not Nonedef login_suc_test1(self):# 测试用户1的登录self._login('qiyu','123456')self._verify_login_success()Driver.getScreenShot()self.driver.back()def login_suc_test2(self):# 测试用户2的登录self._login('zhangsan','1234')self._verify_login_success()self.driver.back()def check_error_alert(self):# 检查错误提示是否出现try:WebDriverWait(self.driver,5).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div')))except:pass# 验证是否有错误提示assert self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div')def check_error_appear(self, username, password):# 验证错误提示是否在用户名或密码为空时出现if username == 'empty':try:WebDriverWait(self.driver, 5).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#signInForm > div.mb-3 > div')))except:pass# 验证用户名为空时是否出现错误提示assert self.driver.find_element(By.CSS_SELECTOR, '#signInForm > div.mb-3 > div')if password == 'empty':try:WebDriverWait(self.driver, 5).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#signInForm > div.mb-2 > div > div')))except:pass# 验证密码为空时是否出现错误提示assert self.driver.find_element(By.CSS_SELECTOR, '#signInForm > div.mb-2 > div > div')def test_login_empty_username_empty_password(self):"""测试用户名和密码为空时的登录行为"""self._login('', '')self.check_error_appear('empty','empty')self.driver.back()def test_login_empty_username_valid_password(self):"""测试用户名为空,密码有效时的登录行为"""self._login('', '1234')self.check_error_appear('empty','')self.driver.back()def test_login_empty_username_invalid_password(self):"""测试用户名为空,密码无效时的登录行为"""self._login('', '123')self.check_error_appear('empty','')self.driver.back()def test_login_invalid_username_empty_password(self):"""测试用户名无效,密码为空时的登录行为"""self._login('123', '')self.check_error_appear('','empty')self.driver.back()def test_login_valid_username_empty_password(self):"""测试用户名有效,密码为空时的登录行为"""self._login('zhangsan', '')self.check_error_appear('','empty')self.driver.back()def test_login_valid_username_invalid_password(self):"""测试用户名有效,密码无效时的登录行为"""self._login('zhangsan', '123')self.check_error_alert()self.driver.back()def test_login_invalid_username_valid_password(self):"""测试用户名无效,密码有效时的登录行为"""self._login('12312', '12334')self.check_error_alert()self.driver.back()def test_login_invalid_username_invalid_password(self):"""测试用户名无效,密码无效时的登录行为"""self._login('123', '123')self.check_error_alert()self.driver.back()
    

注册页自动化测试(Register.py)

测试目标

  • 确保用户注册功能正常,包括不同输入组合的处理逻辑。

测试步骤

  1. 创建 Register.py,引入 Utils.py 及相关依赖。

  2. 定义 Register 类,管理注册页面的测试用例。

  3. 实现以下测试方法:

    • 正确注册测试:填写完整有效信息,并检查注册成功后跳转到登录页。

    • 用户名/密码/昵称为空测试:测试部分字段为空时,系统是否提示错误。

    • 密码不匹配测试:测试密码与确认密码不一致的情况。

    • 未勾选用户协议测试:检查未勾选协议时,是否阻止注册。

执行方式

  • RunTest.py 中调用 Register 类执行测试。

    import time
    import random
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ECclass Register:driver = ''url = ''def __init__(self):self.url = 'http://127.0.0.1:9580/sign-up.html'self.driver = Driver.driverself.driver.get(self.url)def test_valid_inputs_agree_terms(self):"""测试:所有输入均有效,并且同意条款"""random_name = random.randint(100000, 999999)random_nickname = random.randint(100000, 999999)random_password = random.randint(100000, 999999)# 等待输入框加载WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#username')))# 填写表单self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys(random_name)self.driver.find_element(By.CSS_SELECTOR, '#nickname').send_keys(random_nickname)self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys(random_password)self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys(random_password)self.driver.find_element(By.CSS_SELECTOR, '#policy').click()self.driver.find_element(By.CSS_SELECTOR,'#submit').click()# 等待页面跳转WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2')))# 确认跳转到 "用户登录" 页面assert self.driver.find_element(By.CSS_SELECTOR,'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2').text == '用户登录'# 登录测试self.driver.find_element(By.CSS_SELECTOR,'#username').send_keys(random_name)self.driver.find_element(By.CSS_SELECTOR,'#password').send_keys(random_password)self.driver.find_element(By.CSS_SELECTOR,'#submit').click()try:WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页")except:passassert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'def test_valid_username_empty_others_disagree_terms(self):"""测试:用户名有效,其他字段为空,且不同意条款"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#username')))self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys('random_name')# 点击提交按钮WebDriverWait(self.driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit')))self.driver.find_element(By.CSS_SELECTOR, '#submit').click()# 检查错误提示WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div')))WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(4) > div')))WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div')))assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")def test_empty_username_valid_nickname_mixed_passwords_disagree_terms(self):"""测试:用户名为空,昵称有效,密码和确认密码不匹配,且不同意条款"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#nickname')))self.driver.find_element(By.CSS_SELECTOR, '#nickname').send_keys('random_nickname')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#password')))self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#passwordRepeat')))self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys('random_passwordRepeat')WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit')))self.driver.find_element(By.CSS_SELECTOR, '#submit').click()# 等待错误信息WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(2) > div')))WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div')))assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")def test_empty_username_nickname_valid_password_agree_terms(self):"""测试:用户名和昵称为空,密码有效,且同意条款"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#password')))self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#passwordRepeat')))self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys('random_password')self.driver.find_element(By.CSS_SELECTOR, '#policy').click()WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit')))self.driver.find_element(By.CSS_SELECTOR, '#submit').click()# 检查是否出现错误信息WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(2) > div')))WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div')))assert "is-valid" in self.driver.find_element(By.ID, "policy").get_attribute("class")def test_valid_inputs_missing_confirm_password_disagree_terms(self):"""测试:所有输入有效,但缺少确认密码,且不同意条款"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#username')))self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys('random_name')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#nickname')))self.driver.find_element(By.CSS_SELECTOR, '#nickname').send_keys('random_nickname')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#password')))self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit')))self.driver.find_element(By.CSS_SELECTOR, '#submit').click()# 检查是否出现错误信息WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div')))assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")def test_valid_username_empty_nickname_password_confirmed_agree_terms(self):"""测试:用户名有效,昵称为空,密码和确认密码匹配,且同意条款"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#username')))self.driver.find_element(By.CSS_SELECTOR, '#username').send_keys('random_name')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#password')))self.driver.find_element(By.CSS_SELECTOR, '#password').send_keys('random_password')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#passwordRepeat')))self.driver.find_element(By.CSS_SELECTOR, '#passwordRepeat').send_keys('random_password')self.driver.find_element(By.CSS_SELECTOR, '#policy').click()WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit')))self.driver.find_element(By.CSS_SELECTOR, '#submit').click()# 检查是否出现错误信息WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div')))assert "is-valid" in self.driver.find_element(By.ID, "policy").get_attribute("class")def test_invalid_inputs_disagree_terms(self):"""测试:所有输入均无效,并且不同意条款"""WebDriverWait(self.driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#submit')))self.driver.find_element(By.CSS_SELECTOR, '#submit').click()# 确保所有字段都显示错误WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(2) > div')))WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(3) > div')))WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(4) > div')))WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#signUpForm > div > div:nth-child(5) > div')))assert "is-invalid" in self.driver.find_element(By.ID, "policy").get_attribute("class")

个人主页自动化测试(PersonalHomepage.py)

测试目标

  • 确保个人主页各功能正常,包括修改个人信息、头像、密码等。

测试步骤

  1. 创建 PersonalHomepage.py,引入 Utils.py 及相关依赖。

  2. 定义 PersonalHomepage 类,管理个人主页的测试用例。

  3. 实现以下测试方法:

    • 切换页面测试:测试不同版块的切换功能,确保跳转正确。

    • 修改头像测试:检查头像上传功能是否正常。

    • 修改昵称测试:输入新的昵称并保存,验证是否生效。

    • 修改邮箱/手机号测试:更改邮箱或手机号,并检查更新后的信息。

    • 修改个人简介测试:输入新简介并保存,检查是否成功。

    • 修改密码测试:更改密码并使用新密码重新登录。

执行方式

  • RunTest.py 中调用 PersonalHomepage 类执行测试。

    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from pywinauto import Application
    from cases import Loginclass PersonalHomepage:url = ''driver = ''def __init__(self):# 初始化URL和driver,打开首页self.url = 'http://127.0.0.1:9580/index.html'self.driver = Driver.driverself.driver.get(self.url)# 等待页面加载完毕并确保头像元素可见WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#index_nav_avatar')))# 点击头像,进入个人资料设置页面self.driver.find_element(By.CSS_SELECTOR,'#index_nav_avatar').click()# 等待个人设置按钮可点击,并点击进入WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#index_user_settings')))self.driver.find_element(By.CSS_SELECTOR,'#index_user_settings').click()def test_switch_section(self):"""测试不同版块的切换功能"""try:# 等待“最新回复”板块加载,确保初始状态正确WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复")except:pass  # 忽略异常,继续执行# 断言当前版块为“最新回复”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"# 切换到首页WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()try:# 等待首页加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页")except:pass  # 忽略异常# 断言当前版块为“首页”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'# 切换到“Java”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()try:# 等待“Java”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java")except:pass# 断言当前版块为“Java”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'# 切换到“C++”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()try:# 等待“C++”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++")except:pass# 断言当前版块为“C++”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'# 切换到“MySQL”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()try:# 等待“MySQL”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL")except:pass# 断言当前版块为“MySQL”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'def test_search_input(self):"""测试搜索框输入功能"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(123)# 断言输入的值是否正确assert self.driver.find_element(By.CSS_SELECTOR,"body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute("value") == '123'def test_toggle_day_night_mode(self):"""测试日间/夜间模式切换"""WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg')))# 断言初始模式为日间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'# 切换到夜间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg')))# 断言模式已切换为夜间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'# 切换回日间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()def test_message_button(self):"""测试消息按钮是否可点击并弹出消息面板"""WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')def test_user_profile(self):"""测试用户个人信息是否正确显示"""self.driver.fullscreen_window()WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'def test_change_avatar(self):  # 头像修改测试# 等待并点击“更换头像”按钮WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div.row.align-items-center > div:nth-child(2) > a')))self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div.row.align-items-center > div:nth-child(2) > a').click()# 连接到“打开”窗口app = Application().connect(title_re='打开', timeout=1)  # 连接到 "打开" 窗口dlg = app.window(title_re="打开")  # 获取窗口assert dlg.existdlg.close()def test_nickname_field(self):  # 昵称栏测试random_number = random.randint(100, 999)# 等待昵称输入框并进行操作WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#setting_input_nickname')))nickname = self.driver.find_element(By.CSS_SELECTOR,'#setting_input_nickname')nickname.clear()nickname.send_keys(random_number)self.driver.find_element(By.CSS_SELECTOR,'#setting_submit_nickname').click()# 检查提示信息是否存在try:WebDriverWait(self.driver,5).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div')))except:passassert self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div').text# 恢复为默认的“zhangsan”昵称nickname.clear()nickname.send_keys('zhangsan')self.driver.find_element(By.CSS_SELECTOR,'#setting_submit_nickname').click()def test_email_field(self):  # 邮箱栏测试random_number = random.randint(100000, 999999)# 等待邮箱输入框并进行操作WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#setting_input_email')))email = self.driver.find_element(By.CSS_SELECTOR, '#setting_input_email')email.clear()email.send_keys(f'{random_number}qq.com')self.driver.find_element(By.CSS_SELECTOR, '#setting_submit_email').click()# 检查提示信息是否存在try:WebDriverWait(self.driver, 5).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')))except:passassert self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')def test_phone_number_field(self):  # 电话号码栏测试random_number = random.randint(10000000000, 99999999999)# 等待并操作电话号码输入框WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#setting_input_phoneNum')))phone = self.driver.find_element(By.CSS_SELECTOR, '#setting_input_phoneNum')phone.clear()phone.send_keys(random_number)self.driver.find_element(By.CSS_SELECTOR, '#setting_submit_phoneNum').click()# 检查提示信息是否存在try:WebDriverWait(self.driver, 5).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')))except:passassert self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')def test_bio_field(self):  # 个人简介栏测试random_number = random.randint(10000000000, 99999999999)# 等待并操作个人简介输入框WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_textarea_remark')))bio = self.driver.find_element(By.CSS_SELECTOR, '#settings_textarea_remark')# 滚动页面使元素可见self.driver.execute_script("arguments[0].scrollIntoView();", bio)time.sleep(0.5)bio.clear()bio.send_keys(random_number)self.driver.find_element(By.CSS_SELECTOR, '#settings_submit_remark').click()# 检查提示信息是否存在try:WebDriverWait(self.driver, 5).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')))except:passassert self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')def test_change_password(self):  # 修改密码栏测试random_number = random.randint(100, 999)print(f'random_password:{random_number}')# 等待并操作旧密码、新密码、确认新密码输入框WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_input_oldPassword')))oldpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_oldPassword')self.driver.execute_script("arguments[0].scrollIntoView();", oldpassword)oldpassword.clear()oldpassword.send_keys(1234)newpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_newPassword')self.driver.execute_script("arguments[0].scrollIntoView();", newpassword)newpassword.clear()newpassword.send_keys(random_number)cnewpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_passwordRepeat')self.driver.execute_script("arguments[0].scrollIntoView();", cnewpassword)cnewpassword.clear()cnewpassword.send_keys(random_number)element = self.driver.find_element(By.CSS_SELECTOR, '#settings_submit_password')self.driver.execute_script("arguments[0].scrollIntoView();", element)# 提交修改密码WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_submit_password')))time.sleep(0.5)element.click()# 检查密码修改是否成功try:WebDriverWait(self.driver, 5).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2')))except:passassert self.driver.find_element(By.CSS_SELECTOR, 'body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2')# 使用新密码重新登录Login.Login()._login('zhangsan',f'{random_number}')WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#index_nav_avatar')))self.driver.find_element(By.CSS_SELECTOR, '#index_nav_avatar').click()WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#index_user_settings')))self.driver.find_element(By.CSS_SELECTOR, '#index_user_settings').click()WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_input_oldPassword')))oldpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_oldPassword')self.driver.execute_script("arguments[0].scrollIntoView();", oldpassword)oldpassword.clear()oldpassword.send_keys(random_number)newpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_newPassword')self.driver.execute_script("arguments[0].scrollIntoView();", newpassword)newpassword.clear()# 恢复密码为初始值newpassword.send_keys(1234)cnewpassword = self.driver.find_element(By.CSS_SELECTOR, '#settings_input_passwordRepeat')self.driver.execute_script("arguments[0].scrollIntoView();", cnewpassword)cnewpassword.clear()cnewpassword.send_keys(1234)element = self.driver.find_element(By.CSS_SELECTOR, '#settings_submit_password')self.driver.execute_script("arguments[0].scrollIntoView();", element)WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#settings_submit_password')))time.sleep(0.5)element.click()

帖子编辑页自动化测试(Edit.py)

测试目标

  • 确保帖子编辑页功能正常,包括输入标题、内容、板块选择及发布功能。

测试步骤

  1. 创建 Edit.py,引入 Utils.py 及相关依赖。

  2. 定义 Edit 类,管理帖子编辑页面的测试用例。

  3. 实现以下测试方法:

    • 内容框测试:检查帖子内容输入框是否正确加载。

    • 标题输入测试:输入标题并验证输入内容是否正确。

    • 板块选择测试:选择不同板块,并检查选择结果是否正确。

    • 发布测试:点击发布按钮并确保帖子成功发布并跳转到帖子列表页。

执行方式

  • RunTest.py 中调用 Edit 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import Selectclass Edit:driver = ''url = ''def __init__(self):# 初始化方法,打开指定的URLself.url = 'http://127.0.0.1:9580/index.html'self.driver = Driver.driverself.driver.get(self.url)WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post')))# 点击进入文章发布页面self.driver.find_element(By.CSS_SELECTOR, '#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post').click()def Content_Box(self):# 内容框测试,检查内容框是否存在WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre')))# 确认内容框是否已经加载self.driver.find_element(By.CSS_SELECTOR,'#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre')def Title_Bar(self):# 标题栏测试,输入并验证标题内容WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#article_post_title')))self.driver.find_element(By.CSS_SELECTOR,'#article_post_title').send_keys(1)assert self.driver.find_element(By.CSS_SELECTOR,'#article_post_title').get_attribute('value') == "1"def Plate_Selection(self):# 板块选择测试,检查板块选择器中的选项WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#article_post_borad')))select = Select(self.driver.find_element(By.CSS_SELECTOR,'#article_post_borad'))options = [option.text for option in select.options]# 验证板块选项是否正确assert 'C++' in optionsassert '前端技术' in optionsassert 'MySQL' in optionsassert '面试宝典' in optionsassert '经验分享' in optionsassert '招聘信息' in optionsassert '福利待遇' in optionsassert '灌水区' in optionsselect.select_by_visible_text('C++')assert select.first_selected_option.text == 'C++'def Release(self):# 发布测试,点击发布按钮并验证发布反馈WebDriverWait(self.driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#article_post_submit')))self.driver.execute_script("arguments[0].scrollIntoView();",self.driver.find_element(By.CSS_SELECTOR,'#article_post_submit'))time.sleep(0.5)self.driver.find_element(By.CSS_SELECTOR,'#article_post_submit').click()try:WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')))except:pass# 确认发布后的反馈消息出现assert self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div')def test_switch_section(self):"""测试不同版块的切换功能"""try:# 等待“最新回复”板块加载,确保初始状态正确WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复")except:pass  # 忽略异常,继续执行# 断言当前版块为“最新回复”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"# 切换到首页WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()try:# 等待首页加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页")except:pass  # 忽略异常# 断言当前版块为“首页”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'# 切换到“Java”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()try:# 等待“Java”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java")except:pass# 断言当前版块为“Java”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'# 切换到“C++”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()try:# 等待“C++”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++")except:pass# 断言当前版块为“C++”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'# 切换到“MySQL”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()try:# 等待“MySQL”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL")except:pass# 断言当前版块为“MySQL”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'def test_search_input(self):"""测试搜索框输入功能"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(123)# 断言输入的值是否正确assert self.driver.find_element(By.CSS_SELECTOR,"body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute("value") == '123'def test_toggle_day_night_mode(self):"""测试日间/夜间模式切换"""WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg')))# 断言初始模式为日间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'# 切换到夜间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg')))# 断言模式已切换为夜间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'# 切换回日间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()def test_message_button(self):"""测试消息按钮是否可点击并弹出消息面板"""WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')def test_user_profile(self):"""测试用户个人信息是否正确显示"""self.driver.fullscreen_window()WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

帖子详情页自动化测试(Detail.py)

测试目标

  • 确保帖子详情页功能正常,包括查看、评论、点赞等功能。

测试步骤

  1. 创建 Detail.py,引入 Utils.py 及相关依赖。

  2. 定义 Detail 类,管理帖子详情页的测试用例。

  3. 实现以下测试方法:

    • 查看博客测试:进入帖子详情页,确保内容正确显示。

    • 评论测试:输入评论并提交,检查是否成功添加到页面。

    • 点赞测试:点击点赞按钮,确认点赞数增加。

执行方式

  • RunTest.py 中调用 Detail 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ECclass Detail:"""页面详情测试类,包含私信、帖子、评论、点赞等功能的测试"""driver = ''url = ''def __init__(self):"""初始化 WebDriver 并访问指定 URL"""self.driver = Driver.driverself.url = 'http://127.0.0.1:9580/index.html'self.driver.get(self.url)# 等待页面关键元素加载WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong')))# 点击文章进入详情页self.driver.find_element(By.CSS_SELECTOR,'#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong').click()def Private_Message(self):"""测试私信发送功能"""WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#btn_details_send_message')))self.driver.find_element(By.CSS_SELECTOR,'#btn_details_send_message').click()# 等待私信弹窗出现WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'#index_message_modal > div > div > div.modal-header > h5')))assert self.driver.find_element(By.CSS_SELECTOR,'#index_message_modal > div > div > div.modal-header > h5').text == '发送站内信'# 发送内容并提交self.driver.find_element(By.CSS_SELECTOR,'#index_message_receive_content').send_keys('1')self.driver.find_element(By.CSS_SELECTOR,'#btn_index_send_message').click()# 等待发送成功的提示WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div')))# assert '成功' in self.driver.find_element(By.CSS_SELECTOR,'body > div.jq-toast-wrap.bottom-right > div').textdef Post(self):"""测试帖子内容是否正确加载"""WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#details_article_content > p')))WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#details_article_content_title')))def Comment(self):"""测试评论功能"""WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'#article_details_reply > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre')))# 滚动到评论框self.driver.execute_script("arguments[0].scrollIntoView();", self.driver.find_element(By.CSS_SELECTOR,'#article_details_reply > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre'))time.sleep(0.5) # 等待滚动完成self.driver.find_element(By.CSS_SELECTOR,'#details_btn_article_reply > span').click()# 确认评论成功提示WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')))assert '提示' in self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div').textdef Likes(self):"""测试点赞功能"""WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'#details_article_likeCount')))old = int(self.driver.find_element(By.CSS_SELECTOR,'#details_article_likeCount').text)# 点击点赞按钮self.driver.find_element(By.CSS_SELECTOR,'#details_btn_like_count').click()# 等待点赞成功提示WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div > h2')))# 验证点赞数是否增加assert old + 1 == int(self.driver.find_element(By.CSS_SELECTOR,'#details_article_likeCount').text)def test_switch_section(self):"""测试不同版块的切换功能"""try:# 等待“最新回复”板块加载,确保初始状态正确WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复")except:pass# 忽略异常,继续执行# 断言当前版块为“最新回复”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"# 切换到首页WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()try:# 等待首页加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页")except:pass# 忽略异常# 断言当前版块为“首页”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'# 切换到“Java”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()try:# 等待“Java”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java")except:pass# 断言当前版块为“Java”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'# 切换到“C++”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()try:# 等待“C++”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++")except:pass# 断言当前版块为“C++”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'# 切换到“MySQL”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()try:# 等待“MySQL”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL")except:pass# 断言当前版块为“MySQL”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'def test_search_input(self):"""测试搜索框输入功能"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(123)# 断言输入的值是否正确assert self.driver.find_element(By.CSS_SELECTOR,"body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute("value") == '123'def test_toggle_day_night_mode(self):"""测试日间/夜间模式切换"""WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg')))# 断言初始模式为日间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'# 切换到夜间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg')))# 断言模式已切换为夜间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'# 切换回日间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()def test_message_button(self):"""测试消息按钮是否可点击并弹出消息面板"""WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')def test_user_profile(self):"""测试用户个人信息是否正确显示"""self.driver.fullscreen_window()WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

首页自动化测试(HomePage.py)

测试目标

  • 确保首页的基本交互功能正常,包括查看帖子列表、切换主题、搜索等。

测试步骤

  1. 创建 HomePage.py,引入 Utils.py 及相关依赖。

  2. 定义 HomePage 类,管理首页的测试用例。

  3. 实现以下测试方法:

    • 博客列表测试:检查帖子列表是否正确加载。

    • 搜索测试:输入关键词并验证搜索结果是否符合预期。

    • 日夜模式切换测试:切换日间/夜间模式,并验证切换效果。

执行方式

  • RunTest.py 中调用 HomePage 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ECclass HomePage:driver = ''url = ''def __init__(self):# 初始化URL和driverself.url = 'http://127.0.0.1:9580/index.html'self.driver = Driver.driverself.driver.get(self.url)def Button(self):# 等待"发新贴"按钮可点击,并点击它WebDriverWait(self.driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post')))self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post').click()# 验证页面是否跳转到“发新贴”WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2')))assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '发新贴'def List(self):# 等待第一个帖子可点击,并点击它WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong')))self.driver.find_element(By.CSS_SELECTOR,'#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong').click()# 验证页面是否跳转到“最新回复”区域WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3')))assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == '最新回复'def test_switch_section(self):"""测试不同版块的切换功能"""try:# 等待“最新回复”板块加载,确保初始状态正确WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复")except:pass  # 忽略异常,继续执行# 断言当前版块为“最新回复”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"# 切换到首页WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()try:# 等待首页加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页")except:pass  # 忽略异常# 断言当前版块为“首页”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'# 切换到“Java”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()try:# 等待“Java”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java")except:pass# 断言当前版块为“Java”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'# 切换到“C++”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()try:# 等待“C++”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++")except:pass# 断言当前版块为“C++”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'# 切换到“MySQL”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()try:# 等待“MySQL”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL")except:pass# 断言当前版块为“MySQL”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'def test_search_input(self):"""测试搜索框输入功能"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(123)# 断言输入的值是否正确assert self.driver.find_element(By.CSS_SELECTOR,"body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute("value") == '123'def test_toggle_day_night_mode(self):"""测试日间/夜间模式切换"""WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg')))# 断言初始模式为日间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'# 切换到夜间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg')))# 断言模式已切换为夜间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'# 切换回日间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()def test_message_button(self):"""测试消息按钮是否可点击并弹出消息面板"""WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')def test_user_profile(self):"""测试用户个人信息是否正确显示"""self.driver.fullscreen_window()WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

私信功能自动化测试(PrivateMessage.py)

测试目标

  • 确保私信功能正常,包括查看和发送私信。

测试步骤

  1. 创建 PrivateMessage.py,引入 Utils.py 及相关依赖。

  2. 定义 PrivateMessage 类,管理私信的测试用例。

  3. 实现以下测试方法:

    • 查看私信测试:进入私信列表并点击某条私信,检查内容是否正确显示。

    • 发送私信测试:输入内容并发送,确保私信成功发送。

执行方式

  • RunTest.py 中调用 PrivateMessage 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ECclass PrivateMessage:url = ''driver = ''def __init__(self):self.driver = Driver.driverself.url = 'http://127.0.0.1:9580/index.html'self.driver.get(self.url)WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')def reply(self):# 等待并点击私信列表中的第一条消息WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a')))self.driver.find_element(By.CSS_SELECTOR,'#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a').click()# 等待 "取消回复" 按钮出现并点击WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#index_message_reply_cancel')))self.driver.find_element(By.CSS_SELECTOR,'#index_message_reply_cancel').click()# 再次点击同一条私信,重新进入回复界面WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a')))self.driver.find_element(By.CSS_SELECTOR,'#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a').click()# 等待 "回复" 按钮出现并点击WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, '#btn_index_message_reply')))self.driver.find_element(By.CSS_SELECTOR,'#btn_index_message_reply').click()# 等待回复输入框并输入消息WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#index_message_reply_receive_content')))self.driver.find_element(By.CSS_SELECTOR,'#index_message_reply_receive_content').send_keys(123)# 等待 "发送回复" 按钮出现并点击WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#btn_index_send_message_reply')))self.driver.find_element(By.CSS_SELECTOR, '#btn_index_send_message_reply').click()# 等待并检查是否有成功提示WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div')))assert '成功' in self.driver.find_element(By.CSS_SELECTOR, 'body > div.jq-toast-wrap.bottom-right > div').text

我的帖子自动化测试(MyPost.py)

测试目标

  • 确保“我的帖子”页面功能正常,包括查看、管理已发布的帖子。

测试步骤

  1. 创建 MyPost.py,引入 Utils.py 及相关依赖。

  2. 定义 MyPost 类,管理“我的帖子”页面的测试用例。

  3. 实现以下测试方法:

    • 查看已发布帖子:进入“我的帖子”页面,检查列表是否正确显示。

    • 编辑帖子测试:点击某个帖子进行编辑,检查是否能正常修改并保存。

    • 删除帖子测试:删除某个帖子,并检查列表是否正确更新。

执行方式

  • RunTest.py 中调用 MyPost 类执行测试。

    import time
    from common.Utils import Driver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ECclass MyPost:driver = ''url = ''def __init__(self):# 初始化URL和driver,打开用户首页self.url = 'http://127.0.0.1:9580/index.html'self.driver = Driver.driverself.driver.get(self.url)# 等待页面加载完毕,点击头像进入用户资料页面WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_avatar')))self.driver.find_element(By.CSS_SELECTOR, '#index_nav_avatar').click()# 等待用户资料链接可点击,进入用户资料页面WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#index_user_profile')))self.driver.find_element(By.CSS_SELECTOR,'#index_user_profile').click()def Name(self):# 等待用户昵称加载完成,并验证昵称是否为 'zhangsan'WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#profile_nickname')))# 验证昵称是否正确assert self.driver.find_element(By.CSS_SELECTOR,'#profile_nickname').text == 'zhangsan'def Post(self):# 等待第一个帖子可点击WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#profile_article_body > li:nth-child(1) > div.card.timeline-event-card > div > div > div > div > div.text-truncate > a > strong')))self.driver.find_element(By.CSS_SELECTOR,'#profile_article_body > li:nth-child(1) > div.card.timeline-event-card > div > div > div > div > div.text-truncate > a > strong').click()try:# 等待文章编辑按钮出现,若出现则表示该帖子可以编辑WebDriverWait(self.driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#details_artile_edit')))except:pass# 验证是否可以编辑帖子assert self.driver.find_element(By.CSS_SELECTOR,'#details_artile_edit')def test_switch_section(self):"""测试不同版块的切换功能"""try:# 等待“最新回复”板块加载,确保初始状态正确WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text.strip() == "最新回复")except:pass  # 忽略异常,继续执行# 断言当前版块为“最新回复”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3').text == "最新回复"# 切换到首页WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#nav_board_index > a > span.nav-link-title').click()try:# 等待首页加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == "首页")except:pass  # 忽略异常# 断言当前版块为“首页”assert self.driver.find_element(By.CSS_SELECTOR,'#bit-forum-content > div.page-header.d-print-none > div > div > div > h2').text == '首页'# 切换到“Java”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(2) > a > span.nav-link-title').click()try:# 等待“Java”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "Java")except:pass# 断言当前版块为“Java”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'Java'# 切换到“C++”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(3) > a > span.nav-link-title').click()try:# 等待“C++”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "C++")except:pass# 断言当前版块为“C++”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'C++'# 切换到“MySQL”版块WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title')))self.driver.find_element(By.CSS_SELECTOR, '#topBoardList > li:nth-child(5) > a > span.nav-link-title').click()try:# 等待“MySQL”版块加载WebDriverWait(self.driver, 10).until(lambda driver: driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == "MySQL")except:pass# 断言当前版块为“MySQL”assert self.driver.find_element(By.CSS_SELECTOR, '#article_list_board_title').text == 'MySQL'def test_search_input(self):"""测试搜索框输入功能"""WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input').send_keys(123)# 断言输入的值是否正确assert self.driver.find_element(By.CSS_SELECTOR,"body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input").get_attribute("value") == '123'def test_toggle_day_night_mode(self):"""测试日间/夜间模式切换"""WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg')))# 断言初始模式为日间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-light'# 切换到夜间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg').click()WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg')))# 断言模式已切换为夜间模式assert self.driver.find_element(By.CSS_SELECTOR, 'body').get_attribute("class") == 'theme-dark'# 切换回日间模式self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light > svg').click()def test_message_button(self):"""测试消息按钮是否可点击并弹出消息面板"""WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg')))self.driver.find_element(By.CSS_SELECTOR,'body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg').click()assert self.driver.find_element(By.CSS_SELECTOR, '#offcanvasEndLabel')def test_user_profile(self):"""测试用户个人信息是否正确显示"""self.driver.fullscreen_window()WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_nickname')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_nickname').text == 'zhangsan'WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#index_nav_name_sub')))assert self.driver.find_element(By.CSS_SELECTOR, '#index_nav_name_sub').text == '普通用户'
    

运行所有测试(RunTest.py)

测试目标

  • 依次执行所有测试,并确保最终关闭 WebDriver。

测试步骤

  1. 创建 RunTest.py,引入 Utils.py 及所有测试文件。

  2. 依次调用各个测试类的测试方法。

  3. 统一管理 WebDriver 的初始化和退出。

执行方式

  • 直接运行 RunTest.py,所有测试会自动执行。

import time
from common.Utils import Driver
from cases import Login,PersonalHomepage,Edit,Detail,PrivateMessage,HomePage,MyPost,Register# 运行登录相关的测试
def run_Login_tests():"""执行所有登录相关的测试"""login = Login.Login()  # 只实例化一次,避免重复创建对象login.login_suc_test1()login.login_suc_test2()login.test_login_empty_username_empty_password()login.test_login_empty_username_valid_password()login.test_login_empty_username_invalid_password()login.test_login_invalid_username_empty_password()login.test_login_valid_username_empty_password()login.test_login_valid_username_invalid_password()login.test_login_invalid_username_valid_password()login.test_login_invalid_username_invalid_password()# 运行个人主页相关的测试
def run_PersonalHomepage_tests():"""执行所有个人主页相关的测试"""personal_home = PersonalHomepage.PersonalHomepage()personal_home.test_switch_section()personal_home.test_search_input()personal_home.test_toggle_day_night_mode()personal_home.test_message_button()personal_home.test_user_profile()personal_home.test_change_avatar()personal_home.test_nickname_field()personal_home.test_email_field()personal_home.test_phone_number_field()personal_home.test_bio_field()personal_home.test_change_password()# 运行帖子编辑相关的测试
def run_Edit_tests():"""执行所有帖子编辑相关的测试"""edit = Edit.Edit()edit.Content_Box()edit.Title_Bar()edit.Plate_Selection()edit.Release()edit.test_switch_section()edit.test_search_input()edit.test_toggle_day_night_mode()edit.test_message_button()edit.test_user_profile()# 运行帖子详情相关的测试
def run_Detail_tests():"""执行所有帖子详情页面相关的测试"""detail = Detail.Detail()detail.Private_Message()detail.Post()detail.Comment()detail.Likes()detail.test_switch_section()detail.test_search_input()detail.test_toggle_day_night_mode()detail.test_message_button()detail.test_user_profile()# 运行私信功能的测试
def run_PrivateMessage_tests():"""执行私信功能的测试"""private_msg = PrivateMessage.PrivateMessage()private_msg.reply()# 运行首页相关的测试
def run_HomePage_tests():"""执行所有首页相关的测试"""home = HomePage.HomePage()home.Button()home.List()home.test_switch_section()home.test_search_input()home.test_toggle_day_night_mode()home.test_message_button()home.test_user_profile()# 运行“我的帖子”相关的测试
def run_MyPost_test():"""执行所有‘我的帖子’相关的测试"""my_post = MyPost.MyPost()my_post.Name()my_post.Post()my_post.test_switch_section()my_post.test_search_input()my_post.test_toggle_day_night_mode()my_post.test_message_button()my_post.test_user_profile()# 运行注册功能的测试
def run_Register_test():"""执行所有注册功能的测试"""register = Register.Register()register.test_valid_inputs_agree_terms()register.test_valid_username_empty_others_disagree_terms()register.test_empty_username_valid_nickname_mixed_passwords_disagree_terms()register.test_empty_username_nickname_valid_password_agree_terms()register.test_valid_inputs_missing_confirm_password_disagree_terms()register.test_valid_username_empty_nickname_password_confirmed_agree_terms()register.test_invalid_inputs_disagree_terms()# 运行所有测试
def run_all_tests():"""依次执行所有的测试,并在结束后关闭 WebDriver"""try:run_Login_tests()run_PersonalHomepage_tests()run_Edit_tests()run_Detail_tests()run_PrivateMessage_tests()run_HomePage_tests()run_MyPost_test()run_Register_test()except Exception as e:print(f"错误发生: {e}")  # 捕获异常,避免测试中断finally:Driver.driver.quit()  # 测试完成后关闭 WebDriver# 主函数
if __name__ == '__main__':run_all_tests()
可优化部分
  • 菜单反复调用测试,可以专门写一个对菜单功能测试的函数
  • 注释没有统一格式
  • 好多地方截图没补上去

前面几个像登录测试注册那种选择多的是用 allpairs搞定的

3.各函数作用总览

Utils.py
  • __init__(self): 初始化 WebDriver。

  • getScreenShot(self): 截取当前页面截图并保存。


Login.py
  • __init__(self): 初始化 WebDriver 并打开登录页面。

  • _login(self, username, password): 输入用户名和密码,执行登录操作。

  • _verify_login_success(self): 验证用户是否成功登录。

  • login_suc_test1(self): 测试正确的用户名和密码能否成功登录。

  • login_suc_test2(self): 测试另一个正确的用户名和密码登录是否成功。

  • test_login_empty_username_empty_password(self): 测试用户名和密码都为空的情况。

  • test_login_valid_username_empty_password(self): 测试用户名正确但密码为空的情况。

  • test_login_invalid_username_valid_password(self): 测试用户名错误但密码正确的情况。


Register.py
  • __init__(self): 初始化 WebDriver 并打开注册页面。

  • test_valid_inputs_agree_terms(self): 测试所有输入正确且同意条款的情况。

  • test_valid_username_empty_others_disagree_terms(self): 测试仅填写用户名,其他字段为空且不同意条款的情况。

  • test_empty_username_valid_nickname_mixed_passwords_disagree_terms(self): 测试用户名为空、昵称有效但密码不匹配的情况。

  • test_empty_username_nickname_valid_password_agree_terms(self): 测试用户名和昵称为空,密码正确且同意条款的情况。


Edit.py
  • __init__(self): 初始化 WebDriver 并进入编辑页面。

  • Content_Box(self): 检查博客内容输入框是否正确加载。

  • Title_Bar(self): 输入标题并验证输入是否正确。

  • Plate_Selection(self): 选择不同的板块,并检查选择结果是否正确。

  • Release(self): 点击发布按钮,确保博客成功发布。

  • test_switch_section(self): 测试博客发布后页面是否能正确跳转到博客列表。


Detail.py
  • __init__(self): 初始化 WebDriver 并打开博客详情页。

  • Private_Message(self): 测试私信功能,确保发送私信成功。

  • Post(self): 测试博客内容是否正确显示。

  • Comment(self): 测试用户能否成功发表评论。

  • Likes(self): 测试点赞按钮是否正常工作。


PersonalHomepage.py
  • __init__(self): 初始化 WebDriver 并打开个人主页。

  • test_change_avatar(self): 测试头像修改功能。

  • test_nickname_field(self): 测试修改昵称并检查是否保存成功。

  • test_email_field(self): 测试修改邮箱并验证更新后的信息。

  • test_phone_number_field(self): 测试修改手机号功能。

  • test_bio_field(self): 测试个人简介的编辑与保存功能。

  • test_change_password(self): 测试修改密码,并使用新密码重新登录。


PrivateMessage.py
  • __init__(self): 初始化 WebDriver 并进入私信页面。

  • reply(self): 测试私信回复功能,确保发送成功。


HomePage.py
  • __init__(self): 初始化 WebDriver 并打开首页。

  • Button(self): 测试首页“发新贴”按钮是否能正常跳转到编辑页面。

  • List(self): 测试博客列表是否正确加载,并可点击查看详情。

  • test_search_input(self): 测试搜索框输入内容,并检查搜索结果。

  • test_toggle_day_night_mode(self): 测试日间/夜间模式的切换功能。


MyPost.py
  • __init__(self): 初始化 WebDriver 并进入“我的帖子”页面。

  • Name(self): 检查用户名是否正确显示。

  • Post(self): 测试点击某个帖子,确保页面跳转正常。


Test.py
  • run_all_tests(): 运行所有测试用例,确保所有功能正常执行。

4.测试环境与执行方式

运行环境
  • Python 版本:3.13

  • 依赖库:selenium

  • 浏览器:Microsoft Edge   版本 134.0.3124.68 (正式版本) (64 位)

  • WebDriver:msedgedriver 需正确配置

运行方式
  1. 安装 selenium 依赖:

    pip install selenium
  2. 确保 msedgedriver 已正确安装。

  3. 运行 RunCases.py 以执行完整的测试流程:

    python RunCases.py
结果验证
  • 所有测试案例执行完成后,测试日志将会记录各个测试步骤的执行结果。

  • 关键页面截图将在 images/ 目录中保存,以供参考。

  • 若有测试失败,请参考日志进行问题排查,并根据错误信息调整代码或系统设置。

 5.自动化框架特点与亮点

特点

该自动化测试框架结合了 Selenium WebDriver自定义测试模块,能够高效地验证论坛的各项功能。测试用例覆盖了从 用户注册、登录、发布帖子、浏览帖子、私信交互、个人信息管理页面跳转 等多个关键场景。

所有测试用例都封装为独立的函数,目标明确,执行步骤清晰,便于维护和扩展。自动化测试可以反复执行,提高测试覆盖率的同时,也减少了人工干预,提高测试效率。

此外,该框架还利用 Selenium WebDriver 的等待机制,确保页面元素完全加载后再执行操作,减少因页面加载缓慢导致的测试失败。同时,截图功能 使得测试过程可追踪,异常情况可视化,便于快速定位问题。


亮点

1. 统一的 WebDriver 管理
  • 采用 Driver 类 统一管理 WebDriver 实例,避免每个测试用例重复创建 WebDriver,减少资源浪费,提高执行效率。

  • 通过 单例模式 复用 WebDriver,在多个测试用例间共享浏览器会话,减少重复初始化的开销。

2. 功能清晰的测试用例
  • 每个测试用例都封装成独立的函数,清晰定义测试目标验证条件,增强了代码的可读性和可维护性。

  • 测试覆盖了帖子网站的核心功能,包括:

    • 用户注册与登录:模拟不同用户的登录情况,验证账号验证逻辑。

    • 帖子管理:测试帖子的发布、编辑、删除等功能,确保用户可以正常管理文章。

    • 交互功能:测试评论、私信、点赞等用户互动功能,确保社交体验顺畅。

3. 高效的等待机制
  • 结合 显式等待 (WebDriverWait)隐式等待,有效解决页面加载速度和测试执行速度不一致的问题。

  • 避免因为页面元素未完全渲染而导致的 NoSuchElementExceptionElementNotInteractableException,提高测试稳定性和可靠性。

4. 自动截图功能
  • 每个测试用例执行时,自动截图关键操作,便于在测试失败时进行问题追踪和回溯。

  • 结合 日志记录功能,在测试失败时保存错误信息,帮助开发人员快速定位和修复问题。

5. 自动化的重复执行
  • 该框架可以轻松地多次执行同一组测试,适用于回归测试稳定性测试,确保系统在不同时间段或高并发情况下依然表现正常。

  • 结合 定时任务 (cron jobs) 或 CI/CD 流水线,可实现每日自动化回归测试,保证系统功能始终可用。

6. 页面元素检查与交互验证
  • 通过 WebDriver 的 presence_of_element_located()visibility_of_element_located() 方法,确保所有关键元素在交互前正确加载

  • 检测页面上的按钮、表单、文本框等控件是否可点击、可输入、可提交,防止界面交互异常。

 6.性能测试

使用 Apache JMeter论坛系统 进行性能测试,模拟不同用户操作下的系统响应情况,确保系统能够在高并发访问下稳定运行。

测试目标
  • 评估 用户登录、浏览帖子、查看详情、发表帖子 等关键功能的响应时间和吞吐量

  • 通过 并发请求模拟大量用户访问,检查系统的稳定性

  • 记录并分析 响应时间、线程活动情况、事务处理速度,优化系统性能

测试步骤
  1. HTTP 请求默认值设置:定义论坛系统的基本 URL,简化后续请求配置

  2. HTTP 头信息管理器:设置请求头,模拟真实浏览器访问

  3. 自定义变量:定义通用变量,便于动态参数传递

  4. 账号密码 CSV 数据管理:使用 CSV 文件导入用户信息,模拟多个用户登录

  5. HTTP Cookie 管理器:存储会话信息,确保用户身份在请求间保持一致

  6. 执行测试事务

    • 用户登录:模拟用户输入账号密码并登录

    • 用户信息:获取用户的个人资料

    • 列表页:访问帖子列表,测试加载速度

    • 详情页:查看特定帖子内容,测试响应时间

    • 添加帖子:模拟用户发布新帖,验证提交效率

  7. 结果分析

    • 查看结果树:检查每个请求的详细响应数据

    • 聚合报告:统计请求数量、平均响应时间、吞吐量等指标

    • JMeter 监控插件

      • Active Threads Over Time:观察系统在不同时间点的并发用户数

      • Response Times Over Time:分析不同时间点的服务器响应时间

      • Transactions per Second:统计系统每秒钟处理的事务数

 

列表那异常爆表了啊

应该是那一页数据太多的问题

性能测试还在学,这就测的大概,看个乐 

8.完整测试代码连接 

GitHub - bbppooii/Automated-testing-of-forum-system

bbppooi/论坛系统自动化测试


http://www.mrgr.cn/news/95899.html

相关文章:

  • 给Web开发者的HarmonyOS指南02-布局样式
  • Linux 挂载磁盘操作指南
  • 代理记账的第三个十年
  • 【WebGIS教程2】Web服务与地理空间服务解析
  • 攻防世界-web-1
  • html方法收集
  • Spring Boot 三层架构【清晰易懂】
  • npm常用的命令
  • DM9162使用记录
  • 人工智能通识速览
  • 漏洞挖掘---锐明Crocus系统Service.do接口任意文件读取
  • VSCode中使用Markdown以及Mermaid实现流程图和甘特图等效果
  • 深度学习入门之基于MLP的加州房价预测模型
  • 电机倍频曲线的一些奇异特性-原因分析及应用
  • 【Hugging Face 开源库】Diffusers 库 ——扩散模型
  • esp32s3聊天机器人(三)
  • QTcpSocket多线程连接慢问题
  • Tekton系列之实践篇-从触发到完成的完整执行过程
  • 蓝桥杯高频考点——搜索(含C++源码)
  • C++学习:六个月从基础到就业——C++基础语法回顾:指针与引用基础